@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.mjs
CHANGED
|
@@ -23,7 +23,10 @@ var SUPPORTED_EXTENSIONS = [
|
|
|
23
23
|
".md",
|
|
24
24
|
".txt",
|
|
25
25
|
".rst",
|
|
26
|
-
".adoc"
|
|
26
|
+
".adoc",
|
|
27
|
+
".html",
|
|
28
|
+
".htm",
|
|
29
|
+
".toml"
|
|
27
30
|
];
|
|
28
31
|
|
|
29
32
|
// src/shared/cli/functions/parse-args.function.ts
|
|
@@ -659,6 +662,319 @@ function computeDirectoryLevel(filePath, basePath) {
|
|
|
659
662
|
return Math.min(depth + 1, MAX_LEVEL);
|
|
660
663
|
}
|
|
661
664
|
|
|
665
|
+
// src/shared/content-splitter/constants/content-type-maps.constant.ts
|
|
666
|
+
var HINT_FORMAT_MAP = {
|
|
667
|
+
markdown: "markdown",
|
|
668
|
+
"text/markdown": "markdown",
|
|
669
|
+
md: "markdown",
|
|
670
|
+
html: "html",
|
|
671
|
+
"text/html": "html",
|
|
672
|
+
toml: "toml",
|
|
673
|
+
"application/toml": "toml",
|
|
674
|
+
"text/toml": "toml",
|
|
675
|
+
"text/x-toml": "toml"
|
|
676
|
+
};
|
|
677
|
+
var EXTENSION_FORMAT_MAP = {
|
|
678
|
+
md: "markdown",
|
|
679
|
+
markdown: "markdown",
|
|
680
|
+
html: "html",
|
|
681
|
+
htm: "html",
|
|
682
|
+
toml: "toml"
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
// src/shared/content-splitter/functions/detect-content-type.function.ts
|
|
686
|
+
function detectContentType(content, typeHint, filePath) {
|
|
687
|
+
const hinted = typeHint && HINT_FORMAT_MAP[typeHint.toLowerCase()];
|
|
688
|
+
if (hinted) return hinted;
|
|
689
|
+
const extension = filePath?.split(".").pop()?.toLowerCase();
|
|
690
|
+
const extMatch = extension && EXTENSION_FORMAT_MAP[extension];
|
|
691
|
+
if (extMatch) return extMatch;
|
|
692
|
+
return sniffContentType(content);
|
|
693
|
+
}
|
|
694
|
+
function sniffContentType(content) {
|
|
695
|
+
const trimmed = content.trimStart();
|
|
696
|
+
if (/^<!DOCTYPE/i.test(trimmed) || /^<html/i.test(trimmed)) {
|
|
697
|
+
return "html";
|
|
698
|
+
}
|
|
699
|
+
if (trimmed.startsWith("[") && trimmed.includes("=")) {
|
|
700
|
+
return "toml";
|
|
701
|
+
}
|
|
702
|
+
return "plain-text";
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// src/shared/content-splitter/classes/heading-parent-tracker.class.ts
|
|
706
|
+
var HeadingParentTracker = class {
|
|
707
|
+
stack = [];
|
|
708
|
+
/**
|
|
709
|
+
* Resolves the parent index for a heading at `level`
|
|
710
|
+
* appearing at output position `index`, then records the
|
|
711
|
+
* heading so subsequent, deeper headings can nest under it.
|
|
712
|
+
*
|
|
713
|
+
* @param level - heading depth, shallower is smaller
|
|
714
|
+
* @param index - position of this heading in the output
|
|
715
|
+
* sections array
|
|
716
|
+
* @returns the parent's output index, or `null` when the
|
|
717
|
+
* heading is at the root
|
|
718
|
+
*/
|
|
719
|
+
resolve(level, index) {
|
|
720
|
+
while (this.stack.length > 0 && this.stack[this.stack.length - 1].level >= level) {
|
|
721
|
+
this.stack.pop();
|
|
722
|
+
}
|
|
723
|
+
const parentIndex = this.stack.length > 0 ? this.stack[this.stack.length - 1].index : null;
|
|
724
|
+
this.stack.push({ level, index });
|
|
725
|
+
return parentIndex;
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
// src/shared/content-splitter/functions/push-content-section.function.ts
|
|
730
|
+
function pushContentSection(sections, tracker, content, title, level) {
|
|
731
|
+
if (level === void 0) {
|
|
732
|
+
sections.push({ content, parentIndex: null });
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
sections.push({
|
|
736
|
+
title,
|
|
737
|
+
level,
|
|
738
|
+
content,
|
|
739
|
+
parentIndex: tracker.resolve(level, sections.length)
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// src/shared/content-splitter/functions/flush-markdown-draft.function.ts
|
|
744
|
+
function flushMarkdownDraft(draft, sections, tracker) {
|
|
745
|
+
const body = draft.lines.join("\n").trimEnd();
|
|
746
|
+
if (draft.title === void 0 && body.length === 0) return;
|
|
747
|
+
pushContentSection(
|
|
748
|
+
sections,
|
|
749
|
+
tracker,
|
|
750
|
+
body,
|
|
751
|
+
draft.title,
|
|
752
|
+
draft.level
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// src/shared/content-splitter/functions/split-markdown.function.ts
|
|
757
|
+
var HEADING_PATTERN = /^(#{1,6})\s+(.+)$/;
|
|
758
|
+
function splitMarkdown(content) {
|
|
759
|
+
const sections = [];
|
|
760
|
+
const tracker = new HeadingParentTracker();
|
|
761
|
+
let draft = { lines: [] };
|
|
762
|
+
let inCodeBlock = false;
|
|
763
|
+
for (const line of content.split("\n")) {
|
|
764
|
+
if (line.startsWith("```") || line.startsWith("~~~")) {
|
|
765
|
+
inCodeBlock = !inCodeBlock;
|
|
766
|
+
draft.lines.push(line);
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
769
|
+
const heading = inCodeBlock ? null : HEADING_PATTERN.exec(line);
|
|
770
|
+
if (heading) {
|
|
771
|
+
flushMarkdownDraft(draft, sections, tracker);
|
|
772
|
+
draft = {
|
|
773
|
+
title: heading[2].trim(),
|
|
774
|
+
level: heading[1].length,
|
|
775
|
+
lines: []
|
|
776
|
+
};
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
draft.lines.push(line);
|
|
780
|
+
}
|
|
781
|
+
flushMarkdownDraft(draft, sections, tracker);
|
|
782
|
+
return sections.length > 0 ? sections : [{ content: content.trimEnd(), parentIndex: null }];
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// src/shared/content-splitter/functions/split-html.function.ts
|
|
786
|
+
var HEADING_PATTERN2 = /<h([1-6])[^>]*>(.*?)<\/h\1>/gi;
|
|
787
|
+
function splitHtml(content) {
|
|
788
|
+
const matches = [...content.matchAll(HEADING_PATTERN2)];
|
|
789
|
+
if (matches.length === 0) {
|
|
790
|
+
return [{ content: content.trimEnd(), parentIndex: null }];
|
|
791
|
+
}
|
|
792
|
+
const sections = [];
|
|
793
|
+
const tracker = new HeadingParentTracker();
|
|
794
|
+
const firstIndex = matches[0].index;
|
|
795
|
+
const preamble = content.slice(0, firstIndex).trimEnd();
|
|
796
|
+
if (preamble.length > 0) {
|
|
797
|
+
pushContentSection(sections, tracker, preamble);
|
|
798
|
+
}
|
|
799
|
+
matches.forEach((match, i) => {
|
|
800
|
+
const start = match.index + match[0].length;
|
|
801
|
+
const end = matches[i + 1]?.index ?? content.length;
|
|
802
|
+
pushContentSection(
|
|
803
|
+
sections,
|
|
804
|
+
tracker,
|
|
805
|
+
content.slice(start, end).trimEnd(),
|
|
806
|
+
match[2].trim(),
|
|
807
|
+
Number(match[1])
|
|
808
|
+
);
|
|
809
|
+
});
|
|
810
|
+
return sections;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// src/shared/content-splitter/functions/flush-toml-draft.function.ts
|
|
814
|
+
function flushTomlDraft(draft, sections, pathIndex) {
|
|
815
|
+
const body = draft.lines.join("\n").trimEnd();
|
|
816
|
+
if (draft.title === void 0 && body.length === 0) return;
|
|
817
|
+
if (draft.title === void 0) {
|
|
818
|
+
sections.push({ content: body, parentIndex: null });
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
const path = draft.path ?? draft.title;
|
|
822
|
+
sections.push({
|
|
823
|
+
title: draft.title,
|
|
824
|
+
content: body,
|
|
825
|
+
parentIndex: resolveParentIndex(path, pathIndex)
|
|
826
|
+
});
|
|
827
|
+
pathIndex.set(path, sections.length - 1);
|
|
828
|
+
}
|
|
829
|
+
function resolveParentIndex(path, pathIndex) {
|
|
830
|
+
if (/^["']/.test(path)) return null;
|
|
831
|
+
const segments = path.split(".");
|
|
832
|
+
segments.pop();
|
|
833
|
+
if (segments.length === 0) return null;
|
|
834
|
+
return pathIndex.get(segments.join(".")) ?? null;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// src/shared/content-splitter/functions/split-toml.function.ts
|
|
838
|
+
var HEADER_PATTERN = /^\[([^\]]+)\]\s*$/;
|
|
839
|
+
var QUOTED_PATTERN = /^(["'])(.*)\1$/;
|
|
840
|
+
function splitToml(content) {
|
|
841
|
+
const sections = [];
|
|
842
|
+
const pathIndex = /* @__PURE__ */ new Map();
|
|
843
|
+
let draft = { lines: [] };
|
|
844
|
+
for (const line of content.split("\n")) {
|
|
845
|
+
const header = HEADER_PATTERN.exec(line);
|
|
846
|
+
if (header) {
|
|
847
|
+
flushTomlDraft(draft, sections, pathIndex);
|
|
848
|
+
draft = { ...parseHeader(header[1]), lines: [] };
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
draft.lines.push(line);
|
|
852
|
+
}
|
|
853
|
+
flushTomlDraft(draft, sections, pathIndex);
|
|
854
|
+
return sections.length > 0 ? sections : [{ content: content.trimEnd(), parentIndex: null }];
|
|
855
|
+
}
|
|
856
|
+
function parseHeader(inner) {
|
|
857
|
+
const trimmed = inner.trim();
|
|
858
|
+
const quoted = QUOTED_PATTERN.exec(trimmed);
|
|
859
|
+
return quoted ? { title: quoted[2], path: trimmed } : { title: trimmed, path: trimmed };
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// src/shared/content-splitter/functions/split-plain-text.function.ts
|
|
863
|
+
function splitPlainText(content) {
|
|
864
|
+
return [{ content, parentIndex: null }];
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// src/shared/content-splitter/constants/split-strategy-map.constant.ts
|
|
868
|
+
var SPLIT_STRATEGY_MAP = {
|
|
869
|
+
markdown: splitMarkdown,
|
|
870
|
+
html: splitHtml,
|
|
871
|
+
toml: splitToml,
|
|
872
|
+
"plain-text": splitPlainText
|
|
873
|
+
};
|
|
874
|
+
|
|
875
|
+
// src/shared/content-splitter/functions/split-content.function.ts
|
|
876
|
+
function splitContent(content, typeHint, filePath) {
|
|
877
|
+
const format = detectContentType(content, typeHint, filePath);
|
|
878
|
+
return {
|
|
879
|
+
format,
|
|
880
|
+
sections: SPLIT_STRATEGY_MAP[format](content)
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// src/shared/content-splitter/functions/resolve-parent-ids.function.ts
|
|
885
|
+
function resolveParentIds(sections, kbids) {
|
|
886
|
+
return sections.map(
|
|
887
|
+
(section) => section.parentIndex === null ? null : kbids[section.parentIndex]
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// src/shared/cli/functions/map-add-section-result.function.ts
|
|
892
|
+
function mapAddSectionResult(result, path, size, sectionType) {
|
|
893
|
+
return {
|
|
894
|
+
kbid: result.items[0] ?? "",
|
|
895
|
+
indexed_terms_count: 0,
|
|
896
|
+
type: sectionType,
|
|
897
|
+
path,
|
|
898
|
+
size,
|
|
899
|
+
skipped: false,
|
|
900
|
+
superseded: result.superseded ?? null,
|
|
901
|
+
warnings: result.warnings ?? [],
|
|
902
|
+
near_duplicates: result.near_duplicates ?? []
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// src/shared/cli/functions/learn-structured-document.function.ts
|
|
907
|
+
import { basename as basename2 } from "node:path";
|
|
908
|
+
async function learnStructuredDocument(client, options, path, splitResult, sourcePath) {
|
|
909
|
+
const { sections } = splitResult;
|
|
910
|
+
const firstTitled = sections.find((s) => s.title !== void 0);
|
|
911
|
+
const docTitle = firstTitled?.title ?? basename2(path);
|
|
912
|
+
const kbids = [];
|
|
913
|
+
const results = [];
|
|
914
|
+
for (const section of sections) {
|
|
915
|
+
const [parent] = resolveParentIds([section], kbids);
|
|
916
|
+
const added = await client.addSection({
|
|
917
|
+
sectionType: "text",
|
|
918
|
+
content: section.content,
|
|
919
|
+
title: section.title,
|
|
920
|
+
description: options.description,
|
|
921
|
+
docid: path,
|
|
922
|
+
tags: options.tags,
|
|
923
|
+
replace: options.replace,
|
|
924
|
+
sourcePath,
|
|
925
|
+
level: section.level,
|
|
926
|
+
parent: parent ?? void 0
|
|
927
|
+
});
|
|
928
|
+
kbids.push(added.items[0] ?? "");
|
|
929
|
+
results.push(
|
|
930
|
+
mapAddSectionResult(
|
|
931
|
+
added,
|
|
932
|
+
path,
|
|
933
|
+
section.content.length,
|
|
934
|
+
"text"
|
|
935
|
+
)
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
await client.groupSections(docTitle, kbids);
|
|
939
|
+
return results;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// src/shared/cli/functions/learn-target-content.function.ts
|
|
943
|
+
async function learnTargetContent(client, options, path, content, sourcePath, level) {
|
|
944
|
+
if (!options.title) {
|
|
945
|
+
const isStdin = path === "-";
|
|
946
|
+
const split = splitContent(
|
|
947
|
+
content,
|
|
948
|
+
isStdin ? "markdown" : void 0,
|
|
949
|
+
isStdin ? void 0 : path
|
|
950
|
+
);
|
|
951
|
+
const hasTitled = split.sections.some(
|
|
952
|
+
(s) => s.title !== void 0
|
|
953
|
+
);
|
|
954
|
+
if (split.sections.length >= 2 && hasTitled) {
|
|
955
|
+
return learnStructuredDocument(
|
|
956
|
+
client,
|
|
957
|
+
options,
|
|
958
|
+
path,
|
|
959
|
+
split,
|
|
960
|
+
sourcePath
|
|
961
|
+
);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
const result = await client.addSection({
|
|
965
|
+
sectionType: "text",
|
|
966
|
+
content,
|
|
967
|
+
title: options.title,
|
|
968
|
+
description: options.description,
|
|
969
|
+
docid: options.docid,
|
|
970
|
+
tags: options.tags,
|
|
971
|
+
replace: options.replace,
|
|
972
|
+
sourcePath,
|
|
973
|
+
level
|
|
974
|
+
});
|
|
975
|
+
return [mapAddSectionResult(result, path, content.length, "text")];
|
|
976
|
+
}
|
|
977
|
+
|
|
662
978
|
// src/shared/cli/functions/run-learn.function.ts
|
|
663
979
|
async function runLearn(client, options, io) {
|
|
664
980
|
log(
|
|
@@ -673,37 +989,30 @@ async function runLearn(client, options, io) {
|
|
|
673
989
|
if (stdinConsumed) continue;
|
|
674
990
|
stdinConsumed = true;
|
|
675
991
|
const content = await readStdin();
|
|
676
|
-
const result = await client.addSection({
|
|
677
|
-
sectionType: "text",
|
|
678
|
-
content,
|
|
679
|
-
title: options.title,
|
|
680
|
-
description: options.description,
|
|
681
|
-
docid: options.docid,
|
|
682
|
-
tags: options.tags,
|
|
683
|
-
replace: options.replace,
|
|
684
|
-
level: options.level
|
|
685
|
-
});
|
|
686
992
|
results.push(
|
|
687
|
-
|
|
993
|
+
...await learnTargetContent(
|
|
994
|
+
client,
|
|
995
|
+
options,
|
|
996
|
+
"-",
|
|
997
|
+
content,
|
|
998
|
+
void 0,
|
|
999
|
+
options.level
|
|
1000
|
+
)
|
|
688
1001
|
);
|
|
689
1002
|
continue;
|
|
690
1003
|
}
|
|
691
1004
|
const files = collectFiles(target);
|
|
692
1005
|
for (const file of files) {
|
|
693
1006
|
const content = readFileSync(file, "utf-8");
|
|
694
|
-
const result = await client.addSection({
|
|
695
|
-
sectionType: "text",
|
|
696
|
-
content,
|
|
697
|
-
title: options.title,
|
|
698
|
-
description: options.description,
|
|
699
|
-
docid: options.docid,
|
|
700
|
-
tags: options.tags,
|
|
701
|
-
replace: options.replace,
|
|
702
|
-
sourcePath: file,
|
|
703
|
-
level: options.level ?? computeDirectoryLevel(file, target)
|
|
704
|
-
});
|
|
705
1007
|
results.push(
|
|
706
|
-
|
|
1008
|
+
...await learnTargetContent(
|
|
1009
|
+
client,
|
|
1010
|
+
options,
|
|
1011
|
+
file,
|
|
1012
|
+
content,
|
|
1013
|
+
file,
|
|
1014
|
+
options.level ?? computeDirectoryLevel(file, target)
|
|
1015
|
+
)
|
|
707
1016
|
);
|
|
708
1017
|
}
|
|
709
1018
|
}
|
|
@@ -713,19 +1022,6 @@ async function runLearn(client, options, io) {
|
|
|
713
1022
|
);
|
|
714
1023
|
return results;
|
|
715
1024
|
}
|
|
716
|
-
function mapAddSectionResult(result, path, size, sectionType) {
|
|
717
|
-
return {
|
|
718
|
-
kbid: result.items[0] ?? "",
|
|
719
|
-
indexed_terms_count: 0,
|
|
720
|
-
type: sectionType,
|
|
721
|
-
path,
|
|
722
|
-
size,
|
|
723
|
-
skipped: false,
|
|
724
|
-
superseded: result.superseded ?? null,
|
|
725
|
-
warnings: result.warnings ?? [],
|
|
726
|
-
near_duplicates: result.near_duplicates ?? []
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
1025
|
function readProcessStdin() {
|
|
730
1026
|
return new Promise((resolve7) => {
|
|
731
1027
|
const chunks = [];
|
|
@@ -1113,28 +1409,27 @@ async function runSkillLearn(client, options) {
|
|
|
1113
1409
|
};
|
|
1114
1410
|
}
|
|
1115
1411
|
|
|
1412
|
+
// src/shared/query-filter/functions/matches-query.function.ts
|
|
1413
|
+
function matchesQuery(query, ...fields) {
|
|
1414
|
+
if (!query) return true;
|
|
1415
|
+
const needle = query.toLowerCase();
|
|
1416
|
+
return fields.some(
|
|
1417
|
+
(field) => typeof field === "string" && field.toLowerCase().includes(needle)
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1116
1421
|
// src/shared/cli/functions/run-skill-list.function.ts
|
|
1117
|
-
async function runSkillList(client,
|
|
1422
|
+
async function runSkillList(client, options) {
|
|
1118
1423
|
log("running skill-list", 0 /* DEBUG */);
|
|
1119
1424
|
const records = await client.listByType("skill");
|
|
1120
|
-
const
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
}
|
|
1127
|
-
} catch {
|
|
1128
|
-
}
|
|
1129
|
-
return {
|
|
1130
|
-
kbid: r.kbid,
|
|
1131
|
-
name: r.title,
|
|
1132
|
-
description: r.description,
|
|
1133
|
-
argumentCount
|
|
1134
|
-
};
|
|
1135
|
-
});
|
|
1425
|
+
const query = options.args.join(" ").toLowerCase();
|
|
1426
|
+
const filtered = records.filter(
|
|
1427
|
+
(r) => matchesQuery(query, r.title, r.description)
|
|
1428
|
+
);
|
|
1429
|
+
const names = filtered.map((r) => r.title);
|
|
1430
|
+
const data = { items: names, total: names.length, offset: 0 };
|
|
1136
1431
|
return {
|
|
1137
|
-
output: JSON.stringify(
|
|
1432
|
+
output: JSON.stringify(data, null, 2),
|
|
1138
1433
|
exitCode: 0
|
|
1139
1434
|
};
|
|
1140
1435
|
}
|
|
@@ -1263,16 +1558,15 @@ async function runAgentCreate(client, options) {
|
|
|
1263
1558
|
}
|
|
1264
1559
|
|
|
1265
1560
|
// src/shared/cli/functions/run-agent-list.function.ts
|
|
1266
|
-
async function runAgentList(client,
|
|
1561
|
+
async function runAgentList(client, options) {
|
|
1267
1562
|
log("running agent-list", 0 /* DEBUG */);
|
|
1268
1563
|
const docs = await client.listDocumentsByType("agent");
|
|
1269
|
-
const
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
}));
|
|
1564
|
+
const query = options.args.join(" ").toLowerCase();
|
|
1565
|
+
const filtered = docs.filter((d) => matchesQuery(query, d.title));
|
|
1566
|
+
const names = filtered.map((d) => d.title);
|
|
1567
|
+
const data = { items: names, total: names.length, offset: 0 };
|
|
1274
1568
|
return {
|
|
1275
|
-
output: JSON.stringify(
|
|
1569
|
+
output: JSON.stringify(data, null, 2),
|
|
1276
1570
|
exitCode: 0
|
|
1277
1571
|
};
|
|
1278
1572
|
}
|
|
@@ -1740,7 +2034,7 @@ async function handleTypedSearch(client, options, type) {
|
|
|
1740
2034
|
}
|
|
1741
2035
|
|
|
1742
2036
|
// src/shared/version/constants/version.constant.ts
|
|
1743
|
-
var VERSION = "0.6.
|
|
2037
|
+
var VERSION = "0.6.5";
|
|
1744
2038
|
|
|
1745
2039
|
// src/shared/cli/functions/generate-help.function.ts
|
|
1746
2040
|
var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
@@ -1768,13 +2062,13 @@ var GROUP_SUBCOMMANDS = {
|
|
|
1768
2062
|
],
|
|
1769
2063
|
skill: [
|
|
1770
2064
|
["learn", "Create a new skill definition"],
|
|
1771
|
-
["list", "List
|
|
2065
|
+
["list", "List skills (filter by keyword)"],
|
|
1772
2066
|
["get", "Retrieve a skill by name or kbid"],
|
|
1773
2067
|
["delete", "Remove a skill"]
|
|
1774
2068
|
],
|
|
1775
2069
|
agent: [
|
|
1776
2070
|
["create", "Create an agent with skill refs"],
|
|
1777
|
-
["list", "List
|
|
2071
|
+
["list", "List agents (filter by keyword)"],
|
|
1778
2072
|
["get", "Retrieve an agent by docid"],
|
|
1779
2073
|
["delete", "Remove an agent"]
|
|
1780
2074
|
],
|
|
@@ -1819,9 +2113,9 @@ Usage: kbdb [options]
|
|
|
1819
2113
|
kbdb <command> <subcommand> [options] ...[params]
|
|
1820
2114
|
|
|
1821
2115
|
Knowledge Base:
|
|
1822
|
-
learn Import content
|
|
2116
|
+
learn Import content (auto-splits structured formats)
|
|
1823
2117
|
unlearn Remove sections by kbid
|
|
1824
|
-
search Query the knowledge base
|
|
2118
|
+
search Query the knowledge base (sibling boost)
|
|
1825
2119
|
recall Retrieve section context by kbid
|
|
1826
2120
|
content Compose rendered content from ids
|
|
1827
2121
|
|
|
@@ -1840,28 +2134,34 @@ Maintenance:
|
|
|
1840
2134
|
|
|
1841
2135
|
Skills:
|
|
1842
2136
|
skill learn Create a new skill definition
|
|
1843
|
-
skill list List
|
|
2137
|
+
skill list List skills (filter by keyword)
|
|
1844
2138
|
skill get Retrieve a skill by name or kbid
|
|
1845
2139
|
skill delete Remove a skill
|
|
2140
|
+
skill search Search skills by keyword
|
|
1846
2141
|
|
|
1847
2142
|
Agents:
|
|
1848
2143
|
agent create Create an agent with skill refs
|
|
1849
|
-
agent list List
|
|
2144
|
+
agent list List agents (filter by keyword)
|
|
1850
2145
|
agent get Retrieve an agent by docid
|
|
1851
2146
|
agent delete Remove an agent
|
|
1852
|
-
|
|
1853
|
-
Worker:
|
|
1854
|
-
worker stop Stop the worker daemon
|
|
1855
|
-
worker restart Restart the worker daemon
|
|
2147
|
+
agent search Search agents by keyword
|
|
1856
2148
|
|
|
1857
2149
|
Server:
|
|
1858
2150
|
mcp Start MCP server mode (stdio)
|
|
1859
2151
|
|
|
1860
2152
|
Global Options:
|
|
1861
2153
|
-h, --help Show this help message
|
|
1862
|
-
|
|
2154
|
+
--version Show version information
|
|
2155
|
+
-v, --verbose Log warnings (-vv info, -vvv debug)
|
|
1863
2156
|
--db <path> Path to .kbdb directory
|
|
1864
|
-
--format <fmt> Output format (json|text|mcp)
|
|
2157
|
+
--format <fmt> Output format (rec|json|text|mcp)
|
|
2158
|
+
--timeout-ms <ms> Request timeout (default 30000)
|
|
2159
|
+
--retry <n> Retries on timeout (default 1)
|
|
2160
|
+
--non-interactive Suppress prompts
|
|
2161
|
+
|
|
2162
|
+
Worker:
|
|
2163
|
+
worker stop Stop background daemon
|
|
2164
|
+
worker restart Restart background daemon
|
|
1865
2165
|
|
|
1866
2166
|
Run "kbdb <command> --help" for detailed information.
|
|
1867
2167
|
`;
|
|
@@ -1918,9 +2218,22 @@ Options:
|
|
|
1918
2218
|
--replace Supersede existing section by source key
|
|
1919
2219
|
--db <path> Path to .kbdb directory
|
|
1920
2220
|
|
|
2221
|
+
Content splitting:
|
|
2222
|
+
Structured formats are automatically split
|
|
2223
|
+
into independent sections that share a docid.
|
|
2224
|
+
Each section carries a level (heading depth)
|
|
2225
|
+
and parent (kbid of enclosing section).
|
|
2226
|
+
Providing --title imports as a single section
|
|
2227
|
+
(skips splitting).
|
|
2228
|
+
|
|
2229
|
+
Supported formats:
|
|
2230
|
+
Markdown .md, text/markdown ATX headings
|
|
2231
|
+
HTML .html, text/html <h1>-<h6> tags
|
|
2232
|
+
TOML .toml, application/toml [section]
|
|
2233
|
+
Plain .txt, text/plain no splitting
|
|
2234
|
+
|
|
1921
2235
|
Output:
|
|
1922
|
-
|
|
1923
|
-
superseded, warnings, near_duplicates }
|
|
2236
|
+
{ items, total, offset } envelope
|
|
1924
2237
|
|
|
1925
2238
|
Examples:
|
|
1926
2239
|
kbdb learn README.md
|
|
@@ -1955,12 +2268,23 @@ Arguments:
|
|
|
1955
2268
|
Options:
|
|
1956
2269
|
--mode <mode> Result granularity (sections|documents|stats)
|
|
1957
2270
|
--limit <n> Max results (default: 20)
|
|
1958
|
-
--format <fmt> Output format (json|text|mcp)
|
|
2271
|
+
--format <fmt> Output format (rec|json|text|mcp)
|
|
1959
2272
|
--content, -c Hydrate results with section content
|
|
1960
2273
|
--db <path> Path to .kbdb directory
|
|
1961
2274
|
|
|
2275
|
+
Scoring:
|
|
2276
|
+
Results are ranked by BM25F. Sections from
|
|
2277
|
+
the same document (shared docid) receive a
|
|
2278
|
+
sibling score boost when multiple sections
|
|
2279
|
+
match the query.
|
|
2280
|
+
|
|
2281
|
+
Fields:
|
|
2282
|
+
Each result includes level (heading depth,
|
|
2283
|
+
1-6 or null) and parent (kbid of enclosing
|
|
2284
|
+
section or null).
|
|
2285
|
+
|
|
1962
2286
|
Output:
|
|
1963
|
-
|
|
2287
|
+
{ items, total, offset } envelope
|
|
1964
2288
|
|
|
1965
2289
|
Examples:
|
|
1966
2290
|
kbdb search "machine learning"
|
|
@@ -1980,7 +2304,8 @@ Options:
|
|
|
1980
2304
|
--db <path> Path to .kbdb directory
|
|
1981
2305
|
|
|
1982
2306
|
Output:
|
|
1983
|
-
JSON RecallResult or RecallResult[]
|
|
2307
|
+
JSON RecallResult or RecallResult[] with
|
|
2308
|
+
level, parent, siblings, and references
|
|
1984
2309
|
|
|
1985
2310
|
Examples:
|
|
1986
2311
|
kbdb recall abcdef1234567890abcdef1234
|
|
@@ -1989,11 +2314,14 @@ Examples:
|
|
|
1989
2314
|
content: `kbdb content - Compose rendered content from ids
|
|
1990
2315
|
|
|
1991
2316
|
Usage: kbdb content [options] <id>...
|
|
2317
|
+
kbdb content --search <query>...
|
|
1992
2318
|
|
|
1993
2319
|
Arguments:
|
|
1994
2320
|
<id> kbid or docid identifier
|
|
2321
|
+
<query> Search terms (with --search)
|
|
1995
2322
|
|
|
1996
2323
|
Options:
|
|
2324
|
+
--search, -s Search for ids by keyword
|
|
1997
2325
|
--db <path> Path to .kbdb directory
|
|
1998
2326
|
|
|
1999
2327
|
Output:
|
|
@@ -2002,6 +2330,7 @@ Output:
|
|
|
2002
2330
|
Examples:
|
|
2003
2331
|
kbdb content abcdef1234567890abcdef1234
|
|
2004
2332
|
kbdb content id1 id2
|
|
2333
|
+
kbdb content --search machine learning
|
|
2005
2334
|
`,
|
|
2006
2335
|
check: `kbdb check - Verify knowledge base integrity
|
|
2007
2336
|
|
|
@@ -2169,16 +2498,20 @@ Examples:
|
|
|
2169
2498
|
`,
|
|
2170
2499
|
"skill-list": `kbdb skill list - List all skills
|
|
2171
2500
|
|
|
2172
|
-
Usage: kbdb skill list [options]
|
|
2501
|
+
Usage: kbdb skill list [options] [keywords...]
|
|
2502
|
+
|
|
2503
|
+
Arguments:
|
|
2504
|
+
[keywords...] Case-insensitive substring filter on name or description
|
|
2173
2505
|
|
|
2174
2506
|
Options:
|
|
2175
2507
|
--db <path> Path to .kbdb directory
|
|
2176
2508
|
|
|
2177
2509
|
Output:
|
|
2178
|
-
JSON
|
|
2510
|
+
JSON { items, total, offset }
|
|
2179
2511
|
|
|
2180
2512
|
Examples:
|
|
2181
2513
|
kbdb skill list
|
|
2514
|
+
kbdb skill list summarize
|
|
2182
2515
|
kbdb skill list --db /path/to/project
|
|
2183
2516
|
`,
|
|
2184
2517
|
"skill-get": `kbdb skill get - Retrieve a skill by name or kbid
|
|
@@ -2234,16 +2567,20 @@ Examples:
|
|
|
2234
2567
|
`,
|
|
2235
2568
|
"agent-list": `kbdb agent list - List all agents
|
|
2236
2569
|
|
|
2237
|
-
Usage: kbdb agent list [options]
|
|
2570
|
+
Usage: kbdb agent list [options] [keywords...]
|
|
2571
|
+
|
|
2572
|
+
Arguments:
|
|
2573
|
+
[keywords...] Case-insensitive substring filter on agent name
|
|
2238
2574
|
|
|
2239
2575
|
Options:
|
|
2240
2576
|
--db <path> Path to .kbdb directory
|
|
2241
2577
|
|
|
2242
2578
|
Output:
|
|
2243
|
-
JSON
|
|
2579
|
+
JSON { items, total, offset }
|
|
2244
2580
|
|
|
2245
2581
|
Examples:
|
|
2246
2582
|
kbdb agent list
|
|
2583
|
+
kbdb agent list reviewer
|
|
2247
2584
|
kbdb agent list --db /path/to/project
|
|
2248
2585
|
`,
|
|
2249
2586
|
"agent-get": `kbdb agent get - Retrieve an agent by docid
|
|
@@ -3503,7 +3840,7 @@ function createToolDefinitions() {
|
|
|
3503
3840
|
return [
|
|
3504
3841
|
{
|
|
3505
3842
|
name: "search",
|
|
3506
|
-
description: "Query the knowledge base by keywords. Returns ranked results with heading, snippet,
|
|
3843
|
+
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.",
|
|
3507
3844
|
inputSchema: {
|
|
3508
3845
|
type: "object",
|
|
3509
3846
|
properties: {
|
|
@@ -3546,7 +3883,7 @@ function createToolDefinitions() {
|
|
|
3546
3883
|
},
|
|
3547
3884
|
{
|
|
3548
3885
|
name: "learn",
|
|
3549
|
-
description: "Import content into the knowledge base.
|
|
3886
|
+
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.",
|
|
3550
3887
|
inputSchema: {
|
|
3551
3888
|
type: "object",
|
|
3552
3889
|
properties: {
|
|
@@ -3556,11 +3893,11 @@ function createToolDefinitions() {
|
|
|
3556
3893
|
},
|
|
3557
3894
|
type: {
|
|
3558
3895
|
type: "string",
|
|
3559
|
-
description: "MIME type
|
|
3896
|
+
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."
|
|
3560
3897
|
},
|
|
3561
3898
|
title: {
|
|
3562
3899
|
type: "string",
|
|
3563
|
-
description: "Section title. Required for image/* types."
|
|
3900
|
+
description: "Section title. Skips content splitting when set. Required for image/* types."
|
|
3564
3901
|
},
|
|
3565
3902
|
description: {
|
|
3566
3903
|
type: "string",
|
|
@@ -3568,7 +3905,7 @@ function createToolDefinitions() {
|
|
|
3568
3905
|
},
|
|
3569
3906
|
docid: {
|
|
3570
3907
|
type: "string",
|
|
3571
|
-
description: "Document ID to group under"
|
|
3908
|
+
description: "Document ID to group sections under. Set automatically when content splitting is active."
|
|
3572
3909
|
},
|
|
3573
3910
|
tags: {
|
|
3574
3911
|
type: "array",
|
|
@@ -3637,7 +3974,7 @@ function createToolDefinitions() {
|
|
|
3637
3974
|
},
|
|
3638
3975
|
{
|
|
3639
3976
|
name: "recall",
|
|
3640
|
-
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.",
|
|
3977
|
+
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.",
|
|
3641
3978
|
inputSchema: {
|
|
3642
3979
|
type: "object",
|
|
3643
3980
|
properties: {
|
|
@@ -3768,7 +4105,7 @@ function createToolDefinitions() {
|
|
|
3768
4105
|
},
|
|
3769
4106
|
{
|
|
3770
4107
|
name: "skill-learn",
|
|
3771
|
-
description: "Create or update a skill definition. Skills are reusable AI agent capabilities with template placeholders.",
|
|
4108
|
+
description: "Create or update a skill definition. Skills are reusable AI agent capabilities with template placeholders. Stored as atomic JSON (not split into sections).",
|
|
3772
4109
|
inputSchema: {
|
|
3773
4110
|
type: "object",
|
|
3774
4111
|
properties: {
|
|
@@ -3797,10 +4134,15 @@ function createToolDefinitions() {
|
|
|
3797
4134
|
},
|
|
3798
4135
|
{
|
|
3799
4136
|
name: "skill-list",
|
|
3800
|
-
description: "List
|
|
4137
|
+
description: "List skill definitions stored in the knowledge base, optionally filtered by a substring query.",
|
|
3801
4138
|
inputSchema: {
|
|
3802
4139
|
type: "object",
|
|
3803
|
-
properties: {
|
|
4140
|
+
properties: {
|
|
4141
|
+
query: {
|
|
4142
|
+
type: "string",
|
|
4143
|
+
description: "Case-insensitive substring filter on skill name or description."
|
|
4144
|
+
}
|
|
4145
|
+
}
|
|
3804
4146
|
},
|
|
3805
4147
|
annotations: {
|
|
3806
4148
|
title: "List Skills",
|
|
@@ -3857,7 +4199,7 @@ function createToolDefinitions() {
|
|
|
3857
4199
|
},
|
|
3858
4200
|
{
|
|
3859
4201
|
name: "agent-create",
|
|
3860
|
-
description: "Create an AI agent with a persona and optional skill references.",
|
|
4202
|
+
description: "Create an AI agent with a persona and optional skill references. Stored as atomic JSON (not split into sections).",
|
|
3861
4203
|
inputSchema: {
|
|
3862
4204
|
type: "object",
|
|
3863
4205
|
properties: {
|
|
@@ -3891,10 +4233,15 @@ function createToolDefinitions() {
|
|
|
3891
4233
|
},
|
|
3892
4234
|
{
|
|
3893
4235
|
name: "agent-list",
|
|
3894
|
-
description: "List
|
|
4236
|
+
description: "List agent documents in the knowledge base, optionally filtered by a substring query.",
|
|
3895
4237
|
inputSchema: {
|
|
3896
4238
|
type: "object",
|
|
3897
|
-
properties: {
|
|
4239
|
+
properties: {
|
|
4240
|
+
query: {
|
|
4241
|
+
type: "string",
|
|
4242
|
+
description: "Case-insensitive substring filter on agent name or description."
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
3898
4245
|
},
|
|
3899
4246
|
annotations: {
|
|
3900
4247
|
title: "List Agents",
|
|
@@ -4013,7 +4360,7 @@ function createToolDefinitions() {
|
|
|
4013
4360
|
title: "Auto-Capture Review",
|
|
4014
4361
|
readOnlyHint: false,
|
|
4015
4362
|
destructiveHint: false,
|
|
4016
|
-
idempotentHint:
|
|
4363
|
+
idempotentHint: false,
|
|
4017
4364
|
openWorldHint: false
|
|
4018
4365
|
}
|
|
4019
4366
|
}
|
|
@@ -4142,7 +4489,7 @@ async function readAgentDescription(client, sections) {
|
|
|
4142
4489
|
return "";
|
|
4143
4490
|
}
|
|
4144
4491
|
}
|
|
4145
|
-
async function handleAgentList(client) {
|
|
4492
|
+
async function handleAgentList(client, args = {}) {
|
|
4146
4493
|
const docs = await client.listDocumentsByType("agent");
|
|
4147
4494
|
const items = await Promise.all(
|
|
4148
4495
|
docs.map(async (d) => ({
|
|
@@ -4150,17 +4497,17 @@ async function handleAgentList(client) {
|
|
|
4150
4497
|
description: await readAgentDescription(client, d.sections)
|
|
4151
4498
|
}))
|
|
4152
4499
|
);
|
|
4153
|
-
const
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
const text = [`${String(items.length)} agents:`, ...lines].join(
|
|
4157
|
-
"\n"
|
|
4500
|
+
const query = typeof args["query"] === "string" ? args["query"].toLowerCase() : "";
|
|
4501
|
+
const filtered = items.filter(
|
|
4502
|
+
(item) => matchesQuery(query, item.name, item.description)
|
|
4158
4503
|
);
|
|
4504
|
+
const names = filtered.map((item) => item.name);
|
|
4505
|
+
const data = { items: names, total: names.length, offset: 0 };
|
|
4159
4506
|
return {
|
|
4160
4507
|
content: [
|
|
4161
4508
|
{
|
|
4162
4509
|
type: "text",
|
|
4163
|
-
text
|
|
4510
|
+
text: JSON.stringify(data, null, 2)
|
|
4164
4511
|
}
|
|
4165
4512
|
]
|
|
4166
4513
|
};
|
|
@@ -4402,25 +4749,38 @@ async function handleAgentSearch(client, args) {
|
|
|
4402
4749
|
return { content: [{ type: "text", text }] };
|
|
4403
4750
|
}
|
|
4404
4751
|
|
|
4405
|
-
// src/shared/mcp/functions/
|
|
4752
|
+
// src/shared/mcp/functions/as-string.function.ts
|
|
4406
4753
|
function asString2(value, fallback) {
|
|
4407
4754
|
return typeof value === "string" ? value : fallback;
|
|
4408
4755
|
}
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
}
|
|
4756
|
+
|
|
4757
|
+
// src/shared/mcp/functions/as-string-array-or-undefined.function.ts
|
|
4412
4758
|
function asStringArrayOrUndefined(value) {
|
|
4413
4759
|
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
4414
4760
|
return value;
|
|
4415
4761
|
}
|
|
4416
4762
|
return void 0;
|
|
4417
4763
|
}
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4764
|
+
|
|
4765
|
+
// src/shared/mcp/functions/as-boolean-or-undefined.function.ts
|
|
4766
|
+
function asBooleanOrUndefined(value) {
|
|
4767
|
+
return typeof value === "boolean" ? value : void 0;
|
|
4768
|
+
}
|
|
4769
|
+
|
|
4770
|
+
// src/shared/mcp/functions/parse-learn-args.function.ts
|
|
4771
|
+
function parseLearnArgs(args) {
|
|
4772
|
+
return {
|
|
4773
|
+
sectionType: asString2(args["type"], "text/markdown"),
|
|
4774
|
+
title: typeof args["title"] === "string" ? args["title"] : void 0,
|
|
4775
|
+
description: typeof args["description"] === "string" ? args["description"] : void 0,
|
|
4776
|
+
docid: typeof args["docid"] === "string" ? args["docid"] : void 0,
|
|
4777
|
+
tags: asStringArrayOrUndefined(args["tags"]),
|
|
4778
|
+
replace: asBooleanOrUndefined(args["replace"]),
|
|
4779
|
+
level: typeof args["level"] === "number" ? args["level"] : void 0
|
|
4780
|
+
};
|
|
4423
4781
|
}
|
|
4782
|
+
|
|
4783
|
+
// src/shared/mcp/functions/unwrap-json-content.function.ts
|
|
4424
4784
|
function unwrapJsonContent(raw) {
|
|
4425
4785
|
const trimmed = raw.trim();
|
|
4426
4786
|
if (!trimmed.startsWith("{")) return raw;
|
|
@@ -4433,6 +4793,158 @@ function unwrapJsonContent(raw) {
|
|
|
4433
4793
|
}
|
|
4434
4794
|
return raw;
|
|
4435
4795
|
}
|
|
4796
|
+
|
|
4797
|
+
// src/shared/mcp/functions/determine-learn-split.function.ts
|
|
4798
|
+
function determineLearnSplit(content, sectionType, title) {
|
|
4799
|
+
const splittable = sectionType.startsWith("text/") || sectionType === "markdown" || sectionType === "application/toml";
|
|
4800
|
+
if (title !== void 0 || !splittable) return void 0;
|
|
4801
|
+
const result = splitContent(content, sectionType);
|
|
4802
|
+
const hasTitledSection = result.sections.some(
|
|
4803
|
+
(section) => section.title !== void 0
|
|
4804
|
+
);
|
|
4805
|
+
return result.sections.length >= 2 && hasTitledSection ? result : void 0;
|
|
4806
|
+
}
|
|
4807
|
+
|
|
4808
|
+
// src/shared/mcp/functions/learn-with-splitting.function.ts
|
|
4809
|
+
async function learnWithSplitting(client, splitResult, params) {
|
|
4810
|
+
const { sections } = splitResult;
|
|
4811
|
+
const firstTitled = sections.find((s) => s.title !== void 0);
|
|
4812
|
+
const docTitle = firstTitled?.title ?? params.docid ?? "Untitled";
|
|
4813
|
+
const docid = params.docid ?? firstTitled?.title;
|
|
4814
|
+
const kbids = [];
|
|
4815
|
+
for (const section of sections) {
|
|
4816
|
+
const [parent] = resolveParentIds([section], kbids);
|
|
4817
|
+
const result = await client.addSection({
|
|
4818
|
+
sectionType: params.sectionType,
|
|
4819
|
+
content: section.content,
|
|
4820
|
+
title: section.title,
|
|
4821
|
+
description: params.description,
|
|
4822
|
+
docid,
|
|
4823
|
+
tags: params.tags,
|
|
4824
|
+
replace: params.replace,
|
|
4825
|
+
level: section.level,
|
|
4826
|
+
parent: parent ?? void 0
|
|
4827
|
+
});
|
|
4828
|
+
kbids.push(result.items[0] ?? "");
|
|
4829
|
+
}
|
|
4830
|
+
return { kbids, docTitle };
|
|
4831
|
+
}
|
|
4832
|
+
|
|
4833
|
+
// src/shared/mcp/functions/store-split-learn-sections.function.ts
|
|
4834
|
+
async function storeSplitLearnSections(client, splitResult, params) {
|
|
4835
|
+
const { kbids, docTitle } = await learnWithSplitting(
|
|
4836
|
+
client,
|
|
4837
|
+
splitResult,
|
|
4838
|
+
params
|
|
4839
|
+
);
|
|
4840
|
+
await client.groupSections(docTitle, kbids);
|
|
4841
|
+
return {
|
|
4842
|
+
items: kbids,
|
|
4843
|
+
total: kbids.length,
|
|
4844
|
+
offset: 0,
|
|
4845
|
+
superseded: null,
|
|
4846
|
+
warnings: [],
|
|
4847
|
+
near_duplicates: []
|
|
4848
|
+
};
|
|
4849
|
+
}
|
|
4850
|
+
|
|
4851
|
+
// src/shared/mcp/functions/build-learn-payload.function.ts
|
|
4852
|
+
function buildLearnPayload(result) {
|
|
4853
|
+
return {
|
|
4854
|
+
items: result.items,
|
|
4855
|
+
total: result.total,
|
|
4856
|
+
offset: result.offset,
|
|
4857
|
+
superseded: result.superseded ?? null,
|
|
4858
|
+
warnings: result.warnings ?? [],
|
|
4859
|
+
near_duplicates: result.near_duplicates ?? []
|
|
4860
|
+
};
|
|
4861
|
+
}
|
|
4862
|
+
|
|
4863
|
+
// src/shared/mcp/functions/handle-tool-learn.function.ts
|
|
4864
|
+
async function handleToolLearn(client, args) {
|
|
4865
|
+
const learnArgs = parseLearnArgs(args);
|
|
4866
|
+
const { sectionType, title, level, ...shared } = learnArgs;
|
|
4867
|
+
if (sectionType.startsWith("image/") && !title) {
|
|
4868
|
+
return {
|
|
4869
|
+
content: [
|
|
4870
|
+
{
|
|
4871
|
+
type: "text",
|
|
4872
|
+
text: "title is required for image/* types"
|
|
4873
|
+
}
|
|
4874
|
+
],
|
|
4875
|
+
isError: true
|
|
4876
|
+
};
|
|
4877
|
+
}
|
|
4878
|
+
const content = unwrapJsonContent(asString2(args["content"], ""));
|
|
4879
|
+
const splitResult = determineLearnSplit(content, sectionType, title);
|
|
4880
|
+
const result = splitResult ? await storeSplitLearnSections(client, splitResult, {
|
|
4881
|
+
sectionType,
|
|
4882
|
+
...shared
|
|
4883
|
+
}) : await client.addSection({
|
|
4884
|
+
sectionType,
|
|
4885
|
+
content,
|
|
4886
|
+
title,
|
|
4887
|
+
level,
|
|
4888
|
+
...shared
|
|
4889
|
+
});
|
|
4890
|
+
return {
|
|
4891
|
+
content: [
|
|
4892
|
+
{
|
|
4893
|
+
type: "text",
|
|
4894
|
+
text: JSON.stringify(buildLearnPayload(result))
|
|
4895
|
+
}
|
|
4896
|
+
]
|
|
4897
|
+
};
|
|
4898
|
+
}
|
|
4899
|
+
|
|
4900
|
+
// src/shared/mcp/functions/handle-tool-skill-learn.function.ts
|
|
4901
|
+
async function handleToolSkillLearn(client, args) {
|
|
4902
|
+
const name = asString2(args["name"], "");
|
|
4903
|
+
if (!name) {
|
|
4904
|
+
return {
|
|
4905
|
+
content: [{ type: "text", text: "name is required" }],
|
|
4906
|
+
isError: true
|
|
4907
|
+
};
|
|
4908
|
+
}
|
|
4909
|
+
const body = asString2(args["body"], "");
|
|
4910
|
+
if (!body) {
|
|
4911
|
+
return {
|
|
4912
|
+
content: [{ type: "text", text: "body is required" }],
|
|
4913
|
+
isError: true
|
|
4914
|
+
};
|
|
4915
|
+
}
|
|
4916
|
+
const description = typeof args["description"] === "string" ? args["description"] : void 0;
|
|
4917
|
+
const skillArgs = extractSkillArguments(body);
|
|
4918
|
+
const skill = {
|
|
4919
|
+
name,
|
|
4920
|
+
description,
|
|
4921
|
+
arguments: skillArgs.length > 0 ? skillArgs : void 0,
|
|
4922
|
+
body
|
|
4923
|
+
};
|
|
4924
|
+
const json = serializeSkillContent(skill);
|
|
4925
|
+
const result = await client.addSection({
|
|
4926
|
+
sectionType: "skill",
|
|
4927
|
+
content: json,
|
|
4928
|
+
title: name,
|
|
4929
|
+
description
|
|
4930
|
+
});
|
|
4931
|
+
return {
|
|
4932
|
+
content: [
|
|
4933
|
+
{
|
|
4934
|
+
type: "text",
|
|
4935
|
+
text: `Created skill "${name}" (kbid: ${result.items[0]})`
|
|
4936
|
+
}
|
|
4937
|
+
]
|
|
4938
|
+
};
|
|
4939
|
+
}
|
|
4940
|
+
|
|
4941
|
+
// src/shared/mcp/functions/handle-tool-call.function.ts
|
|
4942
|
+
function asStringArray2(value) {
|
|
4943
|
+
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
4944
|
+
return value;
|
|
4945
|
+
}
|
|
4946
|
+
return [];
|
|
4947
|
+
}
|
|
4436
4948
|
async function handleToolCall(client, name, args) {
|
|
4437
4949
|
log("tool call: " + name, 0 /* DEBUG */);
|
|
4438
4950
|
try {
|
|
@@ -4440,7 +4952,7 @@ async function handleToolCall(client, name, args) {
|
|
|
4440
4952
|
case "search":
|
|
4441
4953
|
return await handleSearch2(client, args);
|
|
4442
4954
|
case "learn":
|
|
4443
|
-
return await
|
|
4955
|
+
return await handleToolLearn(client, args);
|
|
4444
4956
|
case "unlearn":
|
|
4445
4957
|
return await handleUnlearn2(client, args);
|
|
4446
4958
|
case "retrieve":
|
|
@@ -4460,9 +4972,9 @@ async function handleToolCall(client, name, args) {
|
|
|
4460
4972
|
case "export":
|
|
4461
4973
|
return await handleExport2(client, args);
|
|
4462
4974
|
case "skill-learn":
|
|
4463
|
-
return await
|
|
4975
|
+
return await handleToolSkillLearn(client, args);
|
|
4464
4976
|
case "skill-list":
|
|
4465
|
-
return await handleSkillList(client);
|
|
4977
|
+
return await handleSkillList(client, args);
|
|
4466
4978
|
case "skill-get":
|
|
4467
4979
|
return await handleSkillGet(client, args);
|
|
4468
4980
|
case "skill-delete":
|
|
@@ -4470,7 +4982,7 @@ async function handleToolCall(client, name, args) {
|
|
|
4470
4982
|
case "agent-create":
|
|
4471
4983
|
return await handleAgentCreate(client, args);
|
|
4472
4984
|
case "agent-list":
|
|
4473
|
-
return await handleAgentList(client);
|
|
4985
|
+
return await handleAgentList(client, args);
|
|
4474
4986
|
case "agent-get":
|
|
4475
4987
|
return await handleAgentGet(client, args);
|
|
4476
4988
|
case "agent-delete":
|
|
@@ -4525,47 +5037,6 @@ async function handleSearch2(client, args) {
|
|
|
4525
5037
|
]
|
|
4526
5038
|
};
|
|
4527
5039
|
}
|
|
4528
|
-
async function handleLearn2(client, args) {
|
|
4529
|
-
const sectionType = asString2(args["type"], "text/markdown");
|
|
4530
|
-
const title = typeof args["title"] === "string" ? args["title"] : void 0;
|
|
4531
|
-
const description = typeof args["description"] === "string" ? args["description"] : void 0;
|
|
4532
|
-
const docid = typeof args["docid"] === "string" ? args["docid"] : void 0;
|
|
4533
|
-
const tags = asStringArrayOrUndefined(args["tags"]);
|
|
4534
|
-
const replace = asBooleanOrUndefined(args["replace"]);
|
|
4535
|
-
if (sectionType.startsWith("image/") && !title) {
|
|
4536
|
-
return {
|
|
4537
|
-
content: [
|
|
4538
|
-
{
|
|
4539
|
-
type: "text",
|
|
4540
|
-
text: "title is required for image/* types"
|
|
4541
|
-
}
|
|
4542
|
-
],
|
|
4543
|
-
isError: true
|
|
4544
|
-
};
|
|
4545
|
-
}
|
|
4546
|
-
const rawContent = asString2(args["content"], "");
|
|
4547
|
-
const content = unwrapJsonContent(rawContent);
|
|
4548
|
-
const result = await client.addSection({
|
|
4549
|
-
sectionType,
|
|
4550
|
-
content,
|
|
4551
|
-
title,
|
|
4552
|
-
description,
|
|
4553
|
-
docid,
|
|
4554
|
-
tags,
|
|
4555
|
-
replace
|
|
4556
|
-
});
|
|
4557
|
-
const payload = {
|
|
4558
|
-
items: result.items,
|
|
4559
|
-
total: result.total,
|
|
4560
|
-
offset: result.offset,
|
|
4561
|
-
superseded: result.superseded ?? null,
|
|
4562
|
-
warnings: result.warnings ?? [],
|
|
4563
|
-
near_duplicates: result.near_duplicates ?? []
|
|
4564
|
-
};
|
|
4565
|
-
return {
|
|
4566
|
-
content: [{ type: "text", text: JSON.stringify(payload) }]
|
|
4567
|
-
};
|
|
4568
|
-
}
|
|
4569
5040
|
async function handleUnlearn2(client, args) {
|
|
4570
5041
|
const kbid = asString2(args["kbid"], "");
|
|
4571
5042
|
await client.removeSection(kbid);
|
|
@@ -4672,56 +5143,17 @@ async function handleRebuild2(client) {
|
|
|
4672
5143
|
const text = `Rebuild complete: ${String(report.sections_reindexed)} sections reindexed, ${String(report.terms_indexed)} terms indexed.`;
|
|
4673
5144
|
return { content: [{ type: "text", text }] };
|
|
4674
5145
|
}
|
|
4675
|
-
async function
|
|
4676
|
-
const name = asString2(args["name"], "");
|
|
4677
|
-
if (!name) {
|
|
4678
|
-
return {
|
|
4679
|
-
content: [{ type: "text", text: "name is required" }],
|
|
4680
|
-
isError: true
|
|
4681
|
-
};
|
|
4682
|
-
}
|
|
4683
|
-
const body = asString2(args["body"], "");
|
|
4684
|
-
if (!body) {
|
|
4685
|
-
return {
|
|
4686
|
-
content: [{ type: "text", text: "body is required" }],
|
|
4687
|
-
isError: true
|
|
4688
|
-
};
|
|
4689
|
-
}
|
|
4690
|
-
const description = typeof args["description"] === "string" ? args["description"] : void 0;
|
|
4691
|
-
const skillArgs = extractSkillArguments(body);
|
|
4692
|
-
const skill = {
|
|
4693
|
-
name,
|
|
4694
|
-
description,
|
|
4695
|
-
arguments: skillArgs.length > 0 ? skillArgs : void 0,
|
|
4696
|
-
body
|
|
4697
|
-
};
|
|
4698
|
-
const json = serializeSkillContent(skill);
|
|
4699
|
-
const result = await client.addSection({
|
|
4700
|
-
sectionType: "skill",
|
|
4701
|
-
content: json,
|
|
4702
|
-
title: name,
|
|
4703
|
-
description
|
|
4704
|
-
});
|
|
4705
|
-
return {
|
|
4706
|
-
content: [
|
|
4707
|
-
{
|
|
4708
|
-
type: "text",
|
|
4709
|
-
text: `Created skill "${name}" (kbid: ${result.items[0]})`
|
|
4710
|
-
}
|
|
4711
|
-
]
|
|
4712
|
-
};
|
|
4713
|
-
}
|
|
4714
|
-
async function handleSkillList(client) {
|
|
5146
|
+
async function handleSkillList(client, args) {
|
|
4715
5147
|
const records = await client.listByType("skill");
|
|
4716
|
-
const
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
return `${String(index + 1)}. ${label} (${r.kbid})${desc}`;
|
|
4720
|
-
});
|
|
4721
|
-
const text = [`${String(records.length)} skills:`, ...lines].join(
|
|
4722
|
-
"\n"
|
|
5148
|
+
const query = typeof args["query"] === "string" ? args["query"].toLowerCase() : "";
|
|
5149
|
+
const filtered = records.filter(
|
|
5150
|
+
(r) => matchesQuery(query, r.title, r.description)
|
|
4723
5151
|
);
|
|
4724
|
-
|
|
5152
|
+
const names = filtered.map((r) => r.title ?? "");
|
|
5153
|
+
const data = { items: names, total: names.length, offset: 0 };
|
|
5154
|
+
return {
|
|
5155
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
5156
|
+
};
|
|
4725
5157
|
}
|
|
4726
5158
|
async function handleSkillGet(client, args) {
|
|
4727
5159
|
const kbid = typeof args["kbid"] === "string" ? args["kbid"] : void 0;
|