@ontos-ai/knowhere-claw 0.1.4 → 0.1.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/README.md +3 -0
- package/dist/_virtual/_rolldown/runtime.js +2 -1
- package/dist/config.js +115 -1
- package/dist/connect-builder.js +181 -0
- package/dist/graph-builder.js +204 -0
- package/dist/index.js +15 -3
- package/dist/kg-service.js +249 -0
- package/dist/node_modules/.pnpm/@mapbox_node-pre-gyp@1.0.11/node_modules/@mapbox/node-pre-gyp/lib/node-pre-gyp.js +212 -0
- package/dist/node_modules/.pnpm/@mapbox_node-pre-gyp@1.0.11/node_modules/@mapbox/node-pre-gyp/lib/pre-binding.js +35 -0
- package/dist/node_modules/.pnpm/@mapbox_node-pre-gyp@1.0.11/node_modules/@mapbox/node-pre-gyp/lib/util/abi_crosswalk.js +2609 -0
- package/dist/node_modules/.pnpm/@mapbox_node-pre-gyp@1.0.11/node_modules/@mapbox/node-pre-gyp/lib/util/napi.js +142 -0
- package/dist/node_modules/.pnpm/@mapbox_node-pre-gyp@1.0.11/node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js +103 -0
- package/dist/node_modules/.pnpm/@mapbox_node-pre-gyp@1.0.11/node_modules/@mapbox/node-pre-gyp/lib/util/versioning.js +199 -0
- package/dist/node_modules/.pnpm/@mapbox_node-pre-gyp@1.0.11/node_modules/@mapbox/node-pre-gyp/package.js +67 -0
- package/dist/node_modules/.pnpm/abbrev@1.1.1/node_modules/abbrev/abbrev.js +59 -0
- package/dist/node_modules/.pnpm/ansi-regex@5.0.1/node_modules/ansi-regex/index.js +11 -0
- package/dist/node_modules/.pnpm/aproba@2.1.0/node_modules/aproba/index.js +119 -0
- package/dist/node_modules/.pnpm/are-we-there-yet@2.0.0/node_modules/are-we-there-yet/lib/index.js +13 -0
- package/dist/node_modules/.pnpm/are-we-there-yet@2.0.0/node_modules/are-we-there-yet/lib/tracker-base.js +16 -0
- package/dist/node_modules/.pnpm/are-we-there-yet@2.0.0/node_modules/are-we-there-yet/lib/tracker-group.js +98 -0
- package/dist/node_modules/.pnpm/are-we-there-yet@2.0.0/node_modules/are-we-there-yet/lib/tracker-stream.js +37 -0
- package/dist/node_modules/.pnpm/are-we-there-yet@2.0.0/node_modules/are-we-there-yet/lib/tracker.js +32 -0
- package/dist/node_modules/.pnpm/balanced-match@1.0.2/node_modules/balanced-match/index.js +53 -0
- package/dist/node_modules/.pnpm/brace-expansion@1.1.12/node_modules/brace-expansion/index.js +132 -0
- package/dist/node_modules/.pnpm/color-support@1.1.3/node_modules/color-support/browser.js +18 -0
- package/dist/node_modules/.pnpm/concat-map@0.0.1/node_modules/concat-map/index.js +19 -0
- package/dist/node_modules/.pnpm/console-control-strings@1.1.0/node_modules/console-control-strings/index.js +104 -0
- package/dist/node_modules/.pnpm/delegates@1.0.0/node_modules/delegates/index.js +104 -0
- package/dist/node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/detect-libc.js +221 -0
- package/dist/node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/elf.js +26 -0
- package/dist/node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/filesystem.js +48 -0
- package/dist/node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/process.js +24 -0
- package/dist/node_modules/.pnpm/emoji-regex@8.0.0/node_modules/emoji-regex/index.js +10 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/copy/copy-sync.js +120 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/copy/copy.js +100 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/copy/index.js +15 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/empty/index.js +43 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/ensure/file.js +53 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/ensure/index.js +27 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/ensure/link.js +56 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/ensure/symlink-paths.js +89 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/ensure/symlink-type.js +35 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/ensure/symlink.js +81 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/fs/index.js +113 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/index.js +29 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/json/index.js +22 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/json/jsonfile.js +15 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/json/output-json-sync.js +15 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/json/output-json.js +15 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/mkdirs/index.js +20 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/mkdirs/make-dir.js +33 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/mkdirs/utils.js +17 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/move/index.js +15 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/move/move-sync.js +56 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/move/move.js +49 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/output-file/index.js +30 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/path-exists/index.js +18 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/remove/index.js +27 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/util/async.js +15 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/util/stat.js +131 -0
- package/dist/node_modules/.pnpm/fs-extra@11.3.4/node_modules/fs-extra/lib/util/utimes.js +34 -0
- package/dist/node_modules/.pnpm/fs.realpath@1.0.0/node_modules/fs.realpath/index.js +51 -0
- package/dist/node_modules/.pnpm/fs.realpath@1.0.0/node_modules/fs.realpath/old.js +171 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/base-theme.js +21 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/error.js +27 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/has-color.js +9 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/index.js +224 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/plumbing.js +48 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/process.js +8 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/progress-bar.js +46 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/render-template.js +155 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/set-immediate.js +14 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/set-interval.js +8 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/spin.js +10 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/template-item.js +58 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/theme-set.js +99 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/themes.js +67 -0
- package/dist/node_modules/.pnpm/gauge@3.0.2/node_modules/gauge/wide-truncate.js +22 -0
- package/dist/node_modules/.pnpm/glob@7.2.3/node_modules/glob/common.js +162 -0
- package/dist/node_modules/.pnpm/glob@7.2.3/node_modules/glob/glob.js +451 -0
- package/dist/node_modules/.pnpm/glob@7.2.3/node_modules/glob/sync.js +280 -0
- package/dist/node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/clone.js +20 -0
- package/dist/node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/graceful-fs.js +362 -0
- package/dist/node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/legacy-streams.js +92 -0
- package/dist/node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/polyfills.js +255 -0
- package/dist/node_modules/.pnpm/has-unicode@2.0.1/node_modules/has-unicode/index.js +14 -0
- package/dist/node_modules/.pnpm/inflight@1.0.6/node_modules/inflight/inflight.js +45 -0
- package/dist/node_modules/.pnpm/inherits@2.0.4/node_modules/inherits/inherits_browser.js +27 -0
- package/dist/node_modules/.pnpm/is-fullwidth-code-point@3.0.0/node_modules/is-fullwidth-code-point/index.js +14 -0
- package/dist/node_modules/.pnpm/jsonfile@6.2.0/node_modules/jsonfile/index.js +68 -0
- package/dist/node_modules/.pnpm/jsonfile@6.2.0/node_modules/jsonfile/utils.js +19 -0
- package/dist/node_modules/.pnpm/minimatch@3.1.5/node_modules/minimatch/minimatch.js +578 -0
- package/dist/node_modules/.pnpm/nodejieba@2.6.0/node_modules/nodejieba/index.js +46 -0
- package/dist/node_modules/.pnpm/nopt@5.0.0/node_modules/nopt/lib/nopt.js +330 -0
- package/dist/node_modules/.pnpm/npmlog@5.0.1/node_modules/npmlog/log.js +305 -0
- package/dist/node_modules/.pnpm/object-assign@4.1.1/node_modules/object-assign/index.js +54 -0
- package/dist/node_modules/.pnpm/once@1.4.0/node_modules/once/once.js +44 -0
- package/dist/node_modules/.pnpm/path-is-absolute@1.0.1/node_modules/path-is-absolute/index.js +19 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/errors-browser.js +88 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/_stream_duplex.js +75 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/_stream_passthrough.js +19 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/_stream_readable.js +666 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/_stream_transform.js +89 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/_stream_writable.js +423 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/async_iterator.js +172 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/buffer_list.js +243 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/destroy.js +77 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +87 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/from-browser.js +10 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/pipeline.js +80 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/state.js +21 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/stream-browser.js +8 -0
- package/dist/node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/readable-browser.js +23 -0
- package/dist/node_modules/.pnpm/rimraf@3.0.2/node_modules/rimraf/rimraf.js +229 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/classes/comparator.js +79 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/classes/range.js +282 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/classes/semver.js +186 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/clean.js +14 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/cmp.js +41 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/coerce.js +34 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/compare-build.js +15 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/compare-loose.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/compare.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/diff.js +32 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/eq.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/gt.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/gte.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/inc.js +22 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/lt.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/lte.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/major.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/minor.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/neq.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/parse.js +19 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/patch.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/prerelease.js +14 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/rcompare.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/rsort.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/satisfies.js +18 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/sort.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/valid.js +14 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/index.js +99 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/internal/constants.js +28 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/internal/debug.js +8 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/internal/identifiers.js +23 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/internal/lrucache.js +36 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/internal/parse-options.js +15 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/internal/re.js +84 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/gtr.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/intersects.js +15 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/ltr.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/max-satisfying.js +31 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/min-satisfying.js +31 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/min-version.js +45 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/outside.js +64 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/simplify.js +35 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/subset.js +102 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/to-comparators.js +11 -0
- package/dist/node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/valid.js +17 -0
- package/dist/node_modules/.pnpm/set-blocking@2.0.0/node_modules/set-blocking/index.js +12 -0
- package/dist/node_modules/.pnpm/signal-exit@3.0.7/node_modules/signal-exit/index.js +130 -0
- package/dist/node_modules/.pnpm/signal-exit@3.0.7/node_modules/signal-exit/signals.js +16 -0
- package/dist/node_modules/.pnpm/string-width@4.2.3/node_modules/string-width/index.js +30 -0
- package/dist/node_modules/.pnpm/strip-ansi@6.0.1/node_modules/strip-ansi/index.js +10 -0
- package/dist/node_modules/.pnpm/universalify@2.0.1/node_modules/universalify/index.js +26 -0
- package/dist/node_modules/.pnpm/util-deprecate@1.0.2/node_modules/util-deprecate/browser.js +59 -0
- package/dist/node_modules/.pnpm/wide-align@1.1.5/node_modules/wide-align/align.js +52 -0
- package/dist/node_modules/.pnpm/wrappy@1.0.2/node_modules/wrappy/wrappy.js +26 -0
- package/dist/tools.js +163 -3
- package/openclaw.plugin.json +1 -1
- package/package.json +15 -6
- package/skills/knowhere/SKILL.md +1 -1
- package/dist/__tests__/channel-route.test.d.ts +0 -1
- package/dist/__tests__/ingest-tool.test.d.ts +0 -1
- package/dist/__tests__/read-result-file-tool.test.d.ts +0 -1
- package/dist/__tests__/tracker-progress.test.d.ts +0 -1
- package/dist/channel-delivery.d.ts +0 -21
- package/dist/client.d.ts +0 -33
- package/dist/config.d.ts +0 -12
- package/dist/error-message.d.ts +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/parser.d.ts +0 -16
- package/dist/session.d.ts +0 -11
- package/dist/store.d.ts +0 -79
- package/dist/text.d.ts +0 -10
- package/dist/tools.d.ts +0 -8
- package/dist/tracker-progress.d.ts +0 -10
- package/dist/types.d.ts +0 -248
package/README.md
CHANGED
|
@@ -138,3 +138,6 @@ Within each scope, the plugin keeps:
|
|
|
138
138
|
|
|
139
139
|
Contributor-oriented architecture, workflow, and packaging notes live in
|
|
140
140
|
`DEVELOPMENT.md` at the repository root.
|
|
141
|
+
|
|
142
|
+
Release-process details for maintainers live in
|
|
143
|
+
[`docs/release-workflow.md`](./docs/release-workflow.md).
|
|
@@ -5,6 +5,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
8
9
|
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
9
10
|
var __exportAll = (all, no_symbols) => {
|
|
10
11
|
let target = {};
|
|
@@ -34,4 +35,4 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
34
35
|
throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
35
36
|
});
|
|
36
37
|
//#endregion
|
|
37
|
-
export { __commonJSMin, __exportAll, __require, __toESM };
|
|
38
|
+
export { __commonJSMin, __esmMin, __exportAll, __require, __toESM };
|
package/dist/config.js
CHANGED
|
@@ -48,6 +48,79 @@ const knowherePluginConfigSchema = {
|
|
|
48
48
|
minimum: 1e3,
|
|
49
49
|
maximum: 72e5,
|
|
50
50
|
default: 6e5
|
|
51
|
+
},
|
|
52
|
+
knowledgeGraph: {
|
|
53
|
+
type: "object",
|
|
54
|
+
additionalProperties: false,
|
|
55
|
+
properties: {
|
|
56
|
+
enabled: {
|
|
57
|
+
type: "boolean",
|
|
58
|
+
default: true
|
|
59
|
+
},
|
|
60
|
+
kbId: { type: "string" },
|
|
61
|
+
kbIdSource: {
|
|
62
|
+
type: "string",
|
|
63
|
+
enum: [
|
|
64
|
+
"disabled",
|
|
65
|
+
"agent",
|
|
66
|
+
"agent-session",
|
|
67
|
+
"global"
|
|
68
|
+
],
|
|
69
|
+
default: "disabled"
|
|
70
|
+
},
|
|
71
|
+
concurrentBuildStrategy: {
|
|
72
|
+
type: "string",
|
|
73
|
+
enum: ["queue", "skip"],
|
|
74
|
+
default: "queue"
|
|
75
|
+
},
|
|
76
|
+
buildTimeout: {
|
|
77
|
+
type: "integer",
|
|
78
|
+
minimum: 1e4,
|
|
79
|
+
maximum: 6e5,
|
|
80
|
+
default: 3e5
|
|
81
|
+
},
|
|
82
|
+
notifyOnGraphFailure: {
|
|
83
|
+
type: "boolean",
|
|
84
|
+
default: false
|
|
85
|
+
},
|
|
86
|
+
connectConfig: {
|
|
87
|
+
type: "object",
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
properties: {
|
|
90
|
+
minKeywordOverlap: {
|
|
91
|
+
type: "integer",
|
|
92
|
+
minimum: 1,
|
|
93
|
+
default: 3
|
|
94
|
+
},
|
|
95
|
+
keywordScoreWeight: {
|
|
96
|
+
type: "number",
|
|
97
|
+
minimum: 0,
|
|
98
|
+
default: 1
|
|
99
|
+
},
|
|
100
|
+
maxConnectionsPerChunk: {
|
|
101
|
+
type: "integer",
|
|
102
|
+
minimum: 1,
|
|
103
|
+
default: 10
|
|
104
|
+
},
|
|
105
|
+
minScoreThreshold: {
|
|
106
|
+
type: "number",
|
|
107
|
+
minimum: 0,
|
|
108
|
+
maximum: 1,
|
|
109
|
+
default: .8
|
|
110
|
+
},
|
|
111
|
+
crossFileOnly: {
|
|
112
|
+
type: "boolean",
|
|
113
|
+
default: true
|
|
114
|
+
},
|
|
115
|
+
maxContentOverlap: {
|
|
116
|
+
type: "number",
|
|
117
|
+
minimum: 0,
|
|
118
|
+
maximum: 1,
|
|
119
|
+
default: .8
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
51
124
|
}
|
|
52
125
|
}
|
|
53
126
|
};
|
|
@@ -142,5 +215,46 @@ async function persistApiKey(storageDir, apiKey) {
|
|
|
142
215
|
const filePath = resolveApiKeyStatePath(storageDir);
|
|
143
216
|
await fs.writeFile(filePath, JSON.stringify({ apiKey: apiKey.trim() }), "utf-8");
|
|
144
217
|
}
|
|
218
|
+
function readKbIdSource(raw) {
|
|
219
|
+
const value = readString(raw, "kbIdSource");
|
|
220
|
+
if (value === "disabled" || value === "agent" || value === "agent-session" || value === "global") return value;
|
|
221
|
+
return "disabled";
|
|
222
|
+
}
|
|
223
|
+
function resolveKnowledgeGraphConfig(raw) {
|
|
224
|
+
const kgConfig = isRecord(raw.knowledgeGraph) ? raw.knowledgeGraph : {};
|
|
225
|
+
const connectConfig = isRecord(kgConfig.connectConfig) ? kgConfig.connectConfig : {};
|
|
226
|
+
return {
|
|
227
|
+
enableKnowledgeGraph: typeof kgConfig.enabled === "boolean" ? kgConfig.enabled : true,
|
|
228
|
+
kbId: readString(kgConfig, "kbId"),
|
|
229
|
+
kbIdSource: readKbIdSource(kgConfig),
|
|
230
|
+
concurrentBuildStrategy: kgConfig.concurrentBuildStrategy === "queue" || kgConfig.concurrentBuildStrategy === "skip" ? kgConfig.concurrentBuildStrategy : "queue",
|
|
231
|
+
buildTimeout: readNumber(kgConfig, "buildTimeout", 3e5, {
|
|
232
|
+
min: 1e4,
|
|
233
|
+
max: 6e5,
|
|
234
|
+
integer: true
|
|
235
|
+
}),
|
|
236
|
+
notifyOnGraphFailure: typeof kgConfig.notifyOnGraphFailure === "boolean" ? kgConfig.notifyOnGraphFailure : false,
|
|
237
|
+
connectConfig: {
|
|
238
|
+
minKeywordOverlap: readNumber(connectConfig, "minKeywordOverlap", 3, {
|
|
239
|
+
min: 1,
|
|
240
|
+
integer: true
|
|
241
|
+
}),
|
|
242
|
+
keywordScoreWeight: readNumber(connectConfig, "keywordScoreWeight", 1, { min: 0 }),
|
|
243
|
+
maxConnectionsPerChunk: readNumber(connectConfig, "maxConnectionsPerChunk", 10, {
|
|
244
|
+
min: 1,
|
|
245
|
+
integer: true
|
|
246
|
+
}),
|
|
247
|
+
minScoreThreshold: readNumber(connectConfig, "minScoreThreshold", .8, {
|
|
248
|
+
min: 0,
|
|
249
|
+
max: 1
|
|
250
|
+
}),
|
|
251
|
+
crossFileOnly: typeof connectConfig.crossFileOnly === "boolean" ? connectConfig.crossFileOnly : true,
|
|
252
|
+
maxContentOverlap: readNumber(connectConfig, "maxContentOverlap", .8, {
|
|
253
|
+
min: 0,
|
|
254
|
+
max: 1
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
145
259
|
//#endregion
|
|
146
|
-
export { assertKnowhereApiKey, formatPaymentRequiredMessage, isPaymentRequiredError, knowherePluginConfigSchema, persistApiKey, readPersistedApiKey, resolveKnowhereConfig };
|
|
260
|
+
export { assertKnowhereApiKey, formatPaymentRequiredMessage, isPaymentRequiredError, knowherePluginConfigSchema, persistApiKey, readPersistedApiKey, resolveKnowhereConfig, resolveKnowledgeGraphConfig };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { __esmMin } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
//#region src/connect-builder.ts
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a keyword to lowercase
|
|
5
|
+
* Equivalent to Python: _normalize_keyword
|
|
6
|
+
*/
|
|
7
|
+
function normalizeKeyword(keyword) {
|
|
8
|
+
return keyword.toLowerCase().trim();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Extract file key from a chunk path
|
|
12
|
+
* Equivalent to Python: _extract_file_key
|
|
13
|
+
*
|
|
14
|
+
* Example: "Default_Root/report.docx/Chapter 1" -> "report.docx"
|
|
15
|
+
*/
|
|
16
|
+
function extractFileKey(path) {
|
|
17
|
+
const parts = path.split("/");
|
|
18
|
+
if (parts.length >= 2) return parts[1];
|
|
19
|
+
return path;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build inverted keyword index: keyword -> [chunk_ids]
|
|
23
|
+
* Equivalent to Python: _build_keyword_index
|
|
24
|
+
*/
|
|
25
|
+
function buildKeywordIndex(chunks) {
|
|
26
|
+
const index = /* @__PURE__ */ new Map();
|
|
27
|
+
for (const chunk of chunks) {
|
|
28
|
+
const keywords = chunk.metadata.keywords || [];
|
|
29
|
+
for (const kw of keywords) {
|
|
30
|
+
const normalized = normalizeKeyword(kw);
|
|
31
|
+
if (!index.has(normalized)) index.set(normalized, /* @__PURE__ */ new Set());
|
|
32
|
+
index.get(normalized).add(chunk.chunk_id);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return index;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get keywords from a chunk with fallback to tokens
|
|
39
|
+
* Equivalent to Python: _get_keywords
|
|
40
|
+
*/
|
|
41
|
+
function getKeywords(chunk) {
|
|
42
|
+
const keywords = chunk.metadata.keywords || [];
|
|
43
|
+
if (keywords.length > 0) return keywords;
|
|
44
|
+
const tokens = chunk.metadata.tokens || [];
|
|
45
|
+
if (tokens.length > 0) return tokens.filter((token) => {
|
|
46
|
+
if (token.length <= 1) return false;
|
|
47
|
+
if (/^\d+$/.test(token)) return false;
|
|
48
|
+
return true;
|
|
49
|
+
});
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Compute character-length-weighted keyword overlap score
|
|
54
|
+
* Equivalent to Python: _compute_keyword_score
|
|
55
|
+
*
|
|
56
|
+
* Formula: sum(len(kw)^2 for kw in shared_keywords) / sqrt(sum(len(kw)^2 for kw in all_keywords_A) * sum(..._B))
|
|
57
|
+
*/
|
|
58
|
+
function computeKeywordScore(keywordsA, keywordsB, sharedKeywords) {
|
|
59
|
+
if (sharedKeywords.length === 0) return 0;
|
|
60
|
+
const sharedWeight = sharedKeywords.reduce((sum, kw) => sum + kw.length ** 2, 0);
|
|
61
|
+
const weightA = keywordsA.reduce((sum, kw) => sum + kw.length ** 2, 0);
|
|
62
|
+
const weightB = keywordsB.reduce((sum, kw) => sum + kw.length ** 2, 0);
|
|
63
|
+
if (weightA === 0 || weightB === 0) return 0;
|
|
64
|
+
const score = sharedWeight / Math.sqrt(weightA * weightB);
|
|
65
|
+
return Math.min(score, 1);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check if two strings are near-duplicates using SequenceMatcher
|
|
69
|
+
* Equivalent to Python: difflib.SequenceMatcher(None, a, b).ratio()
|
|
70
|
+
*
|
|
71
|
+
* Uses Longest Common Subsequence (LCS) algorithm
|
|
72
|
+
*/
|
|
73
|
+
function sequenceMatcherRatio(a, b) {
|
|
74
|
+
if (a === b) return 1;
|
|
75
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
76
|
+
const m = a.length;
|
|
77
|
+
const n = b.length;
|
|
78
|
+
const dp = Array(m + 1).fill(0).map(() => Array(n + 1).fill(0));
|
|
79
|
+
for (let i = 1; i <= m; i++) for (let j = 1; j <= n; j++) if (a[i - 1] === b[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
|
|
80
|
+
else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
|
|
81
|
+
const lcsLength = dp[m][n];
|
|
82
|
+
const totalLength = m + n;
|
|
83
|
+
return 2 * lcsLength / totalLength;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Main function to build connections between chunks
|
|
87
|
+
* Equivalent to Python: build_connections
|
|
88
|
+
*/
|
|
89
|
+
function buildConnections(chunks, config, logger) {
|
|
90
|
+
if (chunks.length < 2) {
|
|
91
|
+
logger?.info("Not enough chunks for connection building (need >= 2)");
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
logger?.info(`Building connections for ${chunks.length} chunks`);
|
|
95
|
+
const keywordIndex = buildKeywordIndex(chunks);
|
|
96
|
+
const chunkById = /* @__PURE__ */ new Map();
|
|
97
|
+
for (const chunk of chunks) chunkById.set(chunk.chunk_id, chunk);
|
|
98
|
+
const chunksByFile = /* @__PURE__ */ new Map();
|
|
99
|
+
for (const chunk of chunks) {
|
|
100
|
+
const fileKey = extractFileKey(chunk.path);
|
|
101
|
+
if (!chunksByFile.has(fileKey)) chunksByFile.set(fileKey, /* @__PURE__ */ new Set());
|
|
102
|
+
chunksByFile.get(fileKey).add(chunk.chunk_id);
|
|
103
|
+
}
|
|
104
|
+
const candidatePairs = /* @__PURE__ */ new Map();
|
|
105
|
+
for (const chunk of chunks) {
|
|
106
|
+
const normalizedKeywords = getKeywords(chunk).map(normalizeKeyword);
|
|
107
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
108
|
+
for (const kw of normalizedKeywords) {
|
|
109
|
+
const matchingChunks = keywordIndex.get(kw);
|
|
110
|
+
if (matchingChunks) {
|
|
111
|
+
for (const targetId of matchingChunks) if (targetId !== chunk.chunk_id) candidates.add(targetId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (candidates.size > 0) candidatePairs.set(chunk.chunk_id, candidates);
|
|
115
|
+
}
|
|
116
|
+
logger?.info(`Found ${candidatePairs.size} chunks with candidate connections`);
|
|
117
|
+
const connections = [];
|
|
118
|
+
const seenPairs = /* @__PURE__ */ new Set();
|
|
119
|
+
for (const [sourceId, targetIds] of candidatePairs) {
|
|
120
|
+
const sourceChunk = chunkById.get(sourceId);
|
|
121
|
+
if (!sourceChunk) continue;
|
|
122
|
+
const sourceKeywords = getKeywords(sourceChunk);
|
|
123
|
+
sourceKeywords.map(normalizeKeyword);
|
|
124
|
+
const sourceFileKey = extractFileKey(sourceChunk.path);
|
|
125
|
+
for (const targetId of targetIds) {
|
|
126
|
+
const targetChunk = chunkById.get(targetId);
|
|
127
|
+
if (!targetChunk) continue;
|
|
128
|
+
const pairKey = sourceId < targetId ? `${sourceId}::${targetId}` : `${targetId}::${sourceId}`;
|
|
129
|
+
if (seenPairs.has(pairKey)) continue;
|
|
130
|
+
seenPairs.add(pairKey);
|
|
131
|
+
const targetFileKey = extractFileKey(targetChunk.path);
|
|
132
|
+
if (config.crossFileOnly && sourceFileKey === targetFileKey) continue;
|
|
133
|
+
const contentRatio = sequenceMatcherRatio(sourceChunk.content.slice(0, 500), targetChunk.content.slice(0, 500));
|
|
134
|
+
if (contentRatio >= config.maxContentOverlap) {
|
|
135
|
+
logger?.info(`Skipping near-duplicate pair: ${sourceChunk.path} <-> ${targetChunk.path} (ratio: ${contentRatio.toFixed(2)})`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const targetKeywords = getKeywords(targetChunk);
|
|
139
|
+
const targetNormalized = targetKeywords.map(normalizeKeyword);
|
|
140
|
+
const sharedKeywords = [];
|
|
141
|
+
for (const kw of sourceKeywords) {
|
|
142
|
+
const normalized = normalizeKeyword(kw);
|
|
143
|
+
if (targetNormalized.includes(normalized)) sharedKeywords.push(kw);
|
|
144
|
+
}
|
|
145
|
+
if (sharedKeywords.length < config.minKeywordOverlap) continue;
|
|
146
|
+
const finalScore = computeKeywordScore(sourceKeywords, targetKeywords, sharedKeywords) * config.keywordScoreWeight;
|
|
147
|
+
if (finalScore < config.minScoreThreshold) continue;
|
|
148
|
+
connections.push({
|
|
149
|
+
source: sourceId,
|
|
150
|
+
target: targetId,
|
|
151
|
+
relation: "related",
|
|
152
|
+
score: finalScore,
|
|
153
|
+
sharedKeywords
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
logger?.info(`Built ${connections.length} connections before filtering`);
|
|
158
|
+
connections.sort((a, b) => b.score - a.score);
|
|
159
|
+
if (config.maxConnectionsPerChunk > 0) {
|
|
160
|
+
const connectionsByChunk = /* @__PURE__ */ new Map();
|
|
161
|
+
for (const conn of connections) {
|
|
162
|
+
if (!connectionsByChunk.has(conn.source)) connectionsByChunk.set(conn.source, []);
|
|
163
|
+
if (!connectionsByChunk.has(conn.target)) connectionsByChunk.set(conn.target, []);
|
|
164
|
+
connectionsByChunk.get(conn.source).push(conn);
|
|
165
|
+
connectionsByChunk.get(conn.target).push(conn);
|
|
166
|
+
}
|
|
167
|
+
const kept = /* @__PURE__ */ new Set();
|
|
168
|
+
for (const [chunkId, conns] of connectionsByChunk) {
|
|
169
|
+
const topN = conns.sort((a, b) => b.score - a.score).slice(0, config.maxConnectionsPerChunk);
|
|
170
|
+
for (const conn of topN) kept.add(conn);
|
|
171
|
+
}
|
|
172
|
+
const filtered = connections.filter((conn) => kept.has(conn));
|
|
173
|
+
logger?.info(`Filtered to ${filtered.length} connections after maxConnectionsPerChunk limit`);
|
|
174
|
+
return filtered;
|
|
175
|
+
}
|
|
176
|
+
return connections;
|
|
177
|
+
}
|
|
178
|
+
var init_connect_builder = __esmMin((() => {}));
|
|
179
|
+
//#endregion
|
|
180
|
+
init_connect_builder();
|
|
181
|
+
export { buildConnections, init_connect_builder };
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { __toESM } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { require_nodejieba } from "./node_modules/.pnpm/nodejieba@2.6.0/node_modules/nodejieba/index.js";
|
|
3
|
+
//#region src/graph-builder.ts
|
|
4
|
+
var import_nodejieba = /* @__PURE__ */ __toESM(require_nodejieba(), 1);
|
|
5
|
+
/**
|
|
6
|
+
* Extract file key from chunk path
|
|
7
|
+
*/
|
|
8
|
+
function extractFileKey(path) {
|
|
9
|
+
const parts = path.split("/");
|
|
10
|
+
if (parts.length >= 2) return parts[1];
|
|
11
|
+
return path;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Extract label from chunk path (last segment)
|
|
15
|
+
*/
|
|
16
|
+
function extractLabel(path) {
|
|
17
|
+
const parts = path.split("/");
|
|
18
|
+
return parts[parts.length - 1] || path;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Extract tokens from text using jieba
|
|
22
|
+
* Equivalent to Python: _extract_tokens_from_content
|
|
23
|
+
*/
|
|
24
|
+
function extractTokensFromContent(content, jiebaInitialized) {
|
|
25
|
+
const cleanContent = content.replace(/<[^>]*>/g, " ");
|
|
26
|
+
if (!jiebaInitialized) return cleanContent.split(/\s+/).filter((w) => w.length > 1);
|
|
27
|
+
try {
|
|
28
|
+
return import_nodejieba.cut(cleanContent).filter((token) => {
|
|
29
|
+
if (token.length <= 1) return false;
|
|
30
|
+
if (/^\d+$/.test(token)) return false;
|
|
31
|
+
if (/^[^\w\u4e00-\u9fa5]+$/.test(token)) return false;
|
|
32
|
+
return true;
|
|
33
|
+
});
|
|
34
|
+
} catch (error) {
|
|
35
|
+
return cleanContent.split(/\s+/).filter((w) => w.length > 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Compute TF-IDF top keywords for a file
|
|
40
|
+
* Equivalent to Python: _compute_tfidf_top_keywords
|
|
41
|
+
*/
|
|
42
|
+
function computeTfidfTopKeywords(fileChunks, allChunks, topK, jiebaInitialized) {
|
|
43
|
+
if (fileChunks.length === 0) return [];
|
|
44
|
+
const fileTokens = [];
|
|
45
|
+
for (const chunk of fileChunks) {
|
|
46
|
+
const tokens = extractTokensFromContent(chunk.content, jiebaInitialized);
|
|
47
|
+
fileTokens.push(...tokens);
|
|
48
|
+
}
|
|
49
|
+
if (fileTokens.length === 0) return [];
|
|
50
|
+
const termFreq = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const token of fileTokens) {
|
|
52
|
+
const normalized = token.toLowerCase();
|
|
53
|
+
termFreq.set(normalized, (termFreq.get(normalized) || 0) + 1);
|
|
54
|
+
}
|
|
55
|
+
const docFreq = /* @__PURE__ */ new Map();
|
|
56
|
+
for (const chunk of allChunks) {
|
|
57
|
+
const tokens = new Set(extractTokensFromContent(chunk.content, jiebaInitialized).map((t) => t.toLowerCase()));
|
|
58
|
+
for (const token of tokens) docFreq.set(token, (docFreq.get(token) || 0) + 1);
|
|
59
|
+
}
|
|
60
|
+
const totalDocs = allChunks.length;
|
|
61
|
+
const tfidfScores = [];
|
|
62
|
+
for (const [term, tf] of termFreq) {
|
|
63
|
+
const df = docFreq.get(term) || 1;
|
|
64
|
+
const tfidf = tf * Math.log(totalDocs / df);
|
|
65
|
+
tfidfScores.push({
|
|
66
|
+
term,
|
|
67
|
+
score: tfidf
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
tfidfScores.sort((a, b) => b.score - a.score);
|
|
71
|
+
return tfidfScores.slice(0, topK).map((item) => item.term);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Compute file importance based on chunk count and usage heat
|
|
75
|
+
* Equivalent to Python: _compute_file_importance
|
|
76
|
+
*
|
|
77
|
+
* Formula: (chunk_count_weight * normalized_chunk_count) + (heat_weight * usage_heat)
|
|
78
|
+
* Usage heat uses exponential decay: sum(e^(-decay * days_since_access))
|
|
79
|
+
*/
|
|
80
|
+
function computeFileImportance(fileKey, fileChunks, allChunks, chunkStats, decayRate = .01) {
|
|
81
|
+
const chunkCountWeight = .3;
|
|
82
|
+
const heatWeight = .7;
|
|
83
|
+
const fileChunkCount = fileChunks.length;
|
|
84
|
+
const maxChunkCount = Math.max(...getAllChunkCountsByFile(allChunks));
|
|
85
|
+
const normalizedChunkCount = maxChunkCount > 0 ? fileChunkCount / maxChunkCount : 0;
|
|
86
|
+
let usageHeat = 0;
|
|
87
|
+
const now = Date.now();
|
|
88
|
+
for (const chunk of fileChunks) {
|
|
89
|
+
const stats = chunkStats[chunk.chunk_id];
|
|
90
|
+
if (stats && stats.hit_count > 0) {
|
|
91
|
+
const daysSinceAccess = (now - (stats.last_accessed ? new Date(stats.last_accessed).getTime() : now)) / (1e3 * 60 * 60 * 24);
|
|
92
|
+
const decayedHitCount = stats.hit_count * Math.exp(-decayRate * daysSinceAccess);
|
|
93
|
+
usageHeat += decayedHitCount;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const normalizedHeat = Math.min(usageHeat / 100, 1);
|
|
97
|
+
const importance = chunkCountWeight * normalizedChunkCount + heatWeight * normalizedHeat;
|
|
98
|
+
return Math.min(importance, 1);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Helper: Get chunk counts by file
|
|
102
|
+
*/
|
|
103
|
+
function getAllChunkCountsByFile(chunks) {
|
|
104
|
+
const countsByFile = /* @__PURE__ */ new Map();
|
|
105
|
+
for (const chunk of chunks) {
|
|
106
|
+
const fileKey = extractFileKey(chunk.path);
|
|
107
|
+
countsByFile.set(fileKey, (countsByFile.get(fileKey) || 0) + 1);
|
|
108
|
+
}
|
|
109
|
+
return Array.from(countsByFile.values());
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Aggregate chunk-level connections into file-level edges
|
|
113
|
+
* Equivalent to Python: _aggregate_file_level_edges
|
|
114
|
+
*/
|
|
115
|
+
function aggregateFileLevelEdges(connections, chunkById, topN = 5) {
|
|
116
|
+
const filePairs = /* @__PURE__ */ new Map();
|
|
117
|
+
for (const conn of connections) {
|
|
118
|
+
const sourceChunk = chunkById.get(conn.source);
|
|
119
|
+
const targetChunk = chunkById.get(conn.target);
|
|
120
|
+
if (!sourceChunk || !targetChunk) continue;
|
|
121
|
+
const sourceFile = extractFileKey(sourceChunk.path);
|
|
122
|
+
const targetFile = extractFileKey(targetChunk.path);
|
|
123
|
+
if (sourceFile === targetFile) continue;
|
|
124
|
+
const pairKey = sourceFile < targetFile ? `${sourceFile}::${targetFile}` : `${targetFile}::${sourceFile}`;
|
|
125
|
+
if (!filePairs.has(pairKey)) filePairs.set(pairKey, []);
|
|
126
|
+
filePairs.get(pairKey).push(conn);
|
|
127
|
+
}
|
|
128
|
+
const fileEdges = [];
|
|
129
|
+
for (const [pairKey, conns] of filePairs) {
|
|
130
|
+
const [sourceFile, targetFile] = pairKey.split("::");
|
|
131
|
+
const avgScore = conns.reduce((sum, conn) => sum + conn.score, 0) / conns.length;
|
|
132
|
+
const topConns = conns.sort((a, b) => b.score - a.score).slice(0, topN).map((conn) => {
|
|
133
|
+
const sourceChunk = chunkById.get(conn.source);
|
|
134
|
+
const targetChunk = chunkById.get(conn.target);
|
|
135
|
+
return {
|
|
136
|
+
source_chunk: extractLabel(sourceChunk.path),
|
|
137
|
+
source_id: conn.source,
|
|
138
|
+
target_chunk: extractLabel(targetChunk.path),
|
|
139
|
+
target_id: conn.target,
|
|
140
|
+
relation: conn.relation,
|
|
141
|
+
score: conn.score
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
fileEdges.push({
|
|
145
|
+
source: sourceFile,
|
|
146
|
+
target: targetFile,
|
|
147
|
+
connection_count: conns.length,
|
|
148
|
+
avg_score: avgScore,
|
|
149
|
+
top_connections: topConns
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return fileEdges;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Main function to build knowledge graph
|
|
156
|
+
* Equivalent to Python: build_knowledge_graph
|
|
157
|
+
*/
|
|
158
|
+
function buildKnowledgeGraph(chunks, connections, chunkStats, jiebaInitialized, logger) {
|
|
159
|
+
logger?.info(`Building knowledge graph from ${chunks.length} chunks and ${connections.length} connections`);
|
|
160
|
+
const chunkById = /* @__PURE__ */ new Map();
|
|
161
|
+
for (const chunk of chunks) chunkById.set(chunk.chunk_id, chunk);
|
|
162
|
+
const chunksByFile = /* @__PURE__ */ new Map();
|
|
163
|
+
for (const chunk of chunks) {
|
|
164
|
+
const fileKey = extractFileKey(chunk.path);
|
|
165
|
+
if (!chunksByFile.has(fileKey)) chunksByFile.set(fileKey, []);
|
|
166
|
+
chunksByFile.get(fileKey).push(chunk);
|
|
167
|
+
}
|
|
168
|
+
const filesMetadata = {};
|
|
169
|
+
for (const [fileKey, fileChunks] of chunksByFile) {
|
|
170
|
+
const typeCount = {};
|
|
171
|
+
for (const chunk of fileChunks) {
|
|
172
|
+
const type = chunk.metadata.type || "text";
|
|
173
|
+
typeCount[type] = (typeCount[type] || 0) + 1;
|
|
174
|
+
}
|
|
175
|
+
const topKeywords = computeTfidfTopKeywords(fileChunks, chunks, 10, jiebaInitialized);
|
|
176
|
+
const importance = computeFileImportance(fileKey, fileChunks, chunks, chunkStats);
|
|
177
|
+
let topSummary = "";
|
|
178
|
+
for (const chunk of fileChunks) if (chunk.metadata.summary && typeof chunk.metadata.summary === "string") {
|
|
179
|
+
topSummary = chunk.metadata.summary;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
filesMetadata[fileKey] = {
|
|
183
|
+
chunks_count: fileChunks.length,
|
|
184
|
+
types: typeCount,
|
|
185
|
+
top_keywords: topKeywords,
|
|
186
|
+
top_summary: topSummary,
|
|
187
|
+
importance
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const fileEdges = aggregateFileLevelEdges(connections, chunkById, 5);
|
|
191
|
+
logger?.info(`Created graph with ${Object.keys(filesMetadata).length} files and ${fileEdges.length} edges`);
|
|
192
|
+
return {
|
|
193
|
+
version: "2.0",
|
|
194
|
+
stats: {
|
|
195
|
+
total_files: Object.keys(filesMetadata).length,
|
|
196
|
+
total_chunks: chunks.length,
|
|
197
|
+
total_cross_file_edges: fileEdges.length
|
|
198
|
+
},
|
|
199
|
+
files: filesMetadata,
|
|
200
|
+
edges: fileEdges
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
204
|
+
export { buildKnowledgeGraph };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { knowherePluginConfigSchema, readPersistedApiKey, resolveKnowhereConfig } from "./config.js";
|
|
1
|
+
import { knowherePluginConfigSchema, readPersistedApiKey, resolveKnowhereConfig, resolveKnowledgeGraphConfig } from "./config.js";
|
|
2
2
|
import { KnowhereStore } from "./store.js";
|
|
3
3
|
import { createKnowhereToolFactory } from "./tools.js";
|
|
4
|
+
import { KnowledgeGraphService } from "./kg-service.js";
|
|
4
5
|
//#region src/index.ts
|
|
5
6
|
const plugin = {
|
|
6
7
|
id: "knowhere-claw",
|
|
@@ -9,11 +10,19 @@ const plugin = {
|
|
|
9
10
|
configSchema: knowherePluginConfigSchema,
|
|
10
11
|
register(api) {
|
|
11
12
|
const config = resolveKnowhereConfig(api);
|
|
13
|
+
const kgConfig = resolveKnowledgeGraphConfig(api.pluginConfig && typeof api.pluginConfig === "object" ? api.pluginConfig : {});
|
|
12
14
|
const store = new KnowhereStore({
|
|
13
15
|
rootDir: config.storageDir,
|
|
14
16
|
scopeMode: config.scopeMode,
|
|
15
17
|
logger: api.logger
|
|
16
18
|
});
|
|
19
|
+
const kgService = new KnowledgeGraphService({
|
|
20
|
+
config: kgConfig,
|
|
21
|
+
logger: api.logger
|
|
22
|
+
});
|
|
23
|
+
kgService.initialize().catch((error) => {
|
|
24
|
+
api.logger.warn(`knowhere: knowledge graph service initialization failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
25
|
+
});
|
|
17
26
|
if (!config.apiKey) readPersistedApiKey(config.storageDir).then((persistedKey) => {
|
|
18
27
|
if (persistedKey) {
|
|
19
28
|
config.apiKey = persistedKey;
|
|
@@ -25,7 +34,8 @@ const plugin = {
|
|
|
25
34
|
api.registerTool(createKnowhereToolFactory({
|
|
26
35
|
api,
|
|
27
36
|
config,
|
|
28
|
-
store
|
|
37
|
+
store,
|
|
38
|
+
kgService
|
|
29
39
|
}), { names: [
|
|
30
40
|
"knowhere_ingest_document",
|
|
31
41
|
"knowhere_list_jobs",
|
|
@@ -37,7 +47,9 @@ const plugin = {
|
|
|
37
47
|
"knowhere_list_documents",
|
|
38
48
|
"knowhere_remove_document",
|
|
39
49
|
"knowhere_clear_scope",
|
|
40
|
-
"knowhere_set_api_key"
|
|
50
|
+
"knowhere_set_api_key",
|
|
51
|
+
"knowhere_kg_list",
|
|
52
|
+
"knowhere_kg_query"
|
|
41
53
|
] });
|
|
42
54
|
}
|
|
43
55
|
};
|