@dikolab/kbdb 0.3.0 → 0.3.1
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 +24 -43
- package/dist/bench/constants/corpus-defaults.constant.d.ts +3 -0
- package/dist/bench/functions/format-report.function.d.ts +11 -0
- package/dist/bench/functions/generate-corpus.function.d.ts +12 -0
- package/dist/bench/functions/measure-operation.function.d.ts +14 -0
- package/dist/bench/functions/seeded-rng.function.d.ts +11 -0
- package/dist/bench/functions/zipf-word.function.d.ts +13 -0
- package/dist/bench/index.d.ts +10 -0
- package/dist/bench/typings/bench-result.interface.d.ts +11 -0
- package/dist/bench/typings/bench-suite-result.interface.d.ts +10 -0
- package/dist/bench/typings/corpus-config.interface.d.ts +11 -0
- package/dist/bench/typings/corpus-section.interface.d.ts +9 -0
- package/dist/cli.cjs +63 -9
- package/dist/cli.cjs.map +2 -2
- package/dist/cli.mjs +63 -9
- package/dist/cli.mjs.map +2 -2
- package/dist/src/shared/auto-capture/classes/auto-capture-controller.class.d.ts +33 -0
- package/dist/src/shared/auto-capture/constants/auto-capture-defaults.constant.d.ts +8 -0
- package/dist/src/shared/auto-capture/functions/build-capture-prompt.function.d.ts +11 -0
- package/dist/src/shared/auto-capture/functions/evaluate-trigger.function.d.ts +12 -0
- package/dist/src/shared/auto-capture/index.d.ts +7 -0
- package/dist/src/shared/auto-capture/typings/auto-capture-config.interface.d.ts +13 -0
- package/dist/src/shared/auto-capture/typings/auto-capture-state.interface.d.ts +13 -0
- package/dist/src/shared/auto-capture/typings/auto-capture-trigger.interface.d.ts +7 -0
- package/dist/src/shared/cli/constants/global-help.constant.d.ts +8 -0
- package/dist/src/shared/cli/constants/leaf-help.constant.d.ts +7 -0
- package/dist/src/shared/cli/constants/memory-protocol-body.constant.d.ts +7 -0
- package/dist/src/shared/cli/constants/query-guidance-body.constant.d.ts +7 -0
- package/dist/src/shared/cli/constants/subcommand-help.constant.d.ts +8 -0
- package/dist/src/shared/cli/functions/collect-files.function.d.ts +13 -0
- package/dist/src/shared/cli/functions/compute-section-kbid.function.d.ts +15 -0
- package/dist/src/shared/cli/functions/format-mcp-output.function.d.ts +9 -0
- package/dist/src/shared/cli/functions/format-text-output.function.d.ts +9 -0
- package/dist/src/shared/cli/functions/generate-group-help.function.d.ts +11 -0
- package/dist/src/shared/cli/functions/handle-data-command.function.d.ts +16 -0
- package/dist/src/shared/cli/functions/handle-mcp.function.d.ts +15 -0
- package/dist/src/shared/cli/functions/handle-migrate.function.d.ts +15 -0
- package/dist/src/shared/cli/functions/hydrate-search-previews.function.d.ts +14 -0
- package/dist/src/shared/cli/functions/resolve-skill-names.function.d.ts +16 -0
- package/dist/src/shared/cli/functions/run-search.function.d.ts +1 -0
- package/dist/src/shared/cli/functions/version-gate.function.d.ts +15 -0
- package/dist/src/shared/cli/functions/wrap-command.function.d.ts +15 -0
- package/dist/src/shared/cli/typings/agent-create-client.interface.d.ts +42 -0
- package/dist/src/shared/cli/typings/agent-get-client.interface.d.ts +36 -0
- package/dist/src/shared/cli/typings/check-client.interface.d.ts +58 -0
- package/dist/src/shared/cli/typings/cli-deps.interface.d.ts +48 -0
- package/dist/src/shared/cli/typings/cli-options.interface.d.ts +2 -0
- package/dist/src/shared/cli/typings/disconnectable-client.interface.d.ts +26 -0
- package/dist/src/shared/cli/typings/dispatch-client.type.d.ts +27 -0
- package/dist/src/shared/cli/typings/learn-client.interface.d.ts +52 -0
- package/dist/src/shared/cli/typings/learn-io.interface.d.ts +5 -0
- package/dist/src/shared/cli/typings/search-client.interface.d.ts +71 -0
- package/dist/src/shared/embedding/classes/null-embedding-provider.class.d.ts +20 -0
- package/dist/src/shared/embedding/constants/near-duplicate-thresholds.constant.d.ts +15 -0
- package/dist/src/shared/embedding/functions/build-vector-index.function.d.ts +14 -0
- package/dist/src/shared/embedding/functions/cosine-similarity.function.d.ts +10 -0
- package/dist/src/shared/embedding/functions/detect-near-duplicates.function.d.ts +18 -0
- package/dist/src/shared/embedding/functions/jaccard-coefficient.function.d.ts +9 -0
- package/dist/src/shared/embedding/functions/read-vector-index-meta.function.d.ts +10 -0
- package/dist/src/shared/embedding/functions/rrf-fuse.function.d.ts +14 -0
- package/dist/src/shared/embedding/functions/search-vectors.function.d.ts +14 -0
- package/dist/src/shared/embedding/index.d.ts +16 -0
- package/dist/src/shared/embedding/typings/embedding-config.interface.d.ts +20 -0
- package/dist/src/shared/embedding/typings/embedding-provider.interface.d.ts +23 -0
- package/dist/src/shared/embedding/typings/near-duplicate-candidate.model.d.ts +23 -0
- package/dist/src/shared/embedding/typings/near-duplicate-result.model.d.ts +24 -0
- package/dist/src/shared/embedding/typings/vector-index-entry.model.d.ts +12 -0
- package/dist/src/shared/embedding/typings/vector-index-meta.model.d.ts +11 -0
- package/dist/src/shared/embedding/typings/vector-search-result.model.d.ts +7 -0
- package/dist/src/shared/mcp/constants/tool-agent-create.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-agent-delete.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-agent-get.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-agent-list.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-auto-capture-review.constant.d.ts +8 -0
- package/dist/src/shared/mcp/constants/tool-check.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-content.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-export.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-gc.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-learn.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-rebuild.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-recall.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-retrieve.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-search.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-skill-delete.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-skill-get.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-skill-learn.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-skill-list.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-status.constant.d.ts +3 -0
- package/dist/src/shared/mcp/constants/tool-unlearn.constant.d.ts +3 -0
- package/dist/src/shared/mcp/functions/as-boolean-or-undefined.function.d.ts +7 -0
- package/dist/src/shared/mcp/functions/as-string-array-or-undefined.function.d.ts +7 -0
- package/dist/src/shared/mcp/functions/as-string-array.function.d.ts +7 -0
- package/dist/src/shared/mcp/functions/as-string.function.d.ts +8 -0
- package/dist/src/shared/mcp/functions/build-skills-text.function.d.ts +18 -0
- package/dist/src/shared/mcp/functions/handle-agent-prompt.function.d.ts +14 -0
- package/dist/src/shared/mcp/functions/handle-mcp-request.function.d.ts +14 -0
- package/dist/src/shared/mcp/functions/handle-prompt-get.function.d.ts +4 -3
- package/dist/src/shared/mcp/functions/handle-skill-prompt.function.d.ts +16 -0
- package/dist/src/shared/mcp/functions/handle-tool-auto-capture-review.function.d.ts +12 -0
- package/dist/src/shared/mcp/functions/handle-tool-check.function.d.ts +11 -0
- package/dist/src/shared/mcp/functions/handle-tool-content.function.d.ts +12 -0
- package/dist/src/shared/mcp/functions/handle-tool-export.function.d.ts +12 -0
- package/dist/src/shared/mcp/functions/handle-tool-gc.function.d.ts +11 -0
- package/dist/src/shared/mcp/functions/handle-tool-learn.function.d.ts +12 -0
- package/dist/src/shared/mcp/functions/handle-tool-rebuild.function.d.ts +11 -0
- package/dist/src/shared/mcp/functions/handle-tool-retrieve.function.d.ts +12 -0
- package/dist/src/shared/mcp/functions/handle-tool-search.function.d.ts +13 -0
- package/dist/src/shared/mcp/functions/handle-tool-skill-delete.function.d.ts +12 -0
- package/dist/src/shared/mcp/functions/handle-tool-skill-get.function.d.ts +13 -0
- package/dist/src/shared/mcp/functions/handle-tool-skill-learn.function.d.ts +13 -0
- package/dist/src/shared/mcp/functions/handle-tool-skill-list.function.d.ts +11 -0
- package/dist/src/shared/mcp/functions/handle-tool-status.function.d.ts +11 -0
- package/dist/src/shared/mcp/functions/handle-tool-unlearn.function.d.ts +12 -0
- package/dist/src/shared/mcp/functions/parse-agent-meta.function.d.ts +14 -0
- package/dist/src/shared/mcp/functions/parse-skill-arguments.function.d.ts +11 -0
- package/dist/src/shared/mcp/functions/read-agent-meta.function.d.ts +17 -0
- package/dist/src/shared/mcp/functions/resolve-skill-refs.function.d.ts +23 -0
- package/dist/src/shared/mcp/functions/run-startup-health-check.function.d.ts +14 -0
- package/dist/src/shared/mcp/typings/mcp-capabilities.interface.d.ts +16 -0
- package/dist/src/shared/mcp/typings/mcp-client.interface.d.ts +2 -0
- package/dist/src/shared/mcp/typings/mcp-completion.interface.d.ts +43 -0
- package/dist/src/shared/mcp/typings/mcp-content-result.model.d.ts +9 -0
- package/dist/src/shared/mcp/typings/mcp-export-result.model.d.ts +11 -0
- package/dist/src/shared/mcp/typings/mcp-gc-result.model.d.ts +15 -0
- package/dist/src/shared/mcp/typings/mcp-integrity-check-result.model.d.ts +16 -0
- package/dist/src/shared/mcp/typings/mcp-integrity-error.model.d.ts +9 -0
- package/dist/src/shared/mcp/typings/mcp-notification.interface.d.ts +9 -0
- package/dist/src/shared/mcp/typings/mcp-rebuild-result.model.d.ts +9 -0
- package/dist/src/shared/mcp/typings/mcp-request.interface.d.ts +11 -0
- package/dist/src/shared/mcp/typings/mcp-resource-result.interface.d.ts +12 -0
- package/dist/src/shared/mcp/typings/mcp-resource-template.interface.d.ts +11 -0
- package/dist/src/shared/mcp/typings/mcp-response.interface.d.ts +18 -0
- package/dist/src/shared/mcp/typings/mcp-server-info.interface.d.ts +7 -0
- package/dist/src/shared/mcp/typings/mcp-server-state.interface.d.ts +16 -0
- package/dist/src/shared/mcp/typings/mcp-tool-annotations.interface.d.ts +32 -0
- package/dist/src/shared/mcp/typings/mcp-tool-definition.interface.d.ts +15 -0
- package/dist/src/shared/mcp/typings/mcp-tool-result.interface.d.ts +19 -0
- package/dist/src/shared/mcp/typings/mcp-worker-client.interface.d.ts +220 -0
- package/dist/src/shared/mcp/typings/tool-call-result.model.d.ts +17 -0
- package/dist/src/shared/sync/functions/build-import-report.function.d.ts +18 -0
- package/dist/src/shared/sync/functions/parse-export-entry.function.d.ts +11 -0
- package/dist/src/shared/sync/functions/resolve-conflict.function.d.ts +13 -0
- package/dist/src/shared/sync/functions/serialize-export-entry.function.d.ts +8 -0
- package/dist/src/shared/sync/index.d.ts +9 -0
- package/dist/src/shared/sync/typings/conflict-resolution.type.d.ts +8 -0
- package/dist/src/shared/sync/typings/export-entry.interface.d.ts +13 -0
- package/dist/src/shared/sync/typings/export-options.interface.d.ts +9 -0
- package/dist/src/shared/sync/typings/import-options.interface.d.ts +7 -0
- package/dist/src/shared/sync/typings/import-report.interface.d.ts +15 -0
- package/dist/src/shared/wasm-codec/functions/decode-one-recall-result.function.d.ts +14 -0
- package/dist/src/shared/wasm-codec/functions/decode-option-string.function.d.ts +12 -0
- package/dist/src/shared/wasm-codec/functions/decode-recall-document.function.d.ts +14 -0
- package/dist/src/shared/wasm-codec/functions/decode-recall-reference.function.d.ts +14 -0
- package/dist/src/shared/wasm-codec/functions/decode-recall-sibling.function.d.ts +13 -0
- package/dist/src/shared/wasm-codec/functions/decode-section-match.function.d.ts +15 -0
- package/dist/src/shared/wasm-codec/functions/decode-section-record-trailing.function.d.ts +14 -0
- package/dist/src/shared/wasm-codec/functions/decode-section-record.function.d.ts +14 -0
- package/dist/src/shared/wasm-codec/functions/decode-section-type.function.d.ts +13 -0
- package/dist/src/shared/wasm-codec/functions/decode-wasm-list.function.d.ts +17 -0
- package/dist/src/shared/wasm-codec/typings/add-section-input.model.d.ts +45 -0
- package/dist/src/shared/wasm-codec/typings/add-section-result.model.d.ts +27 -0
- package/dist/src/shared/wasm-codec/typings/document-manifest.model.d.ts +19 -0
- package/dist/src/shared/wasm-codec/typings/document-section.model.d.ts +12 -0
- package/dist/src/shared/wasm-codec/typings/item-decoder.type.d.ts +6 -0
- package/dist/src/shared/wasm-codec/typings/near-duplicate.model.d.ts +16 -0
- package/dist/src/shared/wasm-codec/typings/paged-search-result.model.d.ts +21 -0
- package/dist/src/shared/wasm-codec/typings/section-match.model.d.ts +31 -0
- package/dist/src/shared/wasm-codec/typings/section-record-trailing.model.d.ts +38 -0
- package/dist/src/shared/wasm-codec/typings/section-record.model.d.ts +66 -0
- package/dist/src/shared/wasm-codec/typings/section-type-result.model.d.ts +12 -0
- package/dist/src/shared/worker-client/functions/handle-ipc-data.function.d.ts +16 -0
- package/dist/src/shared/worker-client/functions/send-ipc-request.function.d.ts +19 -0
- package/dist/src/shared/worker-client/typings/add-section-result.model.d.ts +2 -0
- package/dist/src/shared/worker-client/typings/json-rpc-response.interface.d.ts +16 -0
- package/dist/src/shared/worker-client/typings/pending-call.interface.d.ts +7 -0
- package/dist/src/shared/worker-client/typings/recall-document.model.d.ts +16 -0
- package/dist/src/shared/worker-client/typings/recall-params.model.d.ts +15 -0
- package/dist/src/shared/worker-client/typings/recall-reference.model.d.ts +32 -0
- package/dist/src/shared/worker-client/typings/recall-sibling.model.d.ts +11 -0
- package/dist/src/shared/worker-client/typings/recall-single-result.model.d.ts +40 -0
- package/dist/src/shared/worker-daemon/classes/ipc-error.class.d.ts +17 -0
- package/dist/src/shared/worker-daemon/constants/wasm-method-map.constant.d.ts +16 -0
- package/dist/src/shared/worker-daemon/functions/build-ipc-error-response.function.d.ts +9 -0
- package/dist/src/shared/worker-daemon/functions/check-catalog-version.function.d.ts +9 -0
- package/dist/src/shared/worker-daemon/functions/check-preconditions.function.d.ts +10 -0
- package/dist/src/shared/worker-daemon/functions/detect-stale-pid.function.d.ts +15 -0
- package/dist/src/shared/worker-daemon/functions/dispatch-request.function.d.ts +35 -0
- package/dist/src/shared/worker-daemon/functions/handle-check-version.function.d.ts +23 -0
- package/dist/src/shared/worker-daemon/functions/handle-config-method.function.d.ts +11 -0
- package/dist/src/shared/worker-daemon/functions/handle-read-ops.function.d.ts +52 -0
- package/dist/src/shared/worker-daemon/functions/handle-write-ops.function.d.ts +44 -0
- package/dist/src/shared/worker-daemon/functions/parse-auto-capture-section.function.d.ts +14 -0
- package/dist/src/shared/worker-daemon/functions/parse-catalog-version.function.d.ts +10 -0
- package/dist/src/shared/worker-daemon/functions/parse-embedding-section.function.d.ts +13 -0
- package/dist/src/shared/worker-daemon/functions/parse-worker-toml.function.d.ts +11 -0
- package/dist/src/shared/worker-daemon/functions/run-startup-integrity-check.function.d.ts +18 -0
- package/dist/src/shared/worker-daemon/functions/scan-near-duplicates.function.d.ts +21 -0
- package/dist/src/shared/worker-daemon/functions/wasm-bridge.function.d.ts +51 -0
- package/dist/src/shared/worker-daemon/functions/wasm-memory-helpers.function.d.ts +22 -0
- package/dist/src/shared/worker-daemon/functions/write-lock.function.d.ts +32 -0
- package/dist/src/shared/worker-daemon/typings/allocator-ref.interface.d.ts +16 -0
- package/dist/src/shared/worker-daemon/typings/daemon-config.interface.d.ts +6 -0
- package/dist/src/shared/worker-daemon/typings/fs-adapter.interface.d.ts +22 -0
- package/dist/src/shared/worker-daemon/typings/handler-context.interface.d.ts +18 -0
- package/dist/src/shared/worker-daemon/typings/memory-ref.interface.d.ts +13 -0
- package/dist/src/shared/worker-daemon/typings/wasm-fn.type.d.ts +2 -0
- package/dist/src/shared/worker-daemon/typings/write-lock.interface.d.ts +15 -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/docs/details/mcp-server.md +4 -2
- package/docs/goals/auto-capture.md +378 -0
- package/docs/goals/benchmarking.md +296 -0
- package/docs/goals/concurrency.md +259 -0
- package/docs/goals/hybrid-search.md +436 -0
- package/docs/goals/semantic-dedup.md +229 -0
- package/docs/goals/sync.md +217 -0
- package/docs/modules/rust/fs-database/indexes/vectors.md +110 -0
- package/docs/modules/typescript/shared/auto-capture/module.md +73 -0
- package/docs/modules/typescript/shared/embedding/functions.md +94 -0
- package/docs/modules/typescript/shared/embedding/module.md +71 -0
- package/docs/modules/typescript/shared/embedding/typings.md +122 -0
- package/docs/overview.md +148 -166
- package/docs/release-notes/0.2.0.md +3 -3
- package/docs/release-notes/0.3.0.md +89 -0
- package/docs/release-notes/0.3.1.md +111 -0
- package/docs/release-notes/README.md +2 -0
- package/package.json +1 -1
- package/src/shared/auto-capture/classes/auto-capture-controller.class.ts +62 -0
- package/src/shared/auto-capture/constants/auto-capture-defaults.constant.ts +15 -0
- package/src/shared/auto-capture/functions/build-capture-prompt.function.ts +27 -0
- package/src/shared/auto-capture/functions/evaluate-trigger.function.ts +50 -0
- package/src/shared/auto-capture/index.ts +7 -0
- package/src/shared/auto-capture/typings/auto-capture-config.interface.ts +13 -0
- package/src/shared/auto-capture/typings/auto-capture-state.interface.ts +13 -0
- package/src/shared/auto-capture/typings/auto-capture-trigger.interface.ts +7 -0
- package/src/shared/cli/constants/global-help.constant.ts +73 -0
- package/src/shared/cli/constants/leaf-help.constant.ts +219 -0
- package/src/shared/cli/constants/memory-protocol-body.constant.ts +39 -0
- package/src/shared/cli/constants/query-guidance-body.constant.ts +37 -0
- package/src/shared/cli/constants/subcommand-help.constant.ts +195 -0
- package/src/shared/cli/functions/collect-files.function.ts +55 -0
- package/src/shared/cli/functions/compute-section-kbid.function.ts +49 -0
- package/src/shared/cli/functions/format-mcp-output.function.ts +41 -0
- package/src/shared/cli/functions/format-text-output.function.ts +42 -0
- package/src/shared/cli/functions/generate-group-help.function.ts +41 -0
- package/src/shared/cli/functions/handle-data-command.function.ts +67 -0
- package/src/shared/cli/functions/handle-mcp.function.ts +56 -0
- package/src/shared/cli/functions/handle-migrate.function.ts +64 -0
- package/src/shared/cli/functions/hydrate-search-previews.function.ts +29 -0
- package/src/shared/cli/functions/parse-args.function.ts +3 -0
- package/src/shared/cli/functions/resolve-skill-names.function.ts +43 -0
- package/src/shared/cli/functions/run-search.function.ts +2 -0
- package/src/shared/cli/functions/version-gate.function.ts +44 -0
- package/src/shared/cli/functions/wrap-command.function.ts +34 -0
- package/src/shared/cli/typings/agent-create-client.interface.ts +47 -0
- package/src/shared/cli/typings/agent-get-client.interface.ts +39 -0
- package/src/shared/cli/typings/check-client.interface.ts +66 -0
- package/src/shared/cli/typings/cli-deps.interface.ts +54 -0
- package/src/shared/cli/typings/cli-options.interface.ts +2 -0
- package/src/shared/cli/typings/disconnectable-client.interface.ts +29 -0
- package/src/shared/cli/typings/dispatch-client.type.ts +46 -0
- package/src/shared/cli/typings/learn-client.interface.ts +53 -0
- package/src/shared/cli/typings/learn-io.interface.ts +5 -0
- package/src/shared/cli/typings/search-client.interface.ts +73 -0
- package/src/shared/embedding/classes/null-embedding-provider.class.ts +29 -0
- package/src/shared/embedding/constants/near-duplicate-thresholds.constant.ts +17 -0
- package/src/shared/embedding/functions/build-vector-index.function.ts +79 -0
- package/src/shared/embedding/functions/cosine-similarity.function.ts +31 -0
- package/src/shared/embedding/functions/detect-near-duplicates.function.ts +69 -0
- package/src/shared/embedding/functions/jaccard-coefficient.function.ts +26 -0
- package/src/shared/embedding/functions/read-vector-index-meta.function.ts +44 -0
- package/src/shared/embedding/functions/rrf-fuse.function.ts +33 -0
- package/src/shared/embedding/functions/search-vectors.function.ts +59 -0
- package/src/shared/embedding/index.ts +20 -0
- package/src/shared/embedding/typings/embedding-config.interface.ts +23 -0
- package/src/shared/embedding/typings/embedding-provider.interface.ts +25 -0
- package/src/shared/embedding/typings/near-duplicate-candidate.model.ts +25 -0
- package/src/shared/embedding/typings/near-duplicate-result.model.ts +26 -0
- package/src/shared/embedding/typings/vector-index-entry.model.ts +13 -0
- package/src/shared/embedding/typings/vector-index-meta.model.ts +14 -0
- package/src/shared/embedding/typings/vector-search-result.model.ts +8 -0
- package/src/shared/mcp/classes/mcp-server.class.ts +6 -3
- package/src/shared/mcp/constants/tool-agent-create.constant.ts +39 -0
- package/src/shared/mcp/constants/tool-agent-delete.constant.ts +26 -0
- package/src/shared/mcp/constants/tool-agent-get.constant.ts +24 -0
- package/src/shared/mcp/constants/tool-agent-list.constant.ts +18 -0
- package/src/shared/mcp/constants/tool-auto-capture-review.constant.ts +32 -0
- package/src/shared/mcp/constants/tool-check.constant.ts +21 -0
- package/src/shared/mcp/constants/tool-content.constant.ts +29 -0
- package/src/shared/mcp/constants/tool-export.constant.ts +27 -0
- package/src/shared/mcp/constants/tool-gc.constant.ts +21 -0
- package/src/shared/mcp/constants/tool-learn.constant.ts +58 -0
- package/src/shared/mcp/constants/tool-rebuild.constant.ts +21 -0
- package/src/shared/mcp/constants/tool-recall.constant.ts +36 -0
- package/src/shared/mcp/constants/tool-retrieve.constant.ts +31 -0
- package/src/shared/mcp/constants/tool-search.constant.ts +51 -0
- package/src/shared/mcp/constants/tool-skill-delete.constant.ts +24 -0
- package/src/shared/mcp/constants/tool-skill-get.constant.ts +27 -0
- package/src/shared/mcp/constants/tool-skill-learn.constant.ts +37 -0
- package/src/shared/mcp/constants/tool-skill-list.constant.ts +18 -0
- package/src/shared/mcp/constants/tool-status.constant.ts +20 -0
- package/src/shared/mcp/constants/tool-unlearn.constant.ts +25 -0
- package/src/shared/mcp/functions/as-boolean-or-undefined.function.ts +11 -0
- package/src/shared/mcp/functions/as-string-array-or-undefined.function.ts +17 -0
- package/src/shared/mcp/functions/as-string-array.function.ts +15 -0
- package/src/shared/mcp/functions/as-string.function.ts +10 -0
- package/src/shared/mcp/functions/build-skills-text.function.ts +43 -0
- package/src/shared/mcp/functions/create-tool-definitions.function.ts +28 -0
- package/src/shared/mcp/functions/handle-agent-create.function.ts +1 -1
- package/src/shared/mcp/functions/handle-agent-prompt.function.ts +68 -0
- package/src/shared/mcp/functions/handle-mcp-request.function.ts +202 -0
- package/src/shared/mcp/functions/handle-prompt-get.function.ts +18 -12
- package/src/shared/mcp/functions/handle-skill-prompt.function.ts +44 -0
- package/src/shared/mcp/functions/handle-tool-auto-capture-review.function.ts +24 -0
- package/src/shared/mcp/functions/handle-tool-call.function.ts +18 -0
- package/src/shared/mcp/functions/handle-tool-check.function.ts +21 -0
- package/src/shared/mcp/functions/handle-tool-content.function.ts +23 -0
- package/src/shared/mcp/functions/handle-tool-export.function.ts +25 -0
- package/src/shared/mcp/functions/handle-tool-gc.function.ts +21 -0
- package/src/shared/mcp/functions/handle-tool-learn.function.ts +69 -0
- package/src/shared/mcp/functions/handle-tool-rebuild.function.ts +21 -0
- package/src/shared/mcp/functions/handle-tool-retrieve.function.ts +40 -0
- package/src/shared/mcp/functions/handle-tool-search.function.ts +47 -0
- package/src/shared/mcp/functions/handle-tool-skill-delete.function.ts +34 -0
- package/src/shared/mcp/functions/handle-tool-skill-get.function.ts +59 -0
- package/src/shared/mcp/functions/handle-tool-skill-learn.function.ts +61 -0
- package/src/shared/mcp/functions/handle-tool-skill-list.function.ts +39 -0
- package/src/shared/mcp/functions/handle-tool-status.function.ts +21 -0
- package/src/shared/mcp/functions/handle-tool-unlearn.function.ts +24 -0
- package/src/shared/mcp/functions/parse-agent-meta.function.ts +27 -0
- package/src/shared/mcp/functions/parse-skill-arguments.function.ts +36 -0
- package/src/shared/mcp/functions/read-agent-meta.function.ts +41 -0
- package/src/shared/mcp/functions/resolve-skill-refs.function.ts +50 -0
- package/src/shared/mcp/functions/run-startup-health-check.function.ts +34 -0
- package/src/shared/mcp/typings/mcp-capabilities.interface.ts +16 -0
- package/src/shared/mcp/typings/mcp-client.interface.ts +2 -0
- package/src/shared/mcp/typings/mcp-completion.interface.ts +45 -0
- package/src/shared/mcp/typings/mcp-content-result.model.ts +9 -0
- package/src/shared/mcp/typings/mcp-export-result.model.ts +11 -0
- package/src/shared/mcp/typings/mcp-gc-result.model.ts +15 -0
- package/src/shared/mcp/typings/mcp-integrity-check-result.model.ts +17 -0
- package/src/shared/mcp/typings/mcp-integrity-error.model.ts +15 -0
- package/src/shared/mcp/typings/mcp-notification.interface.ts +9 -0
- package/src/shared/mcp/typings/mcp-rebuild-result.model.ts +9 -0
- package/src/shared/mcp/typings/mcp-request.interface.ts +11 -0
- package/src/shared/mcp/typings/mcp-resource-result.interface.ts +12 -0
- package/src/shared/mcp/typings/mcp-resource-template.interface.ts +11 -0
- package/src/shared/mcp/typings/mcp-response.interface.ts +18 -0
- package/src/shared/mcp/typings/mcp-server-info.interface.ts +7 -0
- package/src/shared/mcp/typings/mcp-server-state.interface.ts +17 -0
- package/src/shared/mcp/typings/mcp-tool-annotations.interface.ts +32 -0
- package/src/shared/mcp/typings/mcp-tool-definition.interface.ts +16 -0
- package/src/shared/mcp/typings/mcp-tool-result.interface.ts +19 -0
- package/src/shared/mcp/typings/mcp-worker-client.interface.ts +243 -0
- package/src/shared/mcp/typings/tool-call-result.model.ts +18 -0
- package/src/shared/sync/functions/build-import-report.function.ts +40 -0
- package/src/shared/sync/functions/parse-export-entry.function.ts +45 -0
- package/src/shared/sync/functions/resolve-conflict.function.ts +31 -0
- package/src/shared/sync/functions/serialize-export-entry.function.ts +18 -0
- package/src/shared/sync/index.ts +9 -0
- package/src/shared/sync/typings/conflict-resolution.type.ts +8 -0
- package/src/shared/sync/typings/export-entry.interface.ts +13 -0
- package/src/shared/sync/typings/export-options.interface.ts +9 -0
- package/src/shared/sync/typings/import-options.interface.ts +7 -0
- package/src/shared/sync/typings/import-report.interface.ts +15 -0
- package/src/shared/wasm-codec/functions/decode-one-recall-result.function.ts +86 -0
- package/src/shared/wasm-codec/functions/decode-option-string.function.ts +24 -0
- package/src/shared/wasm-codec/functions/decode-recall-document.function.ts +59 -0
- package/src/shared/wasm-codec/functions/decode-recall-reference.function.ts +52 -0
- package/src/shared/wasm-codec/functions/decode-recall-sibling.function.ts +43 -0
- package/src/shared/wasm-codec/functions/decode-section-match.function.ts +80 -0
- package/src/shared/wasm-codec/functions/decode-section-record-trailing.function.ts +75 -0
- package/src/shared/wasm-codec/functions/decode-section-record.function.ts +85 -0
- package/src/shared/wasm-codec/functions/decode-section-type.function.ts +30 -0
- package/src/shared/wasm-codec/functions/decode-wasm-list.function.ts +31 -0
- package/src/shared/wasm-codec/typings/add-section-input.model.ts +45 -0
- package/src/shared/wasm-codec/typings/add-section-result.model.ts +28 -0
- package/src/shared/wasm-codec/typings/document-manifest.model.ts +20 -0
- package/src/shared/wasm-codec/typings/document-section.model.ts +12 -0
- package/src/shared/wasm-codec/typings/item-decoder.type.ts +10 -0
- package/src/shared/wasm-codec/typings/near-duplicate.model.ts +16 -0
- package/src/shared/wasm-codec/typings/paged-search-result.model.ts +22 -0
- package/src/shared/wasm-codec/typings/section-match.model.ts +31 -0
- package/src/shared/wasm-codec/typings/section-record-trailing.model.ts +38 -0
- package/src/shared/wasm-codec/typings/section-record.model.ts +66 -0
- package/src/shared/wasm-codec/typings/section-type-result.model.ts +12 -0
- package/src/shared/worker-client/functions/handle-ipc-data.function.ts +49 -0
- package/src/shared/worker-client/functions/send-ipc-request.function.ts +39 -0
- package/src/shared/worker-client/typings/add-section-result.model.ts +2 -0
- package/src/shared/worker-client/typings/json-rpc-response.interface.ts +17 -0
- package/src/shared/worker-client/typings/pending-call.interface.ts +7 -0
- package/src/shared/worker-client/typings/recall-document.model.ts +16 -0
- package/src/shared/worker-client/typings/recall-params.model.ts +15 -0
- package/src/shared/worker-client/typings/recall-reference.model.ts +32 -0
- package/src/shared/worker-client/typings/recall-sibling.model.ts +11 -0
- package/src/shared/worker-client/typings/recall-single-result.model.ts +41 -0
- package/src/shared/worker-daemon/classes/ipc-error.class.ts +22 -0
- package/src/shared/worker-daemon/constants/wasm-method-map.constant.ts +69 -0
- package/src/shared/worker-daemon/functions/build-ipc-error-response.function.ts +16 -0
- package/src/shared/worker-daemon/functions/check-catalog-version.function.ts +54 -0
- package/src/shared/worker-daemon/functions/check-preconditions.function.ts +28 -0
- package/src/shared/worker-daemon/functions/detect-stale-pid.function.ts +33 -0
- package/src/shared/worker-daemon/functions/dispatch-request.function.ts +190 -0
- package/src/shared/worker-daemon/functions/handle-check-version.function.ts +74 -0
- package/src/shared/worker-daemon/functions/handle-config-method.function.ts +27 -0
- package/src/shared/worker-daemon/functions/handle-read-ops.function.ts +236 -0
- package/src/shared/worker-daemon/functions/handle-write-ops.function.ts +257 -0
- package/src/shared/worker-daemon/functions/parse-auto-capture-section.function.ts +51 -0
- package/src/shared/worker-daemon/functions/parse-catalog-version.function.ts +20 -0
- package/src/shared/worker-daemon/functions/parse-embedding-section.function.ts +38 -0
- package/src/shared/worker-daemon/functions/parse-worker-toml.function.ts +104 -0
- package/src/shared/worker-daemon/functions/run-startup-integrity-check.function.ts +55 -0
- package/src/shared/worker-daemon/functions/scan-near-duplicates.function.ts +92 -0
- package/src/shared/worker-daemon/functions/wasm-bridge.function.ts +144 -0
- package/src/shared/worker-daemon/functions/wasm-memory-helpers.function.ts +41 -0
- package/src/shared/worker-daemon/functions/write-lock.function.ts +49 -0
- package/src/shared/worker-daemon/typings/allocator-ref.interface.ts +16 -0
- package/src/shared/worker-daemon/typings/daemon-config.interface.ts +7 -0
- package/src/shared/worker-daemon/typings/fs-adapter.interface.ts +22 -0
- package/src/shared/worker-daemon/typings/handler-context.interface.ts +19 -0
- package/src/shared/worker-daemon/typings/memory-ref.interface.ts +13 -0
- package/src/shared/worker-daemon/typings/wasm-fn.type.ts +2 -0
- package/src/shared/worker-daemon/typings/write-lock.interface.ts +13 -0
- package/src/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/src/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Concurrent Write Safety
|
|
2
|
+
|
|
3
|
+
*One writer at a time, unlimited concurrent readers --
|
|
4
|
+
formalizing the locking model, multi-daemon prevention,
|
|
5
|
+
crash recovery, and stress-test methodology.*
|
|
6
|
+
|
|
7
|
+
## Goal
|
|
8
|
+
|
|
9
|
+
The worker daemon serializes all write operations
|
|
10
|
+
through a single-writer lock. Multiple concurrent
|
|
11
|
+
readers proceed without any lock. This document
|
|
12
|
+
formalizes the locking model, multi-daemon prevention,
|
|
13
|
+
atomic write guarantees, crash recovery, and
|
|
14
|
+
stress-test methodology.
|
|
15
|
+
|
|
16
|
+
This goal addresses gap #3 from the issue
|
|
17
|
+
[2026-06-23 Opus 4.8 Second Brain Review](../issues/2026-06-23-opus-48-second-brain-review.md):
|
|
18
|
+
the single-writer lock in the worker daemon must be
|
|
19
|
+
validated under concurrent load before concurrent
|
|
20
|
+
multi-agent use can be trusted.
|
|
21
|
+
|
|
22
|
+
## Single-Writer Lock
|
|
23
|
+
|
|
24
|
+
The daemon acquires an exclusive file lock on
|
|
25
|
+
`kbdb-{ctx}.lock` in the OS temporary directory during
|
|
26
|
+
write operations. The lock file uses the same context
|
|
27
|
+
ID as the PID file and IPC socket (see
|
|
28
|
+
[Worker Daemon](worker-daemon.md) for context ID
|
|
29
|
+
derivation).
|
|
30
|
+
|
|
31
|
+
- **Read operations** -- search, recall, retrieve,
|
|
32
|
+
content, dbStatus, and listByType -- proceed without
|
|
33
|
+
acquiring the lock. Concurrent read requests from
|
|
34
|
+
multiple worker client connections are fully parallel.
|
|
35
|
+
- **Write operations** -- addSection, updateSection,
|
|
36
|
+
removeSection, groupSections, removeGrouping,
|
|
37
|
+
initDirectory, gc, rebuildIndexes, and export --
|
|
38
|
+
acquire the exclusive lock before calling the
|
|
39
|
+
corresponding WASM export. If another write is
|
|
40
|
+
already in progress, the new write queues behind the
|
|
41
|
+
lock and waits.
|
|
42
|
+
- The lock is held only for the duration of a single
|
|
43
|
+
write operation. It is released immediately after
|
|
44
|
+
the operation completes. It is never held across
|
|
45
|
+
multiple operations or across client connections.
|
|
46
|
+
- The locking model is implemented in TypeScript inside
|
|
47
|
+
the worker daemon (`src/shared/worker-daemon/`), not
|
|
48
|
+
inside any WASM module.
|
|
49
|
+
|
|
50
|
+
This model is equivalent to SQLite's default locking:
|
|
51
|
+
readers never block, and writers take turns one at a
|
|
52
|
+
time.
|
|
53
|
+
|
|
54
|
+
### Write Operations Subject to the Lock
|
|
55
|
+
|
|
56
|
+
| IPC Method | WASM Export |
|
|
57
|
+
|--------------------------|----------------------------|
|
|
58
|
+
| `addSection` | `worker_add_section` |
|
|
59
|
+
| `updateSection` | `worker_update_section` |
|
|
60
|
+
| `removeSection` | `worker_remove_section` |
|
|
61
|
+
| `groupSections` | `worker_group_sections` |
|
|
62
|
+
| `removeGrouping` | `worker_remove_grouping` |
|
|
63
|
+
| `initDirectory` | `worker_init_directory` |
|
|
64
|
+
| `gc` | `worker_garbage_collect` |
|
|
65
|
+
| `rebuildIndexes` | `worker_rebuild_indexes` |
|
|
66
|
+
| `export` | `db_export` |
|
|
67
|
+
|
|
68
|
+
## Multi-Daemon Prevention
|
|
69
|
+
|
|
70
|
+
Each database context gets exactly one daemon process
|
|
71
|
+
at a time, enforced by a PID file keyed to the context
|
|
72
|
+
ID.
|
|
73
|
+
|
|
74
|
+
- The PID file is named `kbdb-{ctx}.pid` and lives in
|
|
75
|
+
the OS temporary directory. Its presence means a
|
|
76
|
+
daemon for that context is either running or died
|
|
77
|
+
without cleaning up.
|
|
78
|
+
- Before spawning a new daemon, the worker client reads
|
|
79
|
+
the PID file (if present) and checks whether the
|
|
80
|
+
recorded process is alive.
|
|
81
|
+
- **PID file absent** -- no running daemon; spawn a
|
|
82
|
+
new one.
|
|
83
|
+
- **PID file present, process alive** -- connect to
|
|
84
|
+
the existing daemon; do not spawn.
|
|
85
|
+
- **PID file present, process dead** -- stale PID
|
|
86
|
+
file from a prior crash; remove the file and spawn
|
|
87
|
+
a new daemon.
|
|
88
|
+
- The daemon writes its PID file only after all startup
|
|
89
|
+
preconditions pass and the WASM module is loaded
|
|
90
|
+
successfully. See [Worker Daemon](worker-daemon.md)
|
|
91
|
+
for the full startup sequence.
|
|
92
|
+
- On graceful shutdown, the daemon removes its PID
|
|
93
|
+
file before exiting.
|
|
94
|
+
|
|
95
|
+
This protocol ensures that the same database directory
|
|
96
|
+
is never served by two concurrent daemon processes.
|
|
97
|
+
|
|
98
|
+
## Atomic Write Guarantees
|
|
99
|
+
|
|
100
|
+
All file writes in the database use the atomic
|
|
101
|
+
write pattern: content is written to a temporary file
|
|
102
|
+
first, then the temporary file is renamed to the final
|
|
103
|
+
path. Rename is an atomic operation on all supported
|
|
104
|
+
filesystems (POSIX and Windows NTFS).
|
|
105
|
+
|
|
106
|
+
- **Section files** (`sections/{prefix}/{kbid}.sec`)
|
|
107
|
+
are written to `sections/{prefix}/{kbid}.sec.tmp`
|
|
108
|
+
then renamed.
|
|
109
|
+
- **Document manifests** (`documents/{docid}.toml`)
|
|
110
|
+
are written to `documents/{docid}.toml.tmp` then
|
|
111
|
+
renamed.
|
|
112
|
+
- **Index files** (`indexes/terms.idx`, etc.) are
|
|
113
|
+
rebuilt to temporary paths then renamed into place.
|
|
114
|
+
- **Catalog** (`catalog.toml`) is written last,
|
|
115
|
+
after all data files are in place. A crash
|
|
116
|
+
before the catalog rename leaves the catalog
|
|
117
|
+
consistent with the previous complete state.
|
|
118
|
+
|
|
119
|
+
If the daemon crashes mid-write, the temporary file
|
|
120
|
+
is orphaned but the original file is intact. On next
|
|
121
|
+
daemon startup, orphaned temporary files (matching
|
|
122
|
+
`*.tmp`) in the database directory are cleaned up.
|
|
123
|
+
|
|
124
|
+
The atomic write pattern is specified in
|
|
125
|
+
[Database](database.md) under Storage Design.
|
|
126
|
+
|
|
127
|
+
## Crash Recovery
|
|
128
|
+
|
|
129
|
+
The table below describes every identified failure
|
|
130
|
+
scenario, the resulting disk state, and the recovery
|
|
131
|
+
action.
|
|
132
|
+
|
|
133
|
+
| Scenario | State After Crash | Recovery |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| Crash during section write | `*.sec.tmp` orphaned, original `.sec` intact | Startup cleans `*.tmp` files |
|
|
136
|
+
| Crash during index rebuild | Partial `*.idx.tmp`, originals intact | Startup cleans `*.tmp`; next `rebuildIndexes` overwrites |
|
|
137
|
+
| Crash during GC | Some unreferenced sections deleted, others not | Re-run `gc`; idempotent |
|
|
138
|
+
| Crash during catalog write | `catalog.toml.tmp` orphaned, original intact | Startup cleans `*.tmp` |
|
|
139
|
+
| PID file not removed | Stale `kbdb-{ctx}.pid` on disk | Worker client detects dead process, removes PID, spawns new daemon |
|
|
140
|
+
| Lock file not released | `kbdb-{ctx}.lock` orphaned | Daemon startup acquires the exclusive lock fresh; OS releases orphaned file locks when the process that held them exits |
|
|
141
|
+
| WASM crash inside write | Partial in-memory state, temp file may exist | Daemon exits; startup cleans `*.tmp`; next operation starts clean |
|
|
142
|
+
|
|
143
|
+
All recovery actions are automatic. No manual
|
|
144
|
+
intervention is required for any scenario in this
|
|
145
|
+
table.
|
|
146
|
+
|
|
147
|
+
## Stress Test Specification
|
|
148
|
+
|
|
149
|
+
The following test harness validates concurrent write
|
|
150
|
+
safety. It must pass on both Deno and Node.js runtimes
|
|
151
|
+
before a release can claim concurrent safety.
|
|
152
|
+
|
|
153
|
+
### Setup
|
|
154
|
+
|
|
155
|
+
1. Create a fresh, empty database directory.
|
|
156
|
+
2. Prepare N unique documents (N in the range 10--50).
|
|
157
|
+
Each document must have distinct content to avoid
|
|
158
|
+
content-address collisions that would make section
|
|
159
|
+
count verification meaningless.
|
|
160
|
+
|
|
161
|
+
### Execution
|
|
162
|
+
|
|
163
|
+
3. Launch N concurrent `kbdb learn` invocations, all
|
|
164
|
+
targeting the same database directory. Each
|
|
165
|
+
invocation learns one of the N unique documents.
|
|
166
|
+
4. Use a process pool or parallel shell to launch all
|
|
167
|
+
N invocations simultaneously -- not sequentially.
|
|
168
|
+
5. Wait for all N invocations to complete. Record any
|
|
169
|
+
non-zero exit codes as failures.
|
|
170
|
+
|
|
171
|
+
### Verification
|
|
172
|
+
|
|
173
|
+
6. Run `kbdb check` against the database.
|
|
174
|
+
The response must have `ok: true`. Any errors in the
|
|
175
|
+
response are test failures.
|
|
176
|
+
7. Query the section count. The count must equal the
|
|
177
|
+
expected number of sections derived from the N
|
|
178
|
+
documents (no duplicates from race conditions, no
|
|
179
|
+
losses from interleaved writes).
|
|
180
|
+
8. Verify that no section has a checksum mismatch.
|
|
181
|
+
A mismatch indicates a torn write -- the atomic
|
|
182
|
+
rename pattern failed or was bypassed.
|
|
183
|
+
|
|
184
|
+
### Pass Criteria
|
|
185
|
+
|
|
186
|
+
| Check | Expected Result |
|
|
187
|
+
|---|---|
|
|
188
|
+
| All `kbdb learn` exit codes | `0` |
|
|
189
|
+
| `kbdb check` response | `ok: true`, zero errors |
|
|
190
|
+
| Section count | Exactly the expected count |
|
|
191
|
+
| Checksum mismatches | Zero |
|
|
192
|
+
|
|
193
|
+
### Runtime Matrix
|
|
194
|
+
|
|
195
|
+
Run the full harness on both runtimes:
|
|
196
|
+
|
|
197
|
+
| Runtime | Command prefix |
|
|
198
|
+
|---|---|
|
|
199
|
+
| Node.js >= 20 | `node dist/kbdb.mjs` |
|
|
200
|
+
| Deno | `deno run --allow-all src/cli.ts` |
|
|
201
|
+
|
|
202
|
+
Both must pass. A failure on one runtime but not the
|
|
203
|
+
other indicates a runtime-specific locking bug.
|
|
204
|
+
|
|
205
|
+
## Edge Cases
|
|
206
|
+
|
|
207
|
+
### Two CLI Invocations Through the Same Daemon
|
|
208
|
+
|
|
209
|
+
When two `kbdb` CLI processes connect to the same
|
|
210
|
+
daemon (same database directory), their write requests
|
|
211
|
+
share the single-writer lock automatically. No user
|
|
212
|
+
action is required. The second write waits for the
|
|
213
|
+
first to complete.
|
|
214
|
+
|
|
215
|
+
### MCP Server Connections
|
|
216
|
+
|
|
217
|
+
An MCP server connection routes all requests through
|
|
218
|
+
a worker client to the daemon, the same as a CLI
|
|
219
|
+
invocation. Multiple MCP client connections routed to
|
|
220
|
+
the same daemon share the write lock:
|
|
221
|
+
|
|
222
|
+
- Concurrent read requests from multiple MCP clients
|
|
223
|
+
are served in parallel.
|
|
224
|
+
- Concurrent write requests from multiple MCP clients
|
|
225
|
+
are serialized through the lock one at a time.
|
|
226
|
+
|
|
227
|
+
There is no per-connection or per-client lock; the
|
|
228
|
+
lock is global to the daemon process.
|
|
229
|
+
|
|
230
|
+
### Direct File Access
|
|
231
|
+
|
|
232
|
+
Accessing or modifying `.kbdb` files directly -- via
|
|
233
|
+
text editor, shell commands, or any process other than
|
|
234
|
+
the daemon -- is not supported. Direct writes bypass
|
|
235
|
+
the single-writer lock and the atomic write pattern,
|
|
236
|
+
and may corrupt the database. All mutations must go
|
|
237
|
+
through the daemon's IPC API.
|
|
238
|
+
|
|
239
|
+
## Design Constraints
|
|
240
|
+
|
|
241
|
+
- **Per-daemon locking, not per-file** -- The lock
|
|
242
|
+
covers all writes to a database context, not writes
|
|
243
|
+
to individual files. This means writes to unrelated
|
|
244
|
+
sections still serialize behind the same lock. The
|
|
245
|
+
simplicity of a single lock outweighs the throughput
|
|
246
|
+
cost at current scale. If per-section parallelism
|
|
247
|
+
becomes necessary, this constraint is the place to
|
|
248
|
+
revisit.
|
|
249
|
+
- **Single-machine only** -- The locking model
|
|
250
|
+
relies on OS-level file locks and process identity
|
|
251
|
+
on a single machine. It provides no guarantees across
|
|
252
|
+
network filesystems or multiple machines. Cross-machine
|
|
253
|
+
scenarios require an external sync mechanism (see
|
|
254
|
+
[Sync](sync.md) when available).
|
|
255
|
+
- **Lock implemented in TypeScript** -- The write lock
|
|
256
|
+
is managed by the TypeScript worker daemon layer, not
|
|
257
|
+
by any WASM module. WASM modules have no knowledge of
|
|
258
|
+
concurrent callers; they process one call at a time
|
|
259
|
+
through the host.
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# Hybrid Search -- Lexical + Vector Retrieval
|
|
2
|
+
|
|
3
|
+
*Optional vector retrieval path alongside BM25F, fused
|
|
4
|
+
with RRF for best-of-both ranking.*
|
|
5
|
+
|
|
6
|
+
## Goal
|
|
7
|
+
|
|
8
|
+
The current retrieval mode is lexical search: BM25F with
|
|
9
|
+
stemming and synonym expansion. It works well for
|
|
10
|
+
structured documentation where terminology is consistent
|
|
11
|
+
-- the agent searches "authentication" and the indexed
|
|
12
|
+
content uses the same word.
|
|
13
|
+
|
|
14
|
+
Lexical search has a ceiling, however. It misses
|
|
15
|
+
associative recall when terminology diverges between the
|
|
16
|
+
time content was stored and the time it is retrieved.
|
|
17
|
+
Example: an agent stores "we chose Postgres because of
|
|
18
|
+
JSONB" and later searches "database rationale" -- lexical
|
|
19
|
+
search misses it because none of the indexed tokens
|
|
20
|
+
(`postgres`, `chose`, `jsonb`) overlap with the query
|
|
21
|
+
tokens (`database`, `rationale`). Vector search finds
|
|
22
|
+
it because the embedding of the query is geometrically
|
|
23
|
+
close to the embedding of the stored sentence.
|
|
24
|
+
|
|
25
|
+
This gap is identified as the critical lexical-only
|
|
26
|
+
ceiling in
|
|
27
|
+
[Opus 4.8 Second Brain Review](../issues/2026-06-23-opus-48-second-brain-review.md)
|
|
28
|
+
(gap #1). Hybrid search closes it by adding an optional
|
|
29
|
+
vector retrieval path alongside the existing lexical
|
|
30
|
+
path, fusing both ranked lists using Reciprocal Rank
|
|
31
|
+
Fusion (RRF) for a final result set that benefits from
|
|
32
|
+
both modes.
|
|
33
|
+
|
|
34
|
+
## Architecture
|
|
35
|
+
|
|
36
|
+
Two retrieval paths run in parallel. The vector path
|
|
37
|
+
runs entirely in TypeScript. No WASM code is added or
|
|
38
|
+
modified.
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Query → ┌─ Lexical path (WASM) ─→ BM25F ranked list ─┐
|
|
42
|
+
│ ├─→ RRF Fusion → Final results
|
|
43
|
+
└─ Vector path (TS) ─→ Cosine ranked list ──┘
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The WASM boundary is untouched. `query-parser.wasm`
|
|
47
|
+
remains a pure-computation lexical module. `kb-worker.wasm`
|
|
48
|
+
continues to orchestrate lexical retrieval via
|
|
49
|
+
`fs-database.wasm` exactly as today. No new WASM crate,
|
|
50
|
+
no new WASM export, and no new host import is needed for
|
|
51
|
+
the vector path.
|
|
52
|
+
|
|
53
|
+
The TypeScript daemon layer adds the vector path as an
|
|
54
|
+
independent retrieval step that runs after the lexical
|
|
55
|
+
path completes (or concurrently if the runtime allows).
|
|
56
|
+
The fused list is assembled in TypeScript before the
|
|
57
|
+
response is returned to the worker client.
|
|
58
|
+
|
|
59
|
+
## EmbeddingProvider Interface
|
|
60
|
+
|
|
61
|
+
### Why TypeScript, Not WASM
|
|
62
|
+
|
|
63
|
+
Three reasons embeddings are computed in TypeScript
|
|
64
|
+
rather than in WASM:
|
|
65
|
+
|
|
66
|
+
1. `wasm32-unknown-unknown` has no network I/O. Calling
|
|
67
|
+
an embedding API from WASM is impossible without a
|
|
68
|
+
host bridge that would defeat the purpose of running
|
|
69
|
+
in WASM.
|
|
70
|
+
2. Embedding models are too large for WASM. A typical
|
|
71
|
+
all-MiniLM-L6-v2 model is ~90 MB. Loading that inside
|
|
72
|
+
the WASM sandbox on every daemon startup is
|
|
73
|
+
impractical.
|
|
74
|
+
3. TypeScript allows pluggable backends. An interface-based
|
|
75
|
+
design lets the daemon swap providers (local ONNX,
|
|
76
|
+
remote API) without changing any WASM code.
|
|
77
|
+
|
|
78
|
+
### Interface Specification
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface EmbeddingProvider {
|
|
82
|
+
embed(texts: string[]): Promise<Float32Array[]>;
|
|
83
|
+
dimensions(): number;
|
|
84
|
+
modelName(): string;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
| Member | Description |
|
|
89
|
+
|--------------|----------------------------------------------|
|
|
90
|
+
| `embed` | Compute embeddings for a batch of input texts. Returns one `Float32Array` per input, each of length `dimensions()`. |
|
|
91
|
+
| `dimensions` | Fixed embedding dimensionality for this provider. All vectors stored under the same model must have this length. |
|
|
92
|
+
| `modelName` | Stable identifier for the model. Used for stale-detection when the configured model changes. |
|
|
93
|
+
|
|
94
|
+
### Implementations
|
|
95
|
+
|
|
96
|
+
Three concrete implementations are specified.
|
|
97
|
+
|
|
98
|
+
**`NullEmbeddingProvider`** -- no-op, returns empty
|
|
99
|
+
arrays. The default when no `[embedding]` section is
|
|
100
|
+
present in `worker.toml`. Requesting `vector` or
|
|
101
|
+
`hybrid` search mode with this provider returns a
|
|
102
|
+
structured error rather than silently returning empty
|
|
103
|
+
results. Satisfies POLA: the absence of configuration
|
|
104
|
+
does not silently degrade results.
|
|
105
|
+
|
|
106
|
+
**`OnnxEmbeddingProvider`** -- local offline inference
|
|
107
|
+
using ONNX Runtime. Default model: `all-MiniLM-L6-v2`
|
|
108
|
+
(384 dimensions). The model file is downloaded on first
|
|
109
|
+
use and cached in the OS user-data directory. Works on
|
|
110
|
+
both Deno and Node.js >= 20. No network dependency
|
|
111
|
+
after the initial model download. Suitable for
|
|
112
|
+
air-gapped or cost-sensitive deployments.
|
|
113
|
+
|
|
114
|
+
**`ApiEmbeddingProvider`** -- calls an external HTTP
|
|
115
|
+
embedding API. Compatible with OpenAI, Anthropic, and
|
|
116
|
+
any endpoint that accepts a `POST /embeddings` request
|
|
117
|
+
with a JSON body `{ "input": string[] }` and returns
|
|
118
|
+
`{ "data": [{ "embedding": number[] }] }`. Configured
|
|
119
|
+
via `worker.toml`. The API key is read from an
|
|
120
|
+
environment variable named by `api_key_env`.
|
|
121
|
+
|
|
122
|
+
## Vector Storage
|
|
123
|
+
|
|
124
|
+
### New Index Files
|
|
125
|
+
|
|
126
|
+
Two new files are added to `indexes/` alongside the
|
|
127
|
+
existing index files. They follow the same rebuild
|
|
128
|
+
semantics as `terms.idx`, `positions.idx`, and
|
|
129
|
+
`corpus.dat`: derived data, rebuildable from section
|
|
130
|
+
content, excluded from version control.
|
|
131
|
+
|
|
132
|
+
**`vectors.idx`** -- binary, fixed-width records.
|
|
133
|
+
|
|
134
|
+
Header layout:
|
|
135
|
+
|
|
136
|
+
| Bytes | Field | Type | Description |
|
|
137
|
+
|-------|----------------|--------|-------------------------------|
|
|
138
|
+
| 0-3 | magic | u8[4] | `b"KBVX"` -- format sentinel |
|
|
139
|
+
| 4 | version | u8 | Format version, currently `1` |
|
|
140
|
+
| 5-6 | dimensions | u16 | Vector length per record |
|
|
141
|
+
| 7-10 | record_count | u32 | Total number of records |
|
|
142
|
+
|
|
143
|
+
Each record immediately follows the header:
|
|
144
|
+
|
|
145
|
+
| Bytes | Field | Type | Description |
|
|
146
|
+
|----------------|----------------|----------------|-------------------|
|
|
147
|
+
| 0-15 | kbid_hash | u8[16] | First 16 bytes of the section kbid, used as a compact lookup key |
|
|
148
|
+
| 16 onwards | embedding | f32[dimensions]| Raw embedding vector |
|
|
149
|
+
|
|
150
|
+
Record size = `16 + dimensions * 4` bytes. All records
|
|
151
|
+
are the same size, enabling O(1) offset computation by
|
|
152
|
+
record index and binary search by kbid hash.
|
|
153
|
+
|
|
154
|
+
**`vectors-meta.toml`** -- human-readable metadata.
|
|
155
|
+
|
|
156
|
+
```toml
|
|
157
|
+
[vectors]
|
|
158
|
+
model_name = "all-MiniLM-L6-v2"
|
|
159
|
+
dimensions = 384
|
|
160
|
+
version = 1
|
|
161
|
+
last_built = "2026-06-23T10:00:00Z"
|
|
162
|
+
section_count = 2847
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
| Field | Description |
|
|
166
|
+
|-----------------|-------------------------------------------|
|
|
167
|
+
| `model_name` | Model name from `EmbeddingProvider.modelName()`. Used for stale detection. |
|
|
168
|
+
| `dimensions` | Must match the `dimensions` header in `vectors.idx`. |
|
|
169
|
+
| `version` | `vectors.idx` format version. |
|
|
170
|
+
| `last_built` | ISO 8601 timestamp of the last rebuild. |
|
|
171
|
+
| `section_count` | Number of sections embedded. |
|
|
172
|
+
|
|
173
|
+
### Updated Directory Layout
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
.kbdb/
|
|
177
|
+
└── indexes/
|
|
178
|
+
├── meta.toml
|
|
179
|
+
├── terms.idx
|
|
180
|
+
├── positions.idx
|
|
181
|
+
├── corpus.dat
|
|
182
|
+
├── references.idx
|
|
183
|
+
├── vectors.idx # new -- binary embedding store
|
|
184
|
+
└── vectors-meta.toml # new -- embedding metadata
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Embedding Lifecycle
|
|
188
|
+
|
|
189
|
+
### Learn Time
|
|
190
|
+
|
|
191
|
+
When a section is added via `kbdb learn`, the lexical
|
|
192
|
+
indexing pipeline runs first (unchanged). After lexical
|
|
193
|
+
indexing completes, the daemon asynchronously computes
|
|
194
|
+
an embedding for the section using the configured
|
|
195
|
+
`EmbeddingProvider`.
|
|
196
|
+
|
|
197
|
+
The embedding input is the concatenation of the
|
|
198
|
+
section's title and body content:
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
{title}\n{content}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The title is prepended because it carries strong
|
|
205
|
+
semantic weight (it receives a 2.0x BM25F field weight
|
|
206
|
+
for the same reason). Concatenating both fields gives
|
|
207
|
+
the embedding model the same semantic signal that BM25F
|
|
208
|
+
heading-weight gives to lexical scoring.
|
|
209
|
+
|
|
210
|
+
Sections with no body content (binary sections where
|
|
211
|
+
content is base64) embed only the title and
|
|
212
|
+
description. Sections with neither title nor body
|
|
213
|
+
content are not embedded.
|
|
214
|
+
|
|
215
|
+
Embedding is best-effort at learn time: if the provider
|
|
216
|
+
fails for a section, the section is still stored
|
|
217
|
+
lexically. A warning is emitted in the learn response
|
|
218
|
+
(`vector_embedding_failed: true`).
|
|
219
|
+
|
|
220
|
+
### Rebuild
|
|
221
|
+
|
|
222
|
+
`kbdb rebuild` regenerates all vector embeddings from
|
|
223
|
+
section content alongside the existing lexical index
|
|
224
|
+
rebuild. Sections are embedded in batches of up to 64
|
|
225
|
+
to respect provider rate limits. The `vectors.idx` and
|
|
226
|
+
`vectors-meta.toml` files are written atomically after
|
|
227
|
+
all embeddings are computed.
|
|
228
|
+
|
|
229
|
+
### Stale Detection
|
|
230
|
+
|
|
231
|
+
When the daemon starts, it reads `vectors-meta.toml`
|
|
232
|
+
and compares `model_name` to the currently configured
|
|
233
|
+
provider's `modelName()`. If they differ, the vector
|
|
234
|
+
index is marked stale. Stale vector indexes are not
|
|
235
|
+
used for retrieval. Search falls back to lexical-only
|
|
236
|
+
with a warning field in the response:
|
|
237
|
+
`vector_index_stale: true`.
|
|
238
|
+
|
|
239
|
+
The agent or operator must run `kbdb rebuild` to
|
|
240
|
+
regenerate vectors with the new model before hybrid or
|
|
241
|
+
vector search resumes.
|
|
242
|
+
|
|
243
|
+
## Score Fusion
|
|
244
|
+
|
|
245
|
+
### Reciprocal Rank Fusion (RRF)
|
|
246
|
+
|
|
247
|
+
RRF combines the lexical ranked list and the vector
|
|
248
|
+
ranked list into a single fused list without requiring
|
|
249
|
+
score normalization. BM25F scores and cosine similarity
|
|
250
|
+
scores live on different scales and cannot be directly
|
|
251
|
+
added -- RRF sidesteps this by working on ranks rather
|
|
252
|
+
than scores.
|
|
253
|
+
|
|
254
|
+
Formula:
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
score(d) = 1/(k + rank_lexical(d)) + 1/(k + rank_vector(d))
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Where:
|
|
261
|
+
|
|
262
|
+
- `k = 60` (standard default, configurable via
|
|
263
|
+
`worker.toml` as `rrf_k`)
|
|
264
|
+
- `rank_lexical(d)` is the 1-based rank of document `d`
|
|
265
|
+
in the BM25F result list, or infinity if `d` does not
|
|
266
|
+
appear in the lexical results
|
|
267
|
+
- `rank_vector(d)` is the 1-based rank of document `d`
|
|
268
|
+
in the cosine similarity result list, or infinity if
|
|
269
|
+
`d` does not appear in the vector results
|
|
270
|
+
- A rank of infinity contributes 0 to the sum (since
|
|
271
|
+
`1/(k + ∞) = 0`)
|
|
272
|
+
|
|
273
|
+
Documents appearing in only one result set receive full
|
|
274
|
+
contribution from that set and zero from the other.
|
|
275
|
+
Documents appearing in both receive a higher combined
|
|
276
|
+
score than either path could produce alone, naturally
|
|
277
|
+
surfacing cross-path agreement.
|
|
278
|
+
|
|
279
|
+
The final result list is sorted by RRF score descending.
|
|
280
|
+
|
|
281
|
+
### Why RRF
|
|
282
|
+
|
|
283
|
+
- Parameter-light: `k = 60` is the well-established
|
|
284
|
+
default from the original RRF paper (Cormack et al.,
|
|
285
|
+
2009). It rarely needs tuning.
|
|
286
|
+
- No normalization: BM25F scores and cosine similarity
|
|
287
|
+
are not comparable in magnitude. RRF requires only
|
|
288
|
+
rank order, not the scores themselves.
|
|
289
|
+
- Robust: adding a low-quality second path cannot hurt
|
|
290
|
+
the top results badly because RRF dampens rank
|
|
291
|
+
contributions as `k` is approached.
|
|
292
|
+
|
|
293
|
+
## Search Mode Parameter
|
|
294
|
+
|
|
295
|
+
A new `search_mode` parameter controls which retrieval
|
|
296
|
+
paths are active for a given search request.
|
|
297
|
+
|
|
298
|
+
| Value | Retrieval behaviour | Embedding provider required |
|
|
299
|
+
|------------|---------------------------------------------|-----------------------------|
|
|
300
|
+
| `lexical` | Lexical path only. Current behaviour. Default. | No |
|
|
301
|
+
| `vector` | Vector path only. Cosine similarity ranking. | Yes |
|
|
302
|
+
| `hybrid` | Both paths, RRF fusion. | Yes |
|
|
303
|
+
|
|
304
|
+
The default is `lexical`. Existing integrations that do
|
|
305
|
+
not supply `search_mode` are unchanged. This is a
|
|
306
|
+
strict backward-compatibility guarantee.
|
|
307
|
+
|
|
308
|
+
Requesting `vector` or `hybrid` when no embedding
|
|
309
|
+
provider is configured (i.e. `NullEmbeddingProvider` is
|
|
310
|
+
active) returns a structured error:
|
|
311
|
+
|
|
312
|
+
```json
|
|
313
|
+
{
|
|
314
|
+
"error": "Vector search requires a configured embedding provider",
|
|
315
|
+
"code": "EMBEDDING_PROVIDER_NOT_CONFIGURED"
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## CLI and MCP Surface
|
|
320
|
+
|
|
321
|
+
### CLI
|
|
322
|
+
|
|
323
|
+
The `search` subcommand gains an optional `--mode` flag:
|
|
324
|
+
|
|
325
|
+
```
|
|
326
|
+
kbdb search "database rationale"
|
|
327
|
+
kbdb search --mode hybrid "database rationale"
|
|
328
|
+
kbdb search --mode vector "database rationale"
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Omitting `--mode` defaults to `lexical`. The flag is
|
|
332
|
+
not shown in the short help unless an embedding provider
|
|
333
|
+
is configured.
|
|
334
|
+
|
|
335
|
+
### MCP
|
|
336
|
+
|
|
337
|
+
The `search` MCP tool gains an optional `mode` parameter
|
|
338
|
+
(string enum: `"lexical" | "vector" | "hybrid"`). The
|
|
339
|
+
parameter is documented as optional in the tool schema
|
|
340
|
+
with a default of `"lexical"`.
|
|
341
|
+
|
|
342
|
+
### Response Envelope
|
|
343
|
+
|
|
344
|
+
`PagedSearchResult` gains two new fields:
|
|
345
|
+
|
|
346
|
+
| Field | Type | Description |
|
|
347
|
+
|--------------------|--------|---------------------------------|
|
|
348
|
+
| `search_mode` | string | The mode that was requested: `"lexical"`, `"vector"`, or `"hybrid"` |
|
|
349
|
+
| `retrieval_method` | string | The mode that was actually used: `"lexical"`, `"vector"`, or `"hybrid"`. Differs from `search_mode` when a fallback occurred (e.g. stale vector index forced `"lexical"`). |
|
|
350
|
+
|
|
351
|
+
Both fields are always present in the response,
|
|
352
|
+
including when `search_mode` was not supplied (in which
|
|
353
|
+
case both fields are `"lexical"`).
|
|
354
|
+
|
|
355
|
+
## Configuration
|
|
356
|
+
|
|
357
|
+
`worker.toml` gains an `[embedding]` section:
|
|
358
|
+
|
|
359
|
+
```toml
|
|
360
|
+
[embedding]
|
|
361
|
+
provider = "onnx" # "onnx" | "api" | "none"
|
|
362
|
+
model = "all-MiniLM-L6-v2"
|
|
363
|
+
dimensions = 384
|
|
364
|
+
rrf_k = 60 # RRF parameter k
|
|
365
|
+
|
|
366
|
+
# API provider only:
|
|
367
|
+
api_url = ""
|
|
368
|
+
api_key_env = "KBDB_API_KEY"
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
| Key | Default | Description |
|
|
372
|
+
|---------------|----------------------|------------------------------|
|
|
373
|
+
| `provider` | `"none"` | Which `EmbeddingProvider` implementation to use |
|
|
374
|
+
| `model` | `"all-MiniLM-L6-v2"` | Model name, passed to the provider |
|
|
375
|
+
| `dimensions` | `384` | Embedding vector length |
|
|
376
|
+
| `rrf_k` | `60` | RRF constant `k` |
|
|
377
|
+
| `api_url` | `""` | Base URL for API provider |
|
|
378
|
+
| `api_key_env` | `"KBDB_API_KEY"` | Environment variable holding the API key |
|
|
379
|
+
|
|
380
|
+
When `[embedding]` is absent from `worker.toml`,
|
|
381
|
+
`provider` defaults to `"none"` and `NullEmbeddingProvider`
|
|
382
|
+
is used.
|
|
383
|
+
|
|
384
|
+
## Fallback Behaviour
|
|
385
|
+
|
|
386
|
+
Three fallback conditions are defined. Each is surfaced
|
|
387
|
+
in the search response with a specific warning field
|
|
388
|
+
rather than silently degrading.
|
|
389
|
+
|
|
390
|
+
**No embedding provider configured.**
|
|
391
|
+
`search_mode` defaults to `lexical`. Requesting `hybrid`
|
|
392
|
+
or `vector` returns a structured error with code
|
|
393
|
+
`EMBEDDING_PROVIDER_NOT_CONFIGURED`. No silent fallback
|
|
394
|
+
occurs -- the caller receives an actionable error
|
|
395
|
+
message.
|
|
396
|
+
|
|
397
|
+
**Stale vector index (model mismatch).**
|
|
398
|
+
When `vectors-meta.toml` model name does not match the
|
|
399
|
+
configured provider's `modelName()`, the daemon marks
|
|
400
|
+
the vector index stale. Any search request that would
|
|
401
|
+
use the vector path falls back to `lexical`. The
|
|
402
|
+
response includes `retrieval_method: "lexical"` and
|
|
403
|
+
`vector_index_stale: true`. The correct remediation is
|
|
404
|
+
`kbdb rebuild`.
|
|
405
|
+
|
|
406
|
+
**Embedding failure during learn.**
|
|
407
|
+
If the embedding provider returns an error for a section
|
|
408
|
+
during learn, the section is stored lexically without an
|
|
409
|
+
embedding. The learn response includes
|
|
410
|
+
`vector_embedding_failed: true`. The section will
|
|
411
|
+
appear in lexical results but not in vector or hybrid
|
|
412
|
+
results until a rebuild is run.
|
|
413
|
+
|
|
414
|
+
## Provider Tradeoffs
|
|
415
|
+
|
|
416
|
+
| Aspect | ONNX (local) | API (cloud) |
|
|
417
|
+
|---------------|---------------------------|------------------------------|
|
|
418
|
+
| Latency | ~10 ms/embed | ~100 ms/embed |
|
|
419
|
+
| Offline | Yes | No |
|
|
420
|
+
| Cost | Free | Per-token |
|
|
421
|
+
| Quality | Good (384 dimensions) | Excellent (1536+ dimensions) |
|
|
422
|
+
| Setup | Model download on first use | API key required |
|
|
423
|
+
| Dual runtime | Deno + Node.js >= 20 | Deno + Node.js >= 20 |
|
|
424
|
+
|
|
425
|
+
Both providers implement the same `EmbeddingProvider`
|
|
426
|
+
interface. The daemon interacts only with the interface.
|
|
427
|
+
|
|
428
|
+
## Design Constraints
|
|
429
|
+
|
|
430
|
+
| Constraint | Details |
|
|
431
|
+
|-----------------------|------------------------------------------------|
|
|
432
|
+
| WASM purity | `query-parser.wasm` remains pure lexical computation with no I/O. No new WASM crate or export is added. |
|
|
433
|
+
| Backward compatibility | Default `search_mode` is `lexical`. Callers that do not supply the parameter receive identical behaviour to today. |
|
|
434
|
+
| File-based storage | `vectors.idx` and `vectors-meta.toml` follow the same derived-and-rebuildable pattern as all other index files. |
|
|
435
|
+
| Dual runtime | `EmbeddingProvider` and all embedding logic must work on Deno and Node.js >= 20. No Node-specific or Deno-specific APIs in the implementation. |
|
|
436
|
+
| No new WASM deps | All new dependencies are TypeScript-side only. The WASM modules (`fs-database.wasm`, `query-parser.wasm`, `kb-worker.wasm`) are not recompiled for this feature. |
|