@dikolab/kbdb 0.6.4 → 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 +452 -144
- package/dist/cli.cjs.map +4 -4
- package/dist/cli.mjs +452 -144
- 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-structured-document.function.d.ts +10 -0
- package/dist/src/shared/cli/functions/learn-target-content.function.d.ts +5 -17
- package/dist/src/shared/cli/functions/split-markdown-sections.function.d.ts +4 -0
- package/dist/src/shared/cli/typings/learn-client.interface.d.ts +2 -0
- package/dist/src/shared/cli/typings/learn-result.model.d.ts +2 -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-tool-learn.function.d.ts +3 -1
- 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/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/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/dist/wasm/kb-worker/kbdb_worker_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,13 +662,102 @@ function computeDirectoryLevel(filePath, basePath) {
|
|
|
659
662
|
return Math.min(depth + 1, MAX_LEVEL);
|
|
660
663
|
}
|
|
661
664
|
|
|
662
|
-
// src/shared/
|
|
663
|
-
|
|
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
|
+
};
|
|
664
684
|
|
|
665
|
-
// src/shared/
|
|
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
|
|
666
757
|
var HEADING_PATTERN = /^(#{1,6})\s+(.+)$/;
|
|
667
|
-
function
|
|
758
|
+
function splitMarkdown(content) {
|
|
668
759
|
const sections = [];
|
|
760
|
+
const tracker = new HeadingParentTracker();
|
|
669
761
|
let draft = { lines: [] };
|
|
670
762
|
let inCodeBlock = false;
|
|
671
763
|
for (const line of content.split("\n")) {
|
|
@@ -676,7 +768,7 @@ function splitMarkdownSections(content) {
|
|
|
676
768
|
}
|
|
677
769
|
const heading = inCodeBlock ? null : HEADING_PATTERN.exec(line);
|
|
678
770
|
if (heading) {
|
|
679
|
-
|
|
771
|
+
flushMarkdownDraft(draft, sections, tracker);
|
|
680
772
|
draft = {
|
|
681
773
|
title: heading[2].trim(),
|
|
682
774
|
level: heading[1].length,
|
|
@@ -686,14 +778,113 @@ function splitMarkdownSections(content) {
|
|
|
686
778
|
}
|
|
687
779
|
draft.lines.push(line);
|
|
688
780
|
}
|
|
689
|
-
|
|
690
|
-
return sections.length > 0 ? sections : [{ content: content.trimEnd() }];
|
|
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;
|
|
691
811
|
}
|
|
692
|
-
|
|
812
|
+
|
|
813
|
+
// src/shared/content-splitter/functions/flush-toml-draft.function.ts
|
|
814
|
+
function flushTomlDraft(draft, sections, pathIndex) {
|
|
693
815
|
const body = draft.lines.join("\n").trimEnd();
|
|
694
816
|
if (draft.title === void 0 && body.length === 0) return;
|
|
695
|
-
|
|
696
|
-
|
|
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]
|
|
697
888
|
);
|
|
698
889
|
}
|
|
699
890
|
|
|
@@ -712,15 +903,16 @@ function mapAddSectionResult(result, path, size, sectionType) {
|
|
|
712
903
|
};
|
|
713
904
|
}
|
|
714
905
|
|
|
715
|
-
// src/shared/cli/functions/learn-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
const
|
|
719
|
-
|
|
720
|
-
const docTitle =
|
|
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);
|
|
721
912
|
const kbids = [];
|
|
722
913
|
const results = [];
|
|
723
914
|
for (const section of sections) {
|
|
915
|
+
const [parent] = resolveParentIds([section], kbids);
|
|
724
916
|
const added = await client.addSection({
|
|
725
917
|
sectionType: "text",
|
|
726
918
|
content: section.content,
|
|
@@ -730,7 +922,8 @@ async function learnMarkdownDocument(client, options, path, content, sourcePath)
|
|
|
730
922
|
tags: options.tags,
|
|
731
923
|
replace: options.replace,
|
|
732
924
|
sourcePath,
|
|
733
|
-
level: section.level
|
|
925
|
+
level: section.level,
|
|
926
|
+
parent: parent ?? void 0
|
|
734
927
|
});
|
|
735
928
|
kbids.push(added.items[0] ?? "");
|
|
736
929
|
results.push(
|
|
@@ -748,16 +941,25 @@ async function learnMarkdownDocument(client, options, path, content, sourcePath)
|
|
|
748
941
|
|
|
749
942
|
// src/shared/cli/functions/learn-target-content.function.ts
|
|
750
943
|
async function learnTargetContent(client, options, path, content, sourcePath, level) {
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
const split =
|
|
754
|
-
client,
|
|
755
|
-
options,
|
|
756
|
-
path,
|
|
944
|
+
if (!options.title) {
|
|
945
|
+
const isStdin = path === "-";
|
|
946
|
+
const split = splitContent(
|
|
757
947
|
content,
|
|
758
|
-
|
|
948
|
+
isStdin ? "markdown" : void 0,
|
|
949
|
+
isStdin ? void 0 : path
|
|
950
|
+
);
|
|
951
|
+
const hasTitled = split.sections.some(
|
|
952
|
+
(s) => s.title !== void 0
|
|
759
953
|
);
|
|
760
|
-
if (split)
|
|
954
|
+
if (split.sections.length >= 2 && hasTitled) {
|
|
955
|
+
return learnStructuredDocument(
|
|
956
|
+
client,
|
|
957
|
+
options,
|
|
958
|
+
path,
|
|
959
|
+
split,
|
|
960
|
+
sourcePath
|
|
961
|
+
);
|
|
962
|
+
}
|
|
761
963
|
}
|
|
762
964
|
const result = await client.addSection({
|
|
763
965
|
sectionType: "text",
|
|
@@ -1832,7 +2034,7 @@ async function handleTypedSearch(client, options, type) {
|
|
|
1832
2034
|
}
|
|
1833
2035
|
|
|
1834
2036
|
// src/shared/version/constants/version.constant.ts
|
|
1835
|
-
var VERSION = "0.6.
|
|
2037
|
+
var VERSION = "0.6.5";
|
|
1836
2038
|
|
|
1837
2039
|
// src/shared/cli/functions/generate-help.function.ts
|
|
1838
2040
|
var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
@@ -1911,7 +2113,7 @@ Usage: kbdb [options]
|
|
|
1911
2113
|
kbdb <command> <subcommand> [options] ...[params]
|
|
1912
2114
|
|
|
1913
2115
|
Knowledge Base:
|
|
1914
|
-
learn Import content (splits
|
|
2116
|
+
learn Import content (auto-splits structured formats)
|
|
1915
2117
|
unlearn Remove sections by kbid
|
|
1916
2118
|
search Query the knowledge base (sibling boost)
|
|
1917
2119
|
recall Retrieve section context by kbid
|
|
@@ -1935,25 +2137,31 @@ Skills:
|
|
|
1935
2137
|
skill list List skills (filter by keyword)
|
|
1936
2138
|
skill get Retrieve a skill by name or kbid
|
|
1937
2139
|
skill delete Remove a skill
|
|
2140
|
+
skill search Search skills by keyword
|
|
1938
2141
|
|
|
1939
2142
|
Agents:
|
|
1940
2143
|
agent create Create an agent with skill refs
|
|
1941
2144
|
agent list List agents (filter by keyword)
|
|
1942
2145
|
agent get Retrieve an agent by docid
|
|
1943
2146
|
agent delete Remove an agent
|
|
1944
|
-
|
|
1945
|
-
Worker:
|
|
1946
|
-
worker stop Stop the worker daemon
|
|
1947
|
-
worker restart Restart the worker daemon
|
|
2147
|
+
agent search Search agents by keyword
|
|
1948
2148
|
|
|
1949
2149
|
Server:
|
|
1950
2150
|
mcp Start MCP server mode (stdio)
|
|
1951
2151
|
|
|
1952
2152
|
Global Options:
|
|
1953
2153
|
-h, --help Show this help message
|
|
1954
|
-
|
|
2154
|
+
--version Show version information
|
|
2155
|
+
-v, --verbose Log warnings (-vv info, -vvv debug)
|
|
1955
2156
|
--db <path> Path to .kbdb directory
|
|
1956
|
-
--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
|
|
1957
2165
|
|
|
1958
2166
|
Run "kbdb <command> --help" for detailed information.
|
|
1959
2167
|
`;
|
|
@@ -2010,14 +2218,19 @@ Options:
|
|
|
2010
2218
|
--replace Supersede existing section by source key
|
|
2011
2219
|
--db <path> Path to .kbdb directory
|
|
2012
2220
|
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
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
|
|
2021
2234
|
|
|
2022
2235
|
Output:
|
|
2023
2236
|
{ items, total, offset } envelope
|
|
@@ -2055,7 +2268,7 @@ Arguments:
|
|
|
2055
2268
|
Options:
|
|
2056
2269
|
--mode <mode> Result granularity (sections|documents|stats)
|
|
2057
2270
|
--limit <n> Max results (default: 20)
|
|
2058
|
-
--format <fmt> Output format (json|text|mcp)
|
|
2271
|
+
--format <fmt> Output format (rec|json|text|mcp)
|
|
2059
2272
|
--content, -c Hydrate results with section content
|
|
2060
2273
|
--db <path> Path to .kbdb directory
|
|
2061
2274
|
|
|
@@ -2065,6 +2278,11 @@ Scoring:
|
|
|
2065
2278
|
sibling score boost when multiple sections
|
|
2066
2279
|
match the query.
|
|
2067
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
|
+
|
|
2068
2286
|
Output:
|
|
2069
2287
|
{ items, total, offset } envelope
|
|
2070
2288
|
|
|
@@ -2086,7 +2304,8 @@ Options:
|
|
|
2086
2304
|
--db <path> Path to .kbdb directory
|
|
2087
2305
|
|
|
2088
2306
|
Output:
|
|
2089
|
-
JSON RecallResult or RecallResult[]
|
|
2307
|
+
JSON RecallResult or RecallResult[] with
|
|
2308
|
+
level, parent, siblings, and references
|
|
2090
2309
|
|
|
2091
2310
|
Examples:
|
|
2092
2311
|
kbdb recall abcdef1234567890abcdef1234
|
|
@@ -2095,11 +2314,14 @@ Examples:
|
|
|
2095
2314
|
content: `kbdb content - Compose rendered content from ids
|
|
2096
2315
|
|
|
2097
2316
|
Usage: kbdb content [options] <id>...
|
|
2317
|
+
kbdb content --search <query>...
|
|
2098
2318
|
|
|
2099
2319
|
Arguments:
|
|
2100
2320
|
<id> kbid or docid identifier
|
|
2321
|
+
<query> Search terms (with --search)
|
|
2101
2322
|
|
|
2102
2323
|
Options:
|
|
2324
|
+
--search, -s Search for ids by keyword
|
|
2103
2325
|
--db <path> Path to .kbdb directory
|
|
2104
2326
|
|
|
2105
2327
|
Output:
|
|
@@ -2108,6 +2330,7 @@ Output:
|
|
|
2108
2330
|
Examples:
|
|
2109
2331
|
kbdb content abcdef1234567890abcdef1234
|
|
2110
2332
|
kbdb content id1 id2
|
|
2333
|
+
kbdb content --search machine learning
|
|
2111
2334
|
`,
|
|
2112
2335
|
check: `kbdb check - Verify knowledge base integrity
|
|
2113
2336
|
|
|
@@ -3617,7 +3840,7 @@ function createToolDefinitions() {
|
|
|
3617
3840
|
return [
|
|
3618
3841
|
{
|
|
3619
3842
|
name: "search",
|
|
3620
|
-
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.",
|
|
3621
3844
|
inputSchema: {
|
|
3622
3845
|
type: "object",
|
|
3623
3846
|
properties: {
|
|
@@ -3660,7 +3883,7 @@ function createToolDefinitions() {
|
|
|
3660
3883
|
},
|
|
3661
3884
|
{
|
|
3662
3885
|
name: "learn",
|
|
3663
|
-
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.",
|
|
3664
3887
|
inputSchema: {
|
|
3665
3888
|
type: "object",
|
|
3666
3889
|
properties: {
|
|
@@ -3670,11 +3893,11 @@ function createToolDefinitions() {
|
|
|
3670
3893
|
},
|
|
3671
3894
|
type: {
|
|
3672
3895
|
type: "string",
|
|
3673
|
-
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."
|
|
3674
3897
|
},
|
|
3675
3898
|
title: {
|
|
3676
3899
|
type: "string",
|
|
3677
|
-
description: "Section title. Skips
|
|
3900
|
+
description: "Section title. Skips content splitting when set. Required for image/* types."
|
|
3678
3901
|
},
|
|
3679
3902
|
description: {
|
|
3680
3903
|
type: "string",
|
|
@@ -3682,7 +3905,7 @@ function createToolDefinitions() {
|
|
|
3682
3905
|
},
|
|
3683
3906
|
docid: {
|
|
3684
3907
|
type: "string",
|
|
3685
|
-
description: "Document ID to group sections under. Set automatically when
|
|
3908
|
+
description: "Document ID to group sections under. Set automatically when content splitting is active."
|
|
3686
3909
|
},
|
|
3687
3910
|
tags: {
|
|
3688
3911
|
type: "array",
|
|
@@ -3751,7 +3974,7 @@ function createToolDefinitions() {
|
|
|
3751
3974
|
},
|
|
3752
3975
|
{
|
|
3753
3976
|
name: "recall",
|
|
3754
|
-
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.",
|
|
3755
3978
|
inputSchema: {
|
|
3756
3979
|
type: "object",
|
|
3757
3980
|
properties: {
|
|
@@ -3882,7 +4105,7 @@ function createToolDefinitions() {
|
|
|
3882
4105
|
},
|
|
3883
4106
|
{
|
|
3884
4107
|
name: "skill-learn",
|
|
3885
|
-
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).",
|
|
3886
4109
|
inputSchema: {
|
|
3887
4110
|
type: "object",
|
|
3888
4111
|
properties: {
|
|
@@ -3976,7 +4199,7 @@ function createToolDefinitions() {
|
|
|
3976
4199
|
},
|
|
3977
4200
|
{
|
|
3978
4201
|
name: "agent-create",
|
|
3979
|
-
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).",
|
|
3980
4203
|
inputSchema: {
|
|
3981
4204
|
type: "object",
|
|
3982
4205
|
properties: {
|
|
@@ -4137,7 +4360,7 @@ function createToolDefinitions() {
|
|
|
4137
4360
|
title: "Auto-Capture Review",
|
|
4138
4361
|
readOnlyHint: false,
|
|
4139
4362
|
destructiveHint: false,
|
|
4140
|
-
idempotentHint:
|
|
4363
|
+
idempotentHint: false,
|
|
4141
4364
|
openWorldHint: false
|
|
4142
4365
|
}
|
|
4143
4366
|
}
|
|
@@ -4526,25 +4749,38 @@ async function handleAgentSearch(client, args) {
|
|
|
4526
4749
|
return { content: [{ type: "text", text }] };
|
|
4527
4750
|
}
|
|
4528
4751
|
|
|
4529
|
-
// src/shared/mcp/functions/
|
|
4752
|
+
// src/shared/mcp/functions/as-string.function.ts
|
|
4530
4753
|
function asString2(value, fallback) {
|
|
4531
4754
|
return typeof value === "string" ? value : fallback;
|
|
4532
4755
|
}
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
}
|
|
4756
|
+
|
|
4757
|
+
// src/shared/mcp/functions/as-string-array-or-undefined.function.ts
|
|
4536
4758
|
function asStringArrayOrUndefined(value) {
|
|
4537
4759
|
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
4538
4760
|
return value;
|
|
4539
4761
|
}
|
|
4540
4762
|
return void 0;
|
|
4541
4763
|
}
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
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
|
+
};
|
|
4547
4781
|
}
|
|
4782
|
+
|
|
4783
|
+
// src/shared/mcp/functions/unwrap-json-content.function.ts
|
|
4548
4784
|
function unwrapJsonContent(raw) {
|
|
4549
4785
|
const trimmed = raw.trim();
|
|
4550
4786
|
if (!trimmed.startsWith("{")) return raw;
|
|
@@ -4557,6 +4793,158 @@ function unwrapJsonContent(raw) {
|
|
|
4557
4793
|
}
|
|
4558
4794
|
return raw;
|
|
4559
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
|
+
}
|
|
4560
4948
|
async function handleToolCall(client, name, args) {
|
|
4561
4949
|
log("tool call: " + name, 0 /* DEBUG */);
|
|
4562
4950
|
try {
|
|
@@ -4564,7 +4952,7 @@ async function handleToolCall(client, name, args) {
|
|
|
4564
4952
|
case "search":
|
|
4565
4953
|
return await handleSearch2(client, args);
|
|
4566
4954
|
case "learn":
|
|
4567
|
-
return await
|
|
4955
|
+
return await handleToolLearn(client, args);
|
|
4568
4956
|
case "unlearn":
|
|
4569
4957
|
return await handleUnlearn2(client, args);
|
|
4570
4958
|
case "retrieve":
|
|
@@ -4584,7 +4972,7 @@ async function handleToolCall(client, name, args) {
|
|
|
4584
4972
|
case "export":
|
|
4585
4973
|
return await handleExport2(client, args);
|
|
4586
4974
|
case "skill-learn":
|
|
4587
|
-
return await
|
|
4975
|
+
return await handleToolSkillLearn(client, args);
|
|
4588
4976
|
case "skill-list":
|
|
4589
4977
|
return await handleSkillList(client, args);
|
|
4590
4978
|
case "skill-get":
|
|
@@ -4649,47 +5037,6 @@ async function handleSearch2(client, args) {
|
|
|
4649
5037
|
]
|
|
4650
5038
|
};
|
|
4651
5039
|
}
|
|
4652
|
-
async function handleLearn2(client, args) {
|
|
4653
|
-
const sectionType = asString2(args["type"], "text/markdown");
|
|
4654
|
-
const title = typeof args["title"] === "string" ? args["title"] : void 0;
|
|
4655
|
-
const description = typeof args["description"] === "string" ? args["description"] : void 0;
|
|
4656
|
-
const docid = typeof args["docid"] === "string" ? args["docid"] : void 0;
|
|
4657
|
-
const tags = asStringArrayOrUndefined(args["tags"]);
|
|
4658
|
-
const replace = asBooleanOrUndefined(args["replace"]);
|
|
4659
|
-
if (sectionType.startsWith("image/") && !title) {
|
|
4660
|
-
return {
|
|
4661
|
-
content: [
|
|
4662
|
-
{
|
|
4663
|
-
type: "text",
|
|
4664
|
-
text: "title is required for image/* types"
|
|
4665
|
-
}
|
|
4666
|
-
],
|
|
4667
|
-
isError: true
|
|
4668
|
-
};
|
|
4669
|
-
}
|
|
4670
|
-
const rawContent = asString2(args["content"], "");
|
|
4671
|
-
const content = unwrapJsonContent(rawContent);
|
|
4672
|
-
const result = await client.addSection({
|
|
4673
|
-
sectionType,
|
|
4674
|
-
content,
|
|
4675
|
-
title,
|
|
4676
|
-
description,
|
|
4677
|
-
docid,
|
|
4678
|
-
tags,
|
|
4679
|
-
replace
|
|
4680
|
-
});
|
|
4681
|
-
const payload = {
|
|
4682
|
-
items: result.items,
|
|
4683
|
-
total: result.total,
|
|
4684
|
-
offset: result.offset,
|
|
4685
|
-
superseded: result.superseded ?? null,
|
|
4686
|
-
warnings: result.warnings ?? [],
|
|
4687
|
-
near_duplicates: result.near_duplicates ?? []
|
|
4688
|
-
};
|
|
4689
|
-
return {
|
|
4690
|
-
content: [{ type: "text", text: JSON.stringify(payload) }]
|
|
4691
|
-
};
|
|
4692
|
-
}
|
|
4693
5040
|
async function handleUnlearn2(client, args) {
|
|
4694
5041
|
const kbid = asString2(args["kbid"], "");
|
|
4695
5042
|
await client.removeSection(kbid);
|
|
@@ -4796,45 +5143,6 @@ async function handleRebuild2(client) {
|
|
|
4796
5143
|
const text = `Rebuild complete: ${String(report.sections_reindexed)} sections reindexed, ${String(report.terms_indexed)} terms indexed.`;
|
|
4797
5144
|
return { content: [{ type: "text", text }] };
|
|
4798
5145
|
}
|
|
4799
|
-
async function handleSkillLearn(client, args) {
|
|
4800
|
-
const name = asString2(args["name"], "");
|
|
4801
|
-
if (!name) {
|
|
4802
|
-
return {
|
|
4803
|
-
content: [{ type: "text", text: "name is required" }],
|
|
4804
|
-
isError: true
|
|
4805
|
-
};
|
|
4806
|
-
}
|
|
4807
|
-
const body = asString2(args["body"], "");
|
|
4808
|
-
if (!body) {
|
|
4809
|
-
return {
|
|
4810
|
-
content: [{ type: "text", text: "body is required" }],
|
|
4811
|
-
isError: true
|
|
4812
|
-
};
|
|
4813
|
-
}
|
|
4814
|
-
const description = typeof args["description"] === "string" ? args["description"] : void 0;
|
|
4815
|
-
const skillArgs = extractSkillArguments(body);
|
|
4816
|
-
const skill = {
|
|
4817
|
-
name,
|
|
4818
|
-
description,
|
|
4819
|
-
arguments: skillArgs.length > 0 ? skillArgs : void 0,
|
|
4820
|
-
body
|
|
4821
|
-
};
|
|
4822
|
-
const json = serializeSkillContent(skill);
|
|
4823
|
-
const result = await client.addSection({
|
|
4824
|
-
sectionType: "skill",
|
|
4825
|
-
content: json,
|
|
4826
|
-
title: name,
|
|
4827
|
-
description
|
|
4828
|
-
});
|
|
4829
|
-
return {
|
|
4830
|
-
content: [
|
|
4831
|
-
{
|
|
4832
|
-
type: "text",
|
|
4833
|
-
text: `Created skill "${name}" (kbid: ${result.items[0]})`
|
|
4834
|
-
}
|
|
4835
|
-
]
|
|
4836
|
-
};
|
|
4837
|
-
}
|
|
4838
5146
|
async function handleSkillList(client, args) {
|
|
4839
5147
|
const records = await client.listByType("skill");
|
|
4840
5148
|
const query = typeof args["query"] === "string" ? args["query"].toLowerCase() : "";
|