@dikolab/kbdb 0.3.2 → 0.4.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 +92 -90
- package/dist/chunk-BJXEVALU.mjs +337 -0
- package/dist/chunk-BJXEVALU.mjs.map +7 -0
- package/dist/cli.cjs +1398 -378
- package/dist/cli.cjs.map +4 -4
- package/dist/cli.d.ts +9 -0
- package/dist/cli.mjs +1138 -342
- package/dist/cli.mjs.map +4 -4
- package/dist/kbdb-worker.cjs +1115 -135
- package/dist/kbdb-worker.cjs.map +4 -4
- package/dist/mod.cjs +351 -69
- package/dist/mod.cjs.map +4 -4
- package/dist/mod.d.ts +23 -2
- package/dist/mod.mjs +349 -68
- package/dist/mod.mjs.map +4 -4
- package/dist/src/shared/cli/functions/dispatch-command.function.d.ts +2 -1
- package/dist/src/shared/cli/functions/find-db.function.d.ts +7 -8
- package/dist/src/shared/cli/functions/handle-mcp.function.d.ts +1 -1
- package/dist/src/shared/cli/functions/parse-args.function.d.ts +4 -3
- package/dist/src/shared/cli/functions/resolve-kbid-prefix.function.d.ts +27 -0
- package/dist/src/shared/cli/functions/resolve-raw-db-path.function.d.ts +10 -0
- package/dist/src/shared/cli/functions/run-cli.function.d.ts +3 -1
- package/dist/src/shared/cli/functions/run-content.function.d.ts +8 -3
- package/dist/src/shared/cli/functions/run-import.function.d.ts +27 -0
- package/dist/src/shared/cli/functions/run-recall.function.d.ts +10 -4
- package/dist/src/shared/cli/functions/run-search.function.d.ts +7 -0
- package/dist/src/shared/cli/functions/run-unlearn.function.d.ts +9 -4
- package/dist/src/shared/cli/functions/run-worker-restart.function.d.ts +11 -0
- package/dist/src/shared/cli/functions/run-worker-stop.function.d.ts +11 -0
- package/dist/src/shared/cli/index.d.ts +2 -0
- package/dist/src/shared/cli/typings/cli-deps.interface.d.ts +4 -1
- package/dist/src/shared/cli/typings/cli-options.interface.d.ts +22 -0
- package/dist/src/shared/cli/typings/dispatch-client.type.d.ts +2 -1
- package/dist/src/shared/cli/typings/search-display.model.d.ts +6 -0
- package/dist/src/shared/embedding/classes/api-embedding-provider.class.d.ts +33 -0
- package/dist/src/shared/embedding/classes/onnx-embedding-provider.class.d.ts +33 -0
- package/dist/src/shared/embedding/classes/tfidf-embedding-provider.class.d.ts +28 -0
- package/dist/src/shared/embedding/constants/tfidf-defaults.constant.d.ts +4 -0
- package/dist/src/shared/embedding/functions/append-vector-entry.function.d.ts +14 -0
- package/dist/src/shared/embedding/functions/create-embedding-provider.function.d.ts +15 -0
- package/dist/src/shared/embedding/functions/detect-stale-vectors.function.d.ts +16 -0
- package/dist/src/shared/embedding/functions/parse-api-embedding-response.function.d.ts +11 -0
- package/dist/src/shared/embedding/functions/rebuild-vectors.function.d.ts +15 -0
- package/dist/src/shared/embedding/functions/scan-semantic-contradictions.function.d.ts +13 -0
- package/dist/src/shared/embedding/index.d.ts +9 -0
- package/dist/src/shared/embedding/typings/semantic-contradiction.model.d.ts +21 -0
- package/dist/src/shared/embedding/typings/stale-vectors-report.model.d.ts +16 -0
- package/dist/src/shared/log/constants/log-colors.constant.d.ts +5 -0
- package/dist/src/shared/log/constants/log-defaults.constant.d.ts +3 -0
- package/dist/src/shared/log/constants/log-icons.constant.d.ts +3 -0
- package/dist/src/shared/log/functions/configure-log.function.d.ts +12 -0
- package/dist/src/shared/log/functions/log.function.d.ts +28 -0
- package/dist/src/shared/log/functions/parse-log-level.function.d.ts +10 -0
- package/dist/src/shared/log/functions/resolve-log-level.function.d.ts +12 -0
- package/dist/src/shared/log/functions/write-stderr.function.d.ts +10 -0
- package/dist/src/shared/log/index.d.ts +10 -0
- package/dist/src/shared/log/typings/log-config.interface.d.ts +7 -0
- package/dist/src/shared/log/typings/log-level.type.d.ts +7 -0
- package/dist/src/shared/log/typings/log-output.interface.d.ts +4 -0
- package/dist/src/shared/mcp/classes/mcp-server.class.d.ts +22 -2
- package/dist/src/shared/mcp/functions/create-mcp-server.function.d.ts +6 -1
- package/dist/src/shared/mcp/functions/has-sampling-capability.function.d.ts +8 -0
- package/dist/src/shared/mcp/functions/run-auto-capture.function.d.ts +26 -0
- package/dist/src/shared/mcp/typings/mcp-client.interface.d.ts +2 -0
- package/dist/src/shared/mcp/typings/mcp-integrity-check-result.model.d.ts +24 -0
- package/dist/src/shared/mcp/typings/mcp-worker-client.interface.d.ts +3 -1
- package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
- package/dist/src/shared/wasm-codec/typings/paged-search-result.model.d.ts +2 -0
- package/dist/src/shared/worker-client/classes/worker-client.class.d.ts +38 -1
- package/dist/src/shared/worker-client/constants/request-timeout.constant.d.ts +2 -0
- package/dist/src/shared/worker-client/constants/retry-defaults.constant.d.ts +2 -0
- package/dist/src/shared/worker-client/functions/get-or-create-client.function.d.ts +20 -0
- package/dist/src/shared/worker-client/functions/retry-on-timeout.function.d.ts +18 -0
- package/dist/src/shared/worker-client/index.d.ts +4 -1
- package/dist/src/shared/worker-client/typings/import-result.model.d.ts +16 -0
- package/dist/src/shared/worker-client/typings/integrity-check-result.model.d.ts +24 -0
- package/dist/src/shared/worker-client/typings/search-params.model.d.ts +4 -0
- package/dist/src/shared/worker-client/typings/search-result.model.d.ts +6 -0
- package/dist/src/shared/worker-client/typings/worker-client-options.interface.d.ts +7 -0
- package/dist/src/shared/worker-daemon/classes/worker-daemon.class.d.ts +6 -0
- package/dist/src/shared/worker-daemon/functions/create-ipc-server.function.d.ts +11 -11
- package/dist/src/shared/worker-daemon/functions/embed-after-learn.function.d.ts +13 -0
- package/dist/src/shared/worker-daemon/functions/handle-hybrid-search.function.d.ts +44 -0
- package/dist/src/shared/worker-daemon/functions/handle-import.function.d.ts +14 -0
- package/dist/src/shared/worker-daemon/functions/handle-read-ops.function.d.ts +7 -1
- package/dist/src/shared/worker-daemon/functions/handle-write-ops.function.d.ts +9 -4
- package/dist/src/shared/worker-daemon/functions/run-worker.function.d.ts +6 -1
- package/dist/src/shared/worker-daemon/typings/handler-context.interface.d.ts +3 -0
- package/dist/src/shared/worker-daemon/typings/wasm-modules.interface.d.ts +5 -0
- package/dist/wasm/default-embedding/kbdb_default_embedding.d.ts +55 -0
- package/dist/wasm/default-embedding/kbdb_default_embedding.js +156 -0
- package/{src/wasm/query-parser/kbdb_query_parser_bg.wasm → dist/wasm/default-embedding/kbdb_default_embedding_bg.wasm} +0 -0
- package/dist/wasm/default-embedding/kbdb_default_embedding_bg.wasm.d.ts +12 -0
- package/dist/wasm/default-embedding/package.json +13 -0
- package/dist/wasm/fs-database/kbdb_fs_database.d.ts +16 -85
- package/dist/wasm/fs-database/kbdb_fs_database.js +16 -85
- package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/dist/wasm/fs-migration/kbdb_fs_migration.d.ts +38 -0
- package/dist/wasm/fs-migration/kbdb_fs_migration.js +130 -0
- package/dist/wasm/fs-migration/kbdb_fs_migration_bg.wasm +0 -0
- package/dist/wasm/fs-migration/kbdb_fs_migration_bg.wasm.d.ts +9 -0
- package/dist/wasm/fs-migration/package.json +13 -0
- package/dist/wasm/kb-worker/kbdb_worker.d.ts +20 -115
- package/dist/wasm/kb-worker/kbdb_worker.js +20 -115
- package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
- package/dist/wasm/query-parser/kbdb_query_parser_bg.wasm +0 -0
- package/dist/worker.d.ts +8 -0
- package/dist/worker.mjs +899 -143
- package/dist/worker.mjs.map +4 -4
- package/docs/details/README.md +4 -0
- package/docs/details/agent-tooling.md +132 -0
- package/docs/details/cli.md +91 -18
- package/docs/details/knowledge-base.md +180 -0
- package/docs/details/library-api.md +42 -2
- package/docs/details/mcp-server.md +53 -7
- package/docs/details/search-and-ranking.md +16 -11
- package/docs/goals/cli.md +142 -37
- package/docs/goals/content-parser.md +1 -1
- package/docs/goals/hybrid-search.md +71 -42
- package/docs/goals/mcp.md +24 -19
- package/docs/goals/overview.md +1 -1
- package/docs/goals/query-parser.md +8 -0
- package/docs/goals/semantic-dedup.md +7 -3
- package/docs/goals/worker-client.md +62 -1
- package/docs/goals/worker-daemon.md +83 -30
- package/docs/modules/overview.md +43 -22
- package/docs/modules/rust/embedding/module.md +91 -0
- package/docs/modules/rust/overview.md +56 -21
- package/docs/modules/rust/query-parser/functions/module.md +7 -5
- package/docs/modules/rust/query-parser/functions/pipeline.md +6 -138
- package/docs/modules/rust/query-parser/module.md +16 -22
- package/docs/modules/rust/query-parser/types/module.md +5 -4
- package/docs/modules/rust/query-parser/types/token.md +5 -1
- package/docs/modules/rust/shared/content-parser/functions.md +1 -1
- package/docs/modules/rust/shared/memory/module.md +1 -1
- package/docs/modules/rust/shared/module.md +33 -5
- package/docs/modules/rust/shared/pipeline/functions.md +141 -0
- package/docs/modules/rust/shared/pipeline/module.md +62 -0
- package/docs/modules/rust/shared/pipeline/types.md +43 -0
- package/docs/modules/rust/shared/section/module.md +1 -1
- package/docs/modules/rust/shared/section/types.md +1 -1
- package/docs/modules/typescript/cli.md +5 -3
- package/docs/modules/typescript/kbdb-worker.md +20 -5
- package/docs/modules/typescript/overview.md +28 -6
- package/docs/modules/typescript/shared/cli/functions.md +131 -17
- package/docs/modules/typescript/shared/cli/module.md +33 -20
- package/docs/modules/typescript/shared/cli/typings.md +25 -0
- package/docs/modules/typescript/shared/embedding/functions.md +125 -19
- package/docs/modules/typescript/shared/embedding/module.md +10 -4
- package/docs/modules/typescript/shared/embedding/typings.md +7 -5
- package/docs/modules/typescript/shared/log/constants.md +82 -0
- package/docs/modules/typescript/shared/log/functions.md +131 -0
- package/docs/modules/typescript/shared/log/module.md +153 -0
- package/docs/modules/typescript/shared/log/typings.md +82 -0
- package/docs/modules/typescript/shared/mcp/module.md +1 -1
- package/docs/modules/typescript/shared/mcp/typings.md +8 -1
- package/docs/modules/typescript/shared/module.md +22 -6
- package/docs/modules/typescript/shared/worker-client/module.md +9 -1
- package/docs/modules/typescript/shared/worker-client/typings.md +3 -0
- package/docs/modules/typescript/shared/worker-daemon/functions.md +19 -6
- package/docs/modules/typescript/shared/worker-daemon/module.md +11 -5
- package/docs/modules/typescript/shared/worker-daemon/typings.md +13 -7
- package/docs/overview.md +1 -2
- package/docs/release-notes/0.4.0.md +80 -0
- package/docs/release-notes/0.4.1.md +149 -0
- package/docs/release-notes/README.md +1 -0
- package/mod.ts +33 -15
- package/package.json +12 -11
- package/dist/chunk-JG2UCKLI.mjs +0 -95
- package/dist/chunk-JG2UCKLI.mjs.map +0 -7
- package/src/cli.ts +0 -71
- package/src/shared/auto-capture/classes/auto-capture-controller.class.ts +0 -62
- package/src/shared/auto-capture/constants/auto-capture-defaults.constant.ts +0 -15
- package/src/shared/auto-capture/functions/build-capture-prompt.function.ts +0 -27
- package/src/shared/auto-capture/functions/evaluate-trigger.function.ts +0 -50
- package/src/shared/auto-capture/index.ts +0 -7
- package/src/shared/auto-capture/typings/auto-capture-config.interface.ts +0 -13
- package/src/shared/auto-capture/typings/auto-capture-state.interface.ts +0 -13
- package/src/shared/auto-capture/typings/auto-capture-trigger.interface.ts +0 -7
- package/src/shared/cli/constants/defaults.constant.ts +0 -19
- package/src/shared/cli/constants/global-help.constant.ts +0 -73
- package/src/shared/cli/constants/help-text.constant.ts +0 -4
- package/src/shared/cli/constants/leaf-help.constant.ts +0 -219
- package/src/shared/cli/constants/memory-protocol-body.constant.ts +0 -39
- package/src/shared/cli/constants/query-guidance-body.constant.ts +0 -37
- package/src/shared/cli/constants/subcommand-help.constant.ts +0 -195
- package/src/shared/cli/functions/collect-files.function.ts +0 -55
- package/src/shared/cli/functions/compute-section-kbid.function.ts +0 -49
- package/src/shared/cli/functions/dispatch-command.function.ts +0 -390
- package/src/shared/cli/functions/ensure-db.function.ts +0 -21
- package/src/shared/cli/functions/error-to-message.function.ts +0 -9
- package/src/shared/cli/functions/find-db.function.ts +0 -20
- package/src/shared/cli/functions/format-mcp-output.function.ts +0 -41
- package/src/shared/cli/functions/format-output.function.ts +0 -95
- package/src/shared/cli/functions/format-text-output.function.ts +0 -42
- package/src/shared/cli/functions/generate-group-help.function.ts +0 -41
- package/src/shared/cli/functions/generate-help.function.ts +0 -654
- package/src/shared/cli/functions/handle-data-command.function.ts +0 -67
- package/src/shared/cli/functions/handle-mcp.function.ts +0 -56
- package/src/shared/cli/functions/handle-migrate.function.ts +0 -64
- package/src/shared/cli/functions/hydrate-search-previews.function.ts +0 -29
- package/src/shared/cli/functions/install-default-skills.function.ts +0 -296
- package/src/shared/cli/functions/is-stdin-tty.function.ts +0 -12
- package/src/shared/cli/functions/parse-args.function.ts +0 -156
- package/src/shared/cli/functions/prompt-user.function.ts +0 -36
- package/src/shared/cli/functions/resolve-skill-names.function.ts +0 -43
- package/src/shared/cli/functions/run-agent-create.function.ts +0 -114
- package/src/shared/cli/functions/run-agent-delete.function.ts +0 -47
- package/src/shared/cli/functions/run-agent-get.function.ts +0 -166
- package/src/shared/cli/functions/run-agent-list.function.ts +0 -58
- package/src/shared/cli/functions/run-check.function.ts +0 -159
- package/src/shared/cli/functions/run-cli.function.ts +0 -299
- package/src/shared/cli/functions/run-content.function.ts +0 -47
- package/src/shared/cli/functions/run-db-init.function.ts +0 -44
- package/src/shared/cli/functions/run-db-migrate.function.ts +0 -40
- package/src/shared/cli/functions/run-export.function.ts +0 -40
- package/src/shared/cli/functions/run-gc.function.ts +0 -51
- package/src/shared/cli/functions/run-init.function.ts +0 -93
- package/src/shared/cli/functions/run-learn.function.ts +0 -223
- package/src/shared/cli/functions/run-migrate.function.ts +0 -85
- package/src/shared/cli/functions/run-rebuild.function.ts +0 -47
- package/src/shared/cli/functions/run-recall.function.ts +0 -66
- package/src/shared/cli/functions/run-search.function.ts +0 -133
- package/src/shared/cli/functions/run-skill-delete.function.ts +0 -47
- package/src/shared/cli/functions/run-skill-get.function.ts +0 -90
- package/src/shared/cli/functions/run-skill-learn.function.ts +0 -70
- package/src/shared/cli/functions/run-skill-list.function.ts +0 -74
- package/src/shared/cli/functions/run-status.function.ts +0 -29
- package/src/shared/cli/functions/run-unlearn.function.ts +0 -58
- package/src/shared/cli/functions/version-gate.function.ts +0 -44
- package/src/shared/cli/functions/wrap-command.function.ts +0 -34
- package/src/shared/cli/index.ts +0 -55
- package/src/shared/cli/typings/agent-create-client.interface.ts +0 -47
- package/src/shared/cli/typings/agent-get-client.interface.ts +0 -39
- package/src/shared/cli/typings/check-client.interface.ts +0 -66
- package/src/shared/cli/typings/cli-deps.interface.ts +0 -54
- package/src/shared/cli/typings/cli-options.interface.ts +0 -72
- package/src/shared/cli/typings/command-result.model.ts +0 -15
- package/src/shared/cli/typings/disconnectable-client.interface.ts +0 -29
- package/src/shared/cli/typings/dispatch-client.type.ts +0 -46
- package/src/shared/cli/typings/learn-client.interface.ts +0 -53
- package/src/shared/cli/typings/learn-io.interface.ts +0 -5
- package/src/shared/cli/typings/learn-result.model.ts +0 -27
- package/src/shared/cli/typings/search-client.interface.ts +0 -73
- package/src/shared/cli/typings/search-display.model.ts +0 -54
- package/src/shared/dir-resolver/functions/join-path.function.ts +0 -13
- package/src/shared/dir-resolver/functions/resolve-base-dir.function.ts +0 -25
- package/src/shared/dir-resolver/functions/resolve-wasm-dir.function.ts +0 -5
- package/src/shared/dir-resolver/functions/resolve-worker-script.function.ts +0 -13
- package/src/shared/dir-resolver/index.ts +0 -11
- package/src/shared/dir-resolver/typings/base-dir.interface.ts +0 -4
- package/src/shared/embedding/classes/null-embedding-provider.class.ts +0 -29
- package/src/shared/embedding/constants/near-duplicate-thresholds.constant.ts +0 -17
- package/src/shared/embedding/functions/build-vector-index.function.ts +0 -79
- package/src/shared/embedding/functions/cosine-similarity.function.ts +0 -31
- package/src/shared/embedding/functions/detect-near-duplicates.function.ts +0 -69
- package/src/shared/embedding/functions/jaccard-coefficient.function.ts +0 -26
- package/src/shared/embedding/functions/read-vector-index-meta.function.ts +0 -44
- package/src/shared/embedding/functions/rrf-fuse.function.ts +0 -33
- package/src/shared/embedding/functions/search-vectors.function.ts +0 -59
- package/src/shared/embedding/index.ts +0 -20
- package/src/shared/embedding/typings/embedding-config.interface.ts +0 -23
- package/src/shared/embedding/typings/embedding-provider.interface.ts +0 -25
- package/src/shared/embedding/typings/near-duplicate-candidate.model.ts +0 -25
- package/src/shared/embedding/typings/near-duplicate-result.model.ts +0 -26
- package/src/shared/embedding/typings/vector-index-entry.model.ts +0 -13
- package/src/shared/embedding/typings/vector-index-meta.model.ts +0 -14
- package/src/shared/embedding/typings/vector-search-result.model.ts +0 -8
- package/src/shared/hash/functions/compute-sha256.ts +0 -17
- package/src/shared/hash/index.ts +0 -1
- package/src/shared/mcp/classes/mcp-server.class.ts +0 -480
- package/src/shared/mcp/constants/mcp-error-codes.constant.ts +0 -30
- package/src/shared/mcp/constants/tool-agent-create.constant.ts +0 -39
- package/src/shared/mcp/constants/tool-agent-delete.constant.ts +0 -26
- package/src/shared/mcp/constants/tool-agent-get.constant.ts +0 -24
- package/src/shared/mcp/constants/tool-agent-list.constant.ts +0 -18
- package/src/shared/mcp/constants/tool-auto-capture-review.constant.ts +0 -32
- package/src/shared/mcp/constants/tool-check.constant.ts +0 -21
- package/src/shared/mcp/constants/tool-content.constant.ts +0 -29
- package/src/shared/mcp/constants/tool-export.constant.ts +0 -27
- package/src/shared/mcp/constants/tool-gc.constant.ts +0 -21
- package/src/shared/mcp/constants/tool-learn.constant.ts +0 -58
- package/src/shared/mcp/constants/tool-rebuild.constant.ts +0 -21
- package/src/shared/mcp/constants/tool-recall.constant.ts +0 -36
- package/src/shared/mcp/constants/tool-retrieve.constant.ts +0 -31
- package/src/shared/mcp/constants/tool-search.constant.ts +0 -51
- package/src/shared/mcp/constants/tool-skill-delete.constant.ts +0 -24
- package/src/shared/mcp/constants/tool-skill-get.constant.ts +0 -27
- package/src/shared/mcp/constants/tool-skill-learn.constant.ts +0 -37
- package/src/shared/mcp/constants/tool-skill-list.constant.ts +0 -18
- package/src/shared/mcp/constants/tool-status.constant.ts +0 -20
- package/src/shared/mcp/constants/tool-unlearn.constant.ts +0 -25
- package/src/shared/mcp/functions/as-boolean-or-undefined.function.ts +0 -11
- package/src/shared/mcp/functions/as-string-array-or-undefined.function.ts +0 -17
- package/src/shared/mcp/functions/as-string-array.function.ts +0 -15
- package/src/shared/mcp/functions/as-string.function.ts +0 -10
- package/src/shared/mcp/functions/build-skills-text.function.ts +0 -43
- package/src/shared/mcp/functions/create-mcp-server.function.ts +0 -14
- package/src/shared/mcp/functions/create-prompt-definitions.function.ts +0 -102
- package/src/shared/mcp/functions/create-resource-templates.function.ts +0 -23
- package/src/shared/mcp/functions/create-tool-definitions.function.ts +0 -530
- package/src/shared/mcp/functions/extract-skill-arguments.function.ts +0 -27
- package/src/shared/mcp/functions/handle-agent-create.function.ts +0 -116
- package/src/shared/mcp/functions/handle-agent-delete.function.ts +0 -50
- package/src/shared/mcp/functions/handle-agent-get.function.ts +0 -160
- package/src/shared/mcp/functions/handle-agent-list.function.ts +0 -50
- package/src/shared/mcp/functions/handle-agent-prompt.function.ts +0 -68
- package/src/shared/mcp/functions/handle-completion.function.ts +0 -114
- package/src/shared/mcp/functions/handle-mcp-request.function.ts +0 -202
- package/src/shared/mcp/functions/handle-prompt-get.function.ts +0 -220
- package/src/shared/mcp/functions/handle-recall.function.ts +0 -66
- package/src/shared/mcp/functions/handle-resource-read.function.ts +0 -56
- package/src/shared/mcp/functions/handle-roots-list.function.ts +0 -29
- package/src/shared/mcp/functions/handle-skill-prompt.function.ts +0 -44
- package/src/shared/mcp/functions/handle-tool-auto-capture-review.function.ts +0 -24
- package/src/shared/mcp/functions/handle-tool-call.function.ts +0 -560
- package/src/shared/mcp/functions/handle-tool-check.function.ts +0 -21
- package/src/shared/mcp/functions/handle-tool-content.function.ts +0 -23
- package/src/shared/mcp/functions/handle-tool-export.function.ts +0 -25
- package/src/shared/mcp/functions/handle-tool-gc.function.ts +0 -21
- package/src/shared/mcp/functions/handle-tool-learn.function.ts +0 -69
- package/src/shared/mcp/functions/handle-tool-rebuild.function.ts +0 -21
- package/src/shared/mcp/functions/handle-tool-retrieve.function.ts +0 -40
- package/src/shared/mcp/functions/handle-tool-search.function.ts +0 -47
- package/src/shared/mcp/functions/handle-tool-skill-delete.function.ts +0 -34
- package/src/shared/mcp/functions/handle-tool-skill-get.function.ts +0 -59
- package/src/shared/mcp/functions/handle-tool-skill-learn.function.ts +0 -61
- package/src/shared/mcp/functions/handle-tool-skill-list.function.ts +0 -39
- package/src/shared/mcp/functions/handle-tool-status.function.ts +0 -21
- package/src/shared/mcp/functions/handle-tool-unlearn.function.ts +0 -24
- package/src/shared/mcp/functions/parse-agent-meta.function.ts +0 -27
- package/src/shared/mcp/functions/parse-skill-arguments.function.ts +0 -36
- package/src/shared/mcp/functions/parse-skill-content.function.ts +0 -38
- package/src/shared/mcp/functions/read-agent-meta.function.ts +0 -41
- package/src/shared/mcp/functions/resolve-skill-refs.function.ts +0 -50
- package/src/shared/mcp/functions/run-startup-health-check.function.ts +0 -34
- package/src/shared/mcp/functions/serialize-skill-content.function.ts +0 -12
- package/src/shared/mcp/functions/should-emit-log.function.ts +0 -38
- package/src/shared/mcp/index.ts +0 -28
- package/src/shared/mcp/typings/agent-types.interface.ts +0 -39
- package/src/shared/mcp/typings/log-types.interface.ts +0 -26
- package/src/shared/mcp/typings/mcp-capabilities.interface.ts +0 -16
- package/src/shared/mcp/typings/mcp-client.interface.ts +0 -317
- package/src/shared/mcp/typings/mcp-completion.interface.ts +0 -45
- package/src/shared/mcp/typings/mcp-content-result.model.ts +0 -9
- package/src/shared/mcp/typings/mcp-export-result.model.ts +0 -11
- package/src/shared/mcp/typings/mcp-gc-result.model.ts +0 -15
- package/src/shared/mcp/typings/mcp-integrity-check-result.model.ts +0 -17
- package/src/shared/mcp/typings/mcp-integrity-error.model.ts +0 -15
- package/src/shared/mcp/typings/mcp-notification.interface.ts +0 -9
- package/src/shared/mcp/typings/mcp-rebuild-result.model.ts +0 -9
- package/src/shared/mcp/typings/mcp-request.interface.ts +0 -11
- package/src/shared/mcp/typings/mcp-resource-result.interface.ts +0 -12
- package/src/shared/mcp/typings/mcp-resource-template.interface.ts +0 -11
- package/src/shared/mcp/typings/mcp-response.interface.ts +0 -18
- package/src/shared/mcp/typings/mcp-server-info.interface.ts +0 -7
- package/src/shared/mcp/typings/mcp-server-state.interface.ts +0 -17
- package/src/shared/mcp/typings/mcp-tool-annotations.interface.ts +0 -32
- package/src/shared/mcp/typings/mcp-tool-definition.interface.ts +0 -16
- package/src/shared/mcp/typings/mcp-tool-result.interface.ts +0 -19
- package/src/shared/mcp/typings/mcp-types.interface.ts +0 -158
- package/src/shared/mcp/typings/mcp-worker-client.interface.ts +0 -243
- package/src/shared/mcp/typings/prompt-types.interface.ts +0 -39
- package/src/shared/mcp/typings/remove-section-result.model.ts +0 -10
- package/src/shared/mcp/typings/sampling-types.interface.ts +0 -48
- package/src/shared/mcp/typings/skill-types.interface.ts +0 -29
- package/src/shared/mcp/typings/tool-call-result.model.ts +0 -18
- package/src/shared/mod.ts +0 -1
- package/src/shared/platform/functions/get-ipc-path.function.ts +0 -19
- package/src/shared/platform/functions/get-tmpdir.function.ts +0 -8
- package/src/shared/platform/functions/is-process-alive.function.ts +0 -17
- package/src/shared/platform/index.ts +0 -3
- package/src/shared/runtime/functions/detect-runtime.ts +0 -14
- package/src/shared/runtime/functions/get-args.ts +0 -16
- package/src/shared/runtime/index.ts +0 -3
- package/src/shared/runtime/typings/runtime.ts +0 -2
- package/src/shared/sync/functions/build-import-report.function.ts +0 -40
- package/src/shared/sync/functions/parse-export-entry.function.ts +0 -45
- package/src/shared/sync/functions/resolve-conflict.function.ts +0 -31
- package/src/shared/sync/functions/serialize-export-entry.function.ts +0 -18
- package/src/shared/sync/index.ts +0 -9
- package/src/shared/sync/typings/conflict-resolution.type.ts +0 -8
- package/src/shared/sync/typings/export-entry.interface.ts +0 -13
- package/src/shared/sync/typings/export-options.interface.ts +0 -9
- package/src/shared/sync/typings/import-options.interface.ts +0 -7
- package/src/shared/sync/typings/import-report.interface.ts +0 -15
- package/src/shared/version/constants/version.constant.ts +0 -2
- package/src/shared/version/index.ts +0 -1
- package/src/shared/wasm-codec/functions/decode-add-section-result.function.ts +0 -112
- package/src/shared/wasm-codec/functions/decode-compose-output.function.ts +0 -16
- package/src/shared/wasm-codec/functions/decode-document-manifest-list.function.ts +0 -70
- package/src/shared/wasm-codec/functions/decode-document-manifest.function.ts +0 -87
- package/src/shared/wasm-codec/functions/decode-f32.function.ts +0 -16
- package/src/shared/wasm-codec/functions/decode-key-value-text.function.ts +0 -15
- package/src/shared/wasm-codec/functions/decode-one-recall-result.function.ts +0 -86
- package/src/shared/wasm-codec/functions/decode-option-string.function.ts +0 -24
- package/src/shared/wasm-codec/functions/decode-recall-document.function.ts +0 -59
- package/src/shared/wasm-codec/functions/decode-recall-reference.function.ts +0 -52
- package/src/shared/wasm-codec/functions/decode-recall-result.function.ts +0 -267
- package/src/shared/wasm-codec/functions/decode-recall-sibling.function.ts +0 -43
- package/src/shared/wasm-codec/functions/decode-remove-flag.function.ts +0 -3
- package/src/shared/wasm-codec/functions/decode-scored-results.function.ts +0 -194
- package/src/shared/wasm-codec/functions/decode-section-match.function.ts +0 -80
- package/src/shared/wasm-codec/functions/decode-section-record-list.function.ts +0 -20
- package/src/shared/wasm-codec/functions/decode-section-record-trailing.function.ts +0 -75
- package/src/shared/wasm-codec/functions/decode-section-record.function.ts +0 -85
- package/src/shared/wasm-codec/functions/decode-section-records.function.ts +0 -249
- package/src/shared/wasm-codec/functions/decode-section-type.function.ts +0 -30
- package/src/shared/wasm-codec/functions/decode-string.function.ts +0 -22
- package/src/shared/wasm-codec/functions/decode-u32.function.ts +0 -16
- package/src/shared/wasm-codec/functions/decode-u64.function.ts +0 -16
- package/src/shared/wasm-codec/functions/decode-wasm-list.function.ts +0 -31
- package/src/shared/wasm-codec/functions/encode-add-section-params.function.ts +0 -102
- package/src/shared/wasm-codec/functions/encode-group-params.function.ts +0 -28
- package/src/shared/wasm-codec/functions/encode-identifier-list.function.ts +0 -17
- package/src/shared/wasm-codec/functions/encode-kbid-list.function.ts +0 -17
- package/src/shared/wasm-codec/functions/encode-option-string.function.ts +0 -14
- package/src/shared/wasm-codec/functions/encode-recall-params.function.ts +0 -68
- package/src/shared/wasm-codec/functions/encode-search-params.function.ts +0 -12
- package/src/shared/wasm-codec/functions/encode-section-type.function.ts +0 -18
- package/src/shared/wasm-codec/functions/encode-string.function.ts +0 -9
- package/src/shared/wasm-codec/functions/encode-type-filter-param.function.ts +0 -13
- package/src/shared/wasm-codec/functions/encode-u32.function.ts +0 -5
- package/src/shared/wasm-codec/functions/encode-update-section-params.function.ts +0 -16
- package/src/shared/wasm-codec/index.ts +0 -49
- package/src/shared/wasm-codec/typings/add-section-input.model.ts +0 -45
- package/src/shared/wasm-codec/typings/add-section-result.model.ts +0 -28
- package/src/shared/wasm-codec/typings/document-manifest.model.ts +0 -20
- package/src/shared/wasm-codec/typings/document-section.model.ts +0 -12
- package/src/shared/wasm-codec/typings/item-decoder.type.ts +0 -10
- package/src/shared/wasm-codec/typings/near-duplicate.model.ts +0 -16
- package/src/shared/wasm-codec/typings/paged-search-result.model.ts +0 -22
- package/src/shared/wasm-codec/typings/section-match.model.ts +0 -31
- package/src/shared/wasm-codec/typings/section-record-trailing.model.ts +0 -38
- package/src/shared/wasm-codec/typings/section-record.model.ts +0 -66
- package/src/shared/wasm-codec/typings/section-type-result.model.ts +0 -12
- package/src/shared/worker-client/classes/worker-client.class.ts +0 -466
- package/src/shared/worker-client/functions/compute-context-id.function.ts +0 -18
- package/src/shared/worker-client/functions/create-worker-client.function.ts +0 -70
- package/src/shared/worker-client/functions/discover-daemon.function.ts +0 -47
- package/src/shared/worker-client/functions/handle-ipc-data.function.ts +0 -49
- package/src/shared/worker-client/functions/resolve-db-path.function.ts +0 -21
- package/src/shared/worker-client/functions/send-ipc-request.function.ts +0 -39
- package/src/shared/worker-client/functions/spawn-daemon.function.ts +0 -35
- package/src/shared/worker-client/functions/wait-for-daemon.function.ts +0 -34
- package/src/shared/worker-client/index.ts +0 -44
- package/src/shared/worker-client/typings/add-section-result.model.ts +0 -39
- package/src/shared/worker-client/typings/content-result.model.ts +0 -12
- package/src/shared/worker-client/typings/daemon-info.model.ts +0 -7
- package/src/shared/worker-client/typings/export-result.model.ts +0 -14
- package/src/shared/worker-client/typings/gc-result.model.ts +0 -18
- package/src/shared/worker-client/typings/integrity-check-result.model.ts +0 -43
- package/src/shared/worker-client/typings/json-rpc-response.interface.ts +0 -17
- package/src/shared/worker-client/typings/migrate-result.model.ts +0 -11
- package/src/shared/worker-client/typings/pending-call.interface.ts +0 -7
- package/src/shared/worker-client/typings/rebuild-result.model.ts +0 -12
- package/src/shared/worker-client/typings/recall-document.model.ts +0 -16
- package/src/shared/worker-client/typings/recall-params.model.ts +0 -15
- package/src/shared/worker-client/typings/recall-reference.model.ts +0 -32
- package/src/shared/worker-client/typings/recall-result.model.ts +0 -98
- package/src/shared/worker-client/typings/recall-sibling.model.ts +0 -11
- package/src/shared/worker-client/typings/recall-single-result.model.ts +0 -41
- package/src/shared/worker-client/typings/remove-section-result.model.ts +0 -7
- package/src/shared/worker-client/typings/search-params.model.ts +0 -14
- package/src/shared/worker-client/typings/search-result.model.ts +0 -43
- package/src/shared/worker-client/typings/section.model.ts +0 -43
- package/src/shared/worker-client/typings/status-result.model.ts +0 -14
- package/src/shared/worker-client/typings/version-status.model.ts +0 -28
- package/src/shared/worker-client/typings/worker-client-error.interface.ts +0 -8
- package/src/shared/worker-client/typings/worker-client-options.interface.ts +0 -30
- package/src/shared/worker-daemon/classes/ipc-error.class.ts +0 -22
- package/src/shared/worker-daemon/classes/worker-daemon.class.ts +0 -1291
- package/src/shared/worker-daemon/constants/daemon-defaults.constant.ts +0 -29
- package/src/shared/worker-daemon/constants/wasm-method-map.constant.ts +0 -69
- package/src/shared/worker-daemon/functions/build-ipc-error-response.function.ts +0 -16
- package/src/shared/worker-daemon/functions/check-catalog-version.function.ts +0 -54
- package/src/shared/worker-daemon/functions/check-preconditions.function.ts +0 -28
- package/src/shared/worker-daemon/functions/create-host-imports.function.ts +0 -328
- package/src/shared/worker-daemon/functions/create-ipc-server.function.ts +0 -87
- package/src/shared/worker-daemon/functions/detect-stale-pid.function.ts +0 -33
- package/src/shared/worker-daemon/functions/dispatch-request.function.ts +0 -190
- package/src/shared/worker-daemon/functions/handle-check-version.function.ts +0 -74
- package/src/shared/worker-daemon/functions/handle-config-method.function.ts +0 -27
- package/src/shared/worker-daemon/functions/handle-read-ops.function.ts +0 -236
- package/src/shared/worker-daemon/functions/handle-write-ops.function.ts +0 -257
- package/src/shared/worker-daemon/functions/load-wasm-modules.function.ts +0 -95
- package/src/shared/worker-daemon/functions/parse-auto-capture-section.function.ts +0 -51
- package/src/shared/worker-daemon/functions/parse-catalog-version.function.ts +0 -20
- package/src/shared/worker-daemon/functions/parse-embedding-section.function.ts +0 -38
- package/src/shared/worker-daemon/functions/parse-worker-toml.function.ts +0 -104
- package/src/shared/worker-daemon/functions/read-config.function.ts +0 -83
- package/src/shared/worker-daemon/functions/run-startup-integrity-check.function.ts +0 -55
- package/src/shared/worker-daemon/functions/run-worker.function.ts +0 -57
- package/src/shared/worker-daemon/functions/scan-near-duplicates.function.ts +0 -92
- package/src/shared/worker-daemon/functions/start-daemon.function.ts +0 -74
- package/src/shared/worker-daemon/functions/wasm-bridge.function.ts +0 -144
- package/src/shared/worker-daemon/functions/wasm-memory-helpers.function.ts +0 -41
- package/src/shared/worker-daemon/functions/write-lock.function.ts +0 -49
- package/src/shared/worker-daemon/index.ts +0 -16
- package/src/shared/worker-daemon/typings/allocator-ref.interface.ts +0 -16
- package/src/shared/worker-daemon/typings/daemon-config.interface.ts +0 -20
- package/src/shared/worker-daemon/typings/fs-adapter.interface.ts +0 -22
- package/src/shared/worker-daemon/typings/handler-context.interface.ts +0 -19
- package/src/shared/worker-daemon/typings/ipc-handler.interface.ts +0 -39
- package/src/shared/worker-daemon/typings/memory-ref.interface.ts +0 -13
- package/src/shared/worker-daemon/typings/wasm-fn.type.ts +0 -2
- package/src/shared/worker-daemon/typings/wasm-modules.interface.ts +0 -7
- package/src/shared/worker-daemon/typings/write-lock.interface.ts +0 -13
- package/src/wasm/fs-database/kbdb_fs_database.d.ts +0 -259
- package/src/wasm/fs-database/kbdb_fs_database.js +0 -515
- package/src/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/src/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +0 -35
- package/src/wasm/fs-database/package.json +0 -13
- package/src/wasm/kb-worker/kbdb_worker.d.ts +0 -650
- package/src/wasm/kb-worker/kbdb_worker.js +0 -1181
- package/src/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
- package/src/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +0 -77
- package/src/wasm/kb-worker/package.json +0 -13
- package/src/wasm/query-parser/kbdb_query_parser.d.ts +0 -195
- package/src/wasm/query-parser/kbdb_query_parser.js +0 -403
- package/src/wasm/query-parser/kbdb_query_parser_bg.wasm.d.ts +0 -25
- package/src/wasm/query-parser/package.json +0 -13
- package/src/worker.ts +0 -42
|
@@ -1,1291 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
existsSync,
|
|
3
|
-
readFileSync,
|
|
4
|
-
readdirSync,
|
|
5
|
-
accessSync,
|
|
6
|
-
writeFileSync,
|
|
7
|
-
unlinkSync,
|
|
8
|
-
constants,
|
|
9
|
-
} from 'node:fs';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
import { tmpdir } from 'node:os';
|
|
12
|
-
import type { Server } from 'node:net';
|
|
13
|
-
import type { DaemonConfig } from '../typings/daemon-config.interface.ts';
|
|
14
|
-
import type { WasmModules } from '../typings/wasm-modules.interface.ts';
|
|
15
|
-
import type {
|
|
16
|
-
IpcRequest,
|
|
17
|
-
IpcResponse,
|
|
18
|
-
IpcHandler,
|
|
19
|
-
} from '../typings/ipc-handler.interface.ts';
|
|
20
|
-
import { DB_FORMAT_VERSION } from '../constants/daemon-defaults.constant.ts';
|
|
21
|
-
import { loadWasmModules } from '../functions/load-wasm-modules.function.ts';
|
|
22
|
-
import { createIpcServer } from '../functions/create-ipc-server.function.ts';
|
|
23
|
-
import { getIpcPath } from '../../platform/functions/get-ipc-path.function.ts';
|
|
24
|
-
import {
|
|
25
|
-
encodeSearchParams,
|
|
26
|
-
encodeAddSectionParams,
|
|
27
|
-
encodeUpdateSectionParams,
|
|
28
|
-
encodeKbidList,
|
|
29
|
-
encodeGroupParams,
|
|
30
|
-
encodeIdentifierList,
|
|
31
|
-
encodeTypeFilterParam,
|
|
32
|
-
encodeRecallParams,
|
|
33
|
-
decodePagedSearchResult,
|
|
34
|
-
decodeSectionRecords,
|
|
35
|
-
decodeSectionRecordList,
|
|
36
|
-
decodeDocumentManifest,
|
|
37
|
-
decodeDocumentManifestList,
|
|
38
|
-
decodeComposeOutput,
|
|
39
|
-
decodeKeyValueText,
|
|
40
|
-
decodeRemoveFlag,
|
|
41
|
-
decodeRecallResult,
|
|
42
|
-
decodeAddSectionResult,
|
|
43
|
-
} from '../../wasm-codec/index.ts';
|
|
44
|
-
|
|
45
|
-
import type { AddSectionInput } from '../../wasm-codec/index.ts';
|
|
46
|
-
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
|
-
// Internal types
|
|
49
|
-
// ---------------------------------------------------------------------------
|
|
50
|
-
|
|
51
|
-
/** Callable WASM export function signature. */
|
|
52
|
-
type WasmFn = (...args: unknown[]) => unknown;
|
|
53
|
-
|
|
54
|
-
/** Mapping from IPC method name to kb-worker.wasm export name. */
|
|
55
|
-
const WASM_METHOD_MAP: Readonly<Partial<Record<string, string>>> = {
|
|
56
|
-
search: 'worker_search',
|
|
57
|
-
addSection: 'worker_add_section',
|
|
58
|
-
add_section: 'worker_add_section',
|
|
59
|
-
updateSection: 'worker_update_section',
|
|
60
|
-
update_section: 'worker_update_section',
|
|
61
|
-
removeSection: 'worker_remove_section',
|
|
62
|
-
remove_section: 'worker_remove_section',
|
|
63
|
-
readSections: 'worker_read_sections',
|
|
64
|
-
read_sections: 'worker_read_sections',
|
|
65
|
-
groupSections: 'worker_group_sections',
|
|
66
|
-
group_sections: 'worker_group_sections',
|
|
67
|
-
removeGrouping: 'worker_remove_grouping',
|
|
68
|
-
remove_grouping: 'worker_remove_grouping',
|
|
69
|
-
retrieveDocument: 'worker_retrieve_doc',
|
|
70
|
-
retrieve_doc: 'worker_retrieve_doc',
|
|
71
|
-
content: 'worker_compose',
|
|
72
|
-
compose: 'worker_compose',
|
|
73
|
-
integrity_check: 'worker_check_integrity',
|
|
74
|
-
integrityCheck: 'worker_check_integrity',
|
|
75
|
-
gc: 'worker_garbage_collect',
|
|
76
|
-
rebuild_indexes: 'worker_rebuild_indexes',
|
|
77
|
-
rebuildIndexes: 'worker_rebuild_indexes',
|
|
78
|
-
init_directory: 'worker_init_directory',
|
|
79
|
-
initDirectory: 'worker_init_directory',
|
|
80
|
-
migrateDatabase: 'worker_migrate',
|
|
81
|
-
query: 'worker_query',
|
|
82
|
-
get_result_status: 'worker_result_status',
|
|
83
|
-
get_result: 'worker_get_result',
|
|
84
|
-
invalidate: 'worker_invalidate',
|
|
85
|
-
invalidate_all: 'worker_invalidate_all',
|
|
86
|
-
invalidateAll: 'worker_invalidate_all',
|
|
87
|
-
db_status: 'worker_status',
|
|
88
|
-
dbStatus: 'worker_status',
|
|
89
|
-
listByType: 'worker_list_by_type',
|
|
90
|
-
list_by_type: 'worker_list_by_type',
|
|
91
|
-
listDocumentsByType: 'worker_list_docs_by_type',
|
|
92
|
-
list_docs_by_type: 'worker_list_docs_by_type',
|
|
93
|
-
recall: 'worker_recall',
|
|
94
|
-
export: 'worker_export',
|
|
95
|
-
exportDb: 'worker_export',
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
/** Config method name prefix. */
|
|
99
|
-
const CONFIG_PREFIX = 'config_';
|
|
100
|
-
|
|
101
|
-
/** Config key → DaemonConfig property mapping. */
|
|
102
|
-
const CONFIG_KEY_MAP: Readonly<
|
|
103
|
-
Partial<Record<string, keyof DaemonConfig>>
|
|
104
|
-
> = {
|
|
105
|
-
timeout_ms: 'timeoutMs',
|
|
106
|
-
item_ttl_ms: 'itemTtlMs',
|
|
107
|
-
item_limit: 'itemLimit',
|
|
108
|
-
index_limit: 'indexLimit',
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
// IpcError
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
|
-
|
|
115
|
-
/** Typed JSON-RPC error used internally by WorkerDaemon dispatch. */
|
|
116
|
-
class IpcError extends Error {
|
|
117
|
-
/** JSON-RPC error code. */
|
|
118
|
-
readonly code: number;
|
|
119
|
-
|
|
120
|
-
constructor(code: number, message: string) {
|
|
121
|
-
super(message);
|
|
122
|
-
this.code = code;
|
|
123
|
-
this.name = 'IpcError';
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// ---------------------------------------------------------------------------
|
|
128
|
-
// WorkerDaemon
|
|
129
|
-
// ---------------------------------------------------------------------------
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Core daemon class that manages the full worker daemon lifecycle.
|
|
133
|
-
*
|
|
134
|
-
* Orchestrates WASM module loading, IPC server creation, request
|
|
135
|
-
* routing to `kb-worker.wasm` exports, idle timeout tracking, and
|
|
136
|
-
* graceful shutdown. The daemon validates startup preconditions before
|
|
137
|
-
* loading WASM modules and rejects IPC requests whose `ctx` param does
|
|
138
|
-
* not match the daemon's context ID.
|
|
139
|
-
*/
|
|
140
|
-
export class WorkerDaemon {
|
|
141
|
-
/** Context ID (16-character hex SHA-256 prefix). */
|
|
142
|
-
readonly ctx: string;
|
|
143
|
-
|
|
144
|
-
/** Absolute path to the `.kbdb` directory. */
|
|
145
|
-
readonly targetDir: string;
|
|
146
|
-
|
|
147
|
-
/** Parsed daemon configuration from `worker.toml`. */
|
|
148
|
-
readonly config: DaemonConfig;
|
|
149
|
-
|
|
150
|
-
/** Number of currently active IPC client connections. */
|
|
151
|
-
get connectionCount(): number {
|
|
152
|
-
return this._connectionCount;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private _connectionCount = 0;
|
|
156
|
-
private _wasmModules: WasmModules | null = null;
|
|
157
|
-
private _idleAt = 0;
|
|
158
|
-
private _idleTimer: ReturnType<typeof setTimeout> | null = null;
|
|
159
|
-
private _server: Server | null = null;
|
|
160
|
-
private readonly _wasmDir: string;
|
|
161
|
-
|
|
162
|
-
/** Queue of waiters for the single-writer lock. */
|
|
163
|
-
private _writeQueue: { resolve: () => void }[] = [];
|
|
164
|
-
|
|
165
|
-
/** Whether the write lock is currently held. */
|
|
166
|
-
private _writeLocked = false;
|
|
167
|
-
|
|
168
|
-
/** Whether the startup integrity check passed. */
|
|
169
|
-
private _integrityOk = true;
|
|
170
|
-
|
|
171
|
-
/** Integrity errors found at startup, if any. */
|
|
172
|
-
private _integrityErrors: string[] = [];
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* @param ctx - context ID (16-hex characters), the first 16 of
|
|
176
|
-
* the SHA-256 hash of `targetDir`
|
|
177
|
-
* @param targetDir - absolute path to the `.kbdb` directory
|
|
178
|
-
* @param config - parsed daemon configuration
|
|
179
|
-
* @param wasmDir - path to the WASM build output directory
|
|
180
|
-
*/
|
|
181
|
-
constructor(
|
|
182
|
-
ctx: string,
|
|
183
|
-
targetDir: string,
|
|
184
|
-
config: DaemonConfig,
|
|
185
|
-
wasmDir?: string,
|
|
186
|
-
) {
|
|
187
|
-
this.ctx = ctx;
|
|
188
|
-
this.targetDir = targetDir;
|
|
189
|
-
this.config = config;
|
|
190
|
-
this._wasmDir = wasmDir ?? '';
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// -----------------------------------------------------------------------
|
|
194
|
-
// Public API
|
|
195
|
-
// -----------------------------------------------------------------------
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Validates startup preconditions before WASM module loading.
|
|
199
|
-
*
|
|
200
|
-
* Checks that the database directory exists, is readable and
|
|
201
|
-
* writable, and that `catalog.toml` reports a compatible version.
|
|
202
|
-
*
|
|
203
|
-
* @throws {Error} if any precondition fails -- `startDaemon`
|
|
204
|
-
* catches this, prints to stderr, and exits with code 1
|
|
205
|
-
*/
|
|
206
|
-
checkPreconditions(): void {
|
|
207
|
-
if (!existsSync(this.targetDir)) {
|
|
208
|
-
throw new Error(
|
|
209
|
-
`database directory not found: ${this.targetDir}`,
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
try {
|
|
214
|
-
accessSync(
|
|
215
|
-
this.targetDir,
|
|
216
|
-
|
|
217
|
-
constants.R_OK | constants.W_OK,
|
|
218
|
-
);
|
|
219
|
-
} catch {
|
|
220
|
-
throw new Error(
|
|
221
|
-
`cannot access database directory: ${this.targetDir}` +
|
|
222
|
-
' -- permission denied',
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
this.checkCatalogVersion();
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Starts the daemon: loads WASM modules, writes the PID file,
|
|
231
|
-
* creates the IPC socket, and begins listening for connections.
|
|
232
|
-
*
|
|
233
|
-
* Call `checkPreconditions()` before `start()` to validate the
|
|
234
|
-
* database directory. The daemon will not start if any precondition
|
|
235
|
-
* fails.
|
|
236
|
-
*
|
|
237
|
-
* @throws when WASM module loading fails or the IPC socket cannot
|
|
238
|
-
* be created
|
|
239
|
-
*/
|
|
240
|
-
async start(): Promise<void> {
|
|
241
|
-
const wasmModules = await loadWasmModules(
|
|
242
|
-
this.config,
|
|
243
|
-
this._wasmDir,
|
|
244
|
-
);
|
|
245
|
-
this._wasmModules = wasmModules;
|
|
246
|
-
|
|
247
|
-
this.initWorkerContext();
|
|
248
|
-
this.runStartupIntegrityCheck();
|
|
249
|
-
|
|
250
|
-
const pidPath = join(tmpdir(), `kbdb-${this.ctx}.pid`);
|
|
251
|
-
writeFileSync(pidPath, process.pid.toString());
|
|
252
|
-
|
|
253
|
-
const ipcPath = getIpcPath(this.ctx);
|
|
254
|
-
|
|
255
|
-
if (existsSync(ipcPath)) {
|
|
256
|
-
try {
|
|
257
|
-
unlinkSync(ipcPath);
|
|
258
|
-
} catch {
|
|
259
|
-
// ignore stale socket removal errors
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const handler: IpcHandler = (req) => this.handleRequest(req);
|
|
264
|
-
this._server = createIpcServer(ipcPath, handler);
|
|
265
|
-
|
|
266
|
-
this._server.on('connection', () => {
|
|
267
|
-
this.incrementConnections();
|
|
268
|
-
this.resetIdleTimer();
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
this._server.on('close', () => {
|
|
272
|
-
this.decrementConnections();
|
|
273
|
-
if (this._connectionCount === 0) {
|
|
274
|
-
this.resetIdleTimer();
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
this.resetIdleTimer();
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Gracefully shuts down the daemon.
|
|
283
|
-
*
|
|
284
|
-
* Stops accepting new connections, clears the idle timer, purges
|
|
285
|
-
* WASM state, removes the PID file and IPC socket file, then exits
|
|
286
|
-
* the process.
|
|
287
|
-
*/
|
|
288
|
-
stop(): void {
|
|
289
|
-
if (this._idleTimer !== null) {
|
|
290
|
-
clearTimeout(this._idleTimer);
|
|
291
|
-
this._idleTimer = null;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (this._server !== null) {
|
|
295
|
-
this._server.close();
|
|
296
|
-
this._server = null;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
this._wasmModules = null;
|
|
300
|
-
|
|
301
|
-
const pidPath = join(tmpdir(), `kbdb-${this.ctx}.pid`);
|
|
302
|
-
try {
|
|
303
|
-
unlinkSync(pidPath);
|
|
304
|
-
} catch {
|
|
305
|
-
// ignore cleanup errors
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const ipcPath = getIpcPath(this.ctx);
|
|
309
|
-
try {
|
|
310
|
-
unlinkSync(ipcPath);
|
|
311
|
-
} catch {
|
|
312
|
-
// ignore cleanup errors
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const crashPath = join(tmpdir(), `kbdb-${this.ctx}.crash`);
|
|
316
|
-
try {
|
|
317
|
-
unlinkSync(crashPath);
|
|
318
|
-
} catch {
|
|
319
|
-
// ignore cleanup errors
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
process.exit(0);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Handles a single JSON-RPC 2.0 request.
|
|
327
|
-
*
|
|
328
|
-
* Validates context, then routes to a daemon-state handler or a
|
|
329
|
-
* WASM export. Requests whose `ctx` param does not match the
|
|
330
|
-
* daemon's context ID are rejected with error code `-32001`.
|
|
331
|
-
*
|
|
332
|
-
* @param request - incoming JSON-RPC request
|
|
333
|
-
* @returns the JSON-RPC response
|
|
334
|
-
*/
|
|
335
|
-
async handleRequest(request: IpcRequest): Promise<IpcResponse> {
|
|
336
|
-
const params = request.params as
|
|
337
|
-
| Record<string, unknown>
|
|
338
|
-
| undefined;
|
|
339
|
-
if (params === undefined || params.ctx !== this.ctx) {
|
|
340
|
-
return this.errorResponse(
|
|
341
|
-
request.id,
|
|
342
|
-
-32001,
|
|
343
|
-
'context mismatch',
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
this.resetIdleTimer();
|
|
348
|
-
|
|
349
|
-
try {
|
|
350
|
-
const result = await this.dispatch(request.method, params);
|
|
351
|
-
this._idleAt = Math.floor(Date.now() / 1000);
|
|
352
|
-
return {
|
|
353
|
-
jsonrpc: '2.0',
|
|
354
|
-
id: request.id,
|
|
355
|
-
result,
|
|
356
|
-
};
|
|
357
|
-
} catch (err) {
|
|
358
|
-
this._idleAt = Math.floor(Date.now() / 1000);
|
|
359
|
-
if (err instanceof IpcError) {
|
|
360
|
-
return this.errorResponse(
|
|
361
|
-
request.id,
|
|
362
|
-
err.code,
|
|
363
|
-
err.message,
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
const message =
|
|
367
|
-
err instanceof Error ? err.message : String(err);
|
|
368
|
-
return this.errorResponse(request.id, -32000, message);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Increments the active connection count.
|
|
374
|
-
*
|
|
375
|
-
* Call when a new IPC client connects.
|
|
376
|
-
*/
|
|
377
|
-
incrementConnections(): void {
|
|
378
|
-
this._connectionCount++;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Decrements the active connection count, clamped to zero.
|
|
383
|
-
*
|
|
384
|
-
* Call when an IPC client disconnects.
|
|
385
|
-
*/
|
|
386
|
-
decrementConnections(): void {
|
|
387
|
-
if (this._connectionCount > 0) {
|
|
388
|
-
this._connectionCount--;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* Injects pre-built WASM modules for unit testing.
|
|
394
|
-
*
|
|
395
|
-
* This method exists solely to support unit tests that cannot
|
|
396
|
-
* load real WASM binaries. It must not be called in production
|
|
397
|
-
* code -- production code uses `start()` to load modules.
|
|
398
|
-
*
|
|
399
|
-
* @param modules - pre-built WASM module instances
|
|
400
|
-
* @internal
|
|
401
|
-
*/
|
|
402
|
-
injectModulesForTesting(modules: WasmModules): void {
|
|
403
|
-
this._wasmModules = modules;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// -----------------------------------------------------------------------
|
|
407
|
-
// Private helpers
|
|
408
|
-
// -----------------------------------------------------------------------
|
|
409
|
-
|
|
410
|
-
/** Resets the idle timer; triggers stop() when it fires. */
|
|
411
|
-
private resetIdleTimer(): void {
|
|
412
|
-
if (this._idleTimer !== null) {
|
|
413
|
-
clearTimeout(this._idleTimer);
|
|
414
|
-
}
|
|
415
|
-
if (this._connectionCount === 0) {
|
|
416
|
-
this._idleTimer = setTimeout(() => {
|
|
417
|
-
this.stop();
|
|
418
|
-
}, this.config.timeoutMs);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/** Reads catalog.toml and validates the version field. */
|
|
423
|
-
private checkCatalogVersion(): void {
|
|
424
|
-
const catalogPath = join(this.targetDir, 'catalog.toml');
|
|
425
|
-
let text: string;
|
|
426
|
-
try {
|
|
427
|
-
text = readFileSync(catalogPath, 'utf-8');
|
|
428
|
-
} catch {
|
|
429
|
-
throw new Error(
|
|
430
|
-
`cannot read database directory: ${this.targetDir}` +
|
|
431
|
-
' -- permission denied',
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
const version = parseCatalogVersion(text);
|
|
436
|
-
if (version === null) {
|
|
437
|
-
throw new Error(
|
|
438
|
-
'database version 0 requires migration to version ' +
|
|
439
|
-
String(DB_FORMAT_VERSION) +
|
|
440
|
-
' -- run `kbdb --migrate` before starting the daemon',
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
if (version > DB_FORMAT_VERSION) {
|
|
445
|
-
throw new Error(
|
|
446
|
-
'database version ' +
|
|
447
|
-
String(version) +
|
|
448
|
-
' is newer than kbdb version ' +
|
|
449
|
-
String(DB_FORMAT_VERSION) +
|
|
450
|
-
' -- upgrade kbdb to open this database',
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (version < DB_FORMAT_VERSION) {
|
|
455
|
-
throw new Error(
|
|
456
|
-
'database version ' +
|
|
457
|
-
String(version) +
|
|
458
|
-
' requires migration to version ' +
|
|
459
|
-
String(DB_FORMAT_VERSION) +
|
|
460
|
-
' -- run `kbdb --migrate` before starting the daemon',
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
/** Builds a JSON-RPC error response. */
|
|
466
|
-
private errorResponse(
|
|
467
|
-
id: number | string,
|
|
468
|
-
code: number,
|
|
469
|
-
message: string,
|
|
470
|
-
): IpcResponse {
|
|
471
|
-
return {
|
|
472
|
-
jsonrpc: '2.0',
|
|
473
|
-
id,
|
|
474
|
-
error: { code, message },
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* Dispatches a request method to the appropriate handler.
|
|
480
|
-
*
|
|
481
|
-
* Handles daemon-state methods (`status`, `idle_at`,
|
|
482
|
-
* `config_{key}`) inline and routes WASM methods to the
|
|
483
|
-
* correct calling convention for each export.
|
|
484
|
-
*/
|
|
485
|
-
private dispatch(
|
|
486
|
-
method: string,
|
|
487
|
-
params: Record<string, unknown>,
|
|
488
|
-
): unknown {
|
|
489
|
-
if (method === 'status') {
|
|
490
|
-
return {
|
|
491
|
-
status: this._connectionCount > 0 ? 'busy' : 'idle',
|
|
492
|
-
integrityOk: this._integrityOk,
|
|
493
|
-
integrityErrors: this._integrityErrors,
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
if (method === 'idle_at') {
|
|
498
|
-
return this._idleAt;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
if (method === 'checkVersion') {
|
|
502
|
-
return this.handleCheckVersion(params);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
if (method.startsWith(CONFIG_PREFIX)) {
|
|
506
|
-
return this.handleConfigMethod(method);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
const wasmMethod = WASM_METHOD_MAP[method];
|
|
510
|
-
if (wasmMethod !== undefined) {
|
|
511
|
-
return this.dispatchWasm(method, wasmMethod, params);
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
throw new IpcError(-32601, `Method not found: ${method}`);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
private async dispatchWasm(
|
|
518
|
-
method: string,
|
|
519
|
-
wasmExport: string,
|
|
520
|
-
params: Record<string, unknown>,
|
|
521
|
-
): Promise<unknown> {
|
|
522
|
-
// Read-only operations — no write lock required.
|
|
523
|
-
if (method === 'search' || method === 'query') {
|
|
524
|
-
return this.handleSearch(params);
|
|
525
|
-
}
|
|
526
|
-
if (method === 'readSections' || method === 'read_sections') {
|
|
527
|
-
return this.handleReadSections(params);
|
|
528
|
-
}
|
|
529
|
-
if (method === 'retrieveDocument' || method === 'retrieve_doc') {
|
|
530
|
-
return this.handleRetrieveDoc(params);
|
|
531
|
-
}
|
|
532
|
-
if (method === 'content' || method === 'compose') {
|
|
533
|
-
return this.handleCompose(params);
|
|
534
|
-
}
|
|
535
|
-
if (method === 'integrityCheck' || method === 'integrity_check') {
|
|
536
|
-
return this.handleIntegrityCheck();
|
|
537
|
-
}
|
|
538
|
-
if (method === 'dbStatus' || method === 'db_status') {
|
|
539
|
-
return this.handleDbStatus();
|
|
540
|
-
}
|
|
541
|
-
if (method === 'get_result_status') {
|
|
542
|
-
return this.handleResultStatus(params);
|
|
543
|
-
}
|
|
544
|
-
if (method === 'get_result') {
|
|
545
|
-
return this.handleGetResult(params);
|
|
546
|
-
}
|
|
547
|
-
if (method === 'listByType' || method === 'list_by_type') {
|
|
548
|
-
return this.handleListByType(params);
|
|
549
|
-
}
|
|
550
|
-
if (
|
|
551
|
-
method === 'listDocumentsByType' ||
|
|
552
|
-
method === 'list_docs_by_type'
|
|
553
|
-
) {
|
|
554
|
-
return this.handleListDocsByType(params);
|
|
555
|
-
}
|
|
556
|
-
if (method === 'recall') {
|
|
557
|
-
return this.handleRecall(params);
|
|
558
|
-
}
|
|
559
|
-
if (method === 'export' || method === 'exportDb') {
|
|
560
|
-
return this.handleExport(params);
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// Write operations — serialised through the single-writer lock.
|
|
564
|
-
await this.acquireWriteLock();
|
|
565
|
-
try {
|
|
566
|
-
if (method === 'invalidate') {
|
|
567
|
-
return this.handleInvalidate(params);
|
|
568
|
-
}
|
|
569
|
-
if (
|
|
570
|
-
method === 'invalidateAll' ||
|
|
571
|
-
method === 'invalidate_all'
|
|
572
|
-
) {
|
|
573
|
-
return this.handleInvalidateAll();
|
|
574
|
-
}
|
|
575
|
-
if (method === 'addSection' || method === 'add_section') {
|
|
576
|
-
return this.handleAddSection(params);
|
|
577
|
-
}
|
|
578
|
-
if (
|
|
579
|
-
method === 'updateSection' ||
|
|
580
|
-
method === 'update_section'
|
|
581
|
-
) {
|
|
582
|
-
return this.handleUpdateSection(params);
|
|
583
|
-
}
|
|
584
|
-
if (
|
|
585
|
-
method === 'removeSection' ||
|
|
586
|
-
method === 'remove_section'
|
|
587
|
-
) {
|
|
588
|
-
return this.handleRemoveSection(params);
|
|
589
|
-
}
|
|
590
|
-
if (
|
|
591
|
-
method === 'groupSections' ||
|
|
592
|
-
method === 'group_sections'
|
|
593
|
-
) {
|
|
594
|
-
return this.handleGroupSections(params);
|
|
595
|
-
}
|
|
596
|
-
if (
|
|
597
|
-
method === 'removeGrouping' ||
|
|
598
|
-
method === 'remove_grouping'
|
|
599
|
-
) {
|
|
600
|
-
return this.handleRemoveGrouping(params);
|
|
601
|
-
}
|
|
602
|
-
if (method === 'gc') {
|
|
603
|
-
return this.handleGc();
|
|
604
|
-
}
|
|
605
|
-
if (
|
|
606
|
-
method === 'rebuildIndexes' ||
|
|
607
|
-
method === 'rebuild_indexes'
|
|
608
|
-
) {
|
|
609
|
-
return this.handleRebuild();
|
|
610
|
-
}
|
|
611
|
-
if (
|
|
612
|
-
method === 'initDirectory' ||
|
|
613
|
-
method === 'init_directory'
|
|
614
|
-
) {
|
|
615
|
-
return this.handleInitDirectory(params);
|
|
616
|
-
}
|
|
617
|
-
if (method === 'migrateDatabase') {
|
|
618
|
-
throw new IpcError(
|
|
619
|
-
-32601,
|
|
620
|
-
'migrateDatabase is not yet supported',
|
|
621
|
-
);
|
|
622
|
-
}
|
|
623
|
-
return this.invokeWasmRaw(wasmExport, new Uint8Array(0));
|
|
624
|
-
} finally {
|
|
625
|
-
this.releaseWriteLock();
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
// -- Search/query (token-based async) --
|
|
630
|
-
|
|
631
|
-
private handleSearch(params: Record<string, unknown>): unknown {
|
|
632
|
-
const query = (params['query'] as string | undefined) ?? '';
|
|
633
|
-
const mode = (params['mode'] as string | undefined) ?? 'and';
|
|
634
|
-
const limit = Number(params['limit'] ?? 20);
|
|
635
|
-
const offset = Number(params['offset'] ?? 0);
|
|
636
|
-
const encoded = encodeSearchParams(query, mode, limit, offset);
|
|
637
|
-
|
|
638
|
-
const searchFn = this.getExport('worker_search');
|
|
639
|
-
const ptr = this.wasmAlloc(encoded.length);
|
|
640
|
-
this.wasmWrite(ptr, encoded);
|
|
641
|
-
const token = searchFn(ptr, encoded.length) as number;
|
|
642
|
-
this.wasmFree(ptr, encoded.length);
|
|
643
|
-
|
|
644
|
-
const statusFn = this.getExport('worker_result_status');
|
|
645
|
-
const status = statusFn(token) as number;
|
|
646
|
-
if (status === 3) {
|
|
647
|
-
const getResultFn = this.getExport('worker_get_result');
|
|
648
|
-
getResultFn(token);
|
|
649
|
-
const errBytes = this.readReturnSlot();
|
|
650
|
-
const errMsg = new TextDecoder().decode(errBytes);
|
|
651
|
-
throw new IpcError(-32000, errMsg);
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
const getResultFn = this.getExport('worker_get_result');
|
|
655
|
-
const rc = getResultFn(token) as number;
|
|
656
|
-
if (rc === -1) {
|
|
657
|
-
const errBytes = this.readReturnSlot();
|
|
658
|
-
throw new IpcError(-32000, new TextDecoder().decode(errBytes));
|
|
659
|
-
}
|
|
660
|
-
const resultBytes = this.readReturnSlot();
|
|
661
|
-
return decodePagedSearchResult(resultBytes);
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// -- Token status/result (u32 direct params) --
|
|
665
|
-
|
|
666
|
-
private handleResultStatus(
|
|
667
|
-
params: Record<string, unknown>,
|
|
668
|
-
): unknown {
|
|
669
|
-
const token = Number(params['token'] ?? 0);
|
|
670
|
-
const fn = this.getExport('worker_result_status');
|
|
671
|
-
const status = fn(token) as number;
|
|
672
|
-
return { status };
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
private handleGetResult(params: Record<string, unknown>): unknown {
|
|
676
|
-
const token = Number(params['token'] ?? 0);
|
|
677
|
-
const fn = this.getExport('worker_get_result');
|
|
678
|
-
const rc = fn(token) as number;
|
|
679
|
-
if (rc === -1) {
|
|
680
|
-
const errBytes = this.readReturnSlot();
|
|
681
|
-
throw new IpcError(-32000, new TextDecoder().decode(errBytes));
|
|
682
|
-
}
|
|
683
|
-
const bytes = this.readReturnSlot();
|
|
684
|
-
return decodePagedSearchResult(bytes);
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
// -- Binary-encoded input methods --
|
|
688
|
-
|
|
689
|
-
private handleAddSection(params: Record<string, unknown>): unknown {
|
|
690
|
-
const sectionType = (params['sectionType'] ?? 'text') as string;
|
|
691
|
-
const semanticType =
|
|
692
|
-
sectionType === 'text' ||
|
|
693
|
-
sectionType === 'code' ||
|
|
694
|
-
sectionType === 'image'
|
|
695
|
-
? sectionType
|
|
696
|
-
: 'text';
|
|
697
|
-
const typeName =
|
|
698
|
-
sectionType !== semanticType ? sectionType : null;
|
|
699
|
-
const tags = Array.isArray(params['tags'])
|
|
700
|
-
? (params['tags'] as string[])
|
|
701
|
-
: [];
|
|
702
|
-
const input: AddSectionInput = {
|
|
703
|
-
sectionType: semanticType,
|
|
704
|
-
mimeType: params['mimeType'] as string | undefined,
|
|
705
|
-
content: (params['content'] as string | undefined) ?? '',
|
|
706
|
-
title: (params['title'] as string | null) ?? null,
|
|
707
|
-
description: (params['description'] as string | null) ?? null,
|
|
708
|
-
docid: (params['docid'] as string | null) ?? null,
|
|
709
|
-
typeName,
|
|
710
|
-
sourcePath:
|
|
711
|
-
typeof params['sourcePath'] === 'string'
|
|
712
|
-
? params['sourcePath']
|
|
713
|
-
: undefined,
|
|
714
|
-
sourceMtime:
|
|
715
|
-
typeof params['sourceMtime'] === 'string'
|
|
716
|
-
? params['sourceMtime']
|
|
717
|
-
: undefined,
|
|
718
|
-
tags,
|
|
719
|
-
replace: params['replace'] === true,
|
|
720
|
-
};
|
|
721
|
-
const encoded = encodeAddSectionParams(input);
|
|
722
|
-
const bytes = this.callWasmSync('worker_add_section', encoded);
|
|
723
|
-
const decoded = decodeAddSectionResult(bytes);
|
|
724
|
-
const nearDups =
|
|
725
|
-
decoded.nearDuplicates.length > 0
|
|
726
|
-
? decoded.nearDuplicates
|
|
727
|
-
: this.scanNearDuplicates(input.content, decoded.kbid);
|
|
728
|
-
return {
|
|
729
|
-
kbid: decoded.kbid,
|
|
730
|
-
indexed_terms_count: decoded.indexedTermsCount,
|
|
731
|
-
elapsed_ms: decoded.elapsedMs,
|
|
732
|
-
superseded: decoded.superseded,
|
|
733
|
-
warnings: decoded.warnings,
|
|
734
|
-
near_duplicates: nearDups,
|
|
735
|
-
};
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
private handleUpdateSection(
|
|
739
|
-
params: Record<string, unknown>,
|
|
740
|
-
): unknown {
|
|
741
|
-
const oldKbid = (params['kbid'] as string | undefined) ?? '';
|
|
742
|
-
const updSectionType = (params['sectionType'] ??
|
|
743
|
-
'text') as string;
|
|
744
|
-
const updSemanticType =
|
|
745
|
-
updSectionType === 'text' ||
|
|
746
|
-
updSectionType === 'code' ||
|
|
747
|
-
updSectionType === 'image'
|
|
748
|
-
? updSectionType
|
|
749
|
-
: 'text';
|
|
750
|
-
const updTypeName =
|
|
751
|
-
updSectionType !== updSemanticType ? updSectionType : null;
|
|
752
|
-
const input: AddSectionInput = {
|
|
753
|
-
sectionType: updSemanticType,
|
|
754
|
-
mimeType: params['mimeType'] as string | undefined,
|
|
755
|
-
content: (params['content'] as string | undefined) ?? '',
|
|
756
|
-
title: (params['title'] as string | null) ?? null,
|
|
757
|
-
description: (params['description'] as string | null) ?? null,
|
|
758
|
-
docid: (params['docid'] as string | null) ?? null,
|
|
759
|
-
typeName: updTypeName,
|
|
760
|
-
};
|
|
761
|
-
const encoded = encodeUpdateSectionParams(oldKbid, input);
|
|
762
|
-
const bytes = this.callWasmSync('worker_update_section', encoded);
|
|
763
|
-
const newKbid = new TextDecoder().decode(bytes);
|
|
764
|
-
return { kbid: newKbid };
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
private handleReadSections(
|
|
768
|
-
params: Record<string, unknown>,
|
|
769
|
-
): unknown {
|
|
770
|
-
const kbids = (params['kbids'] ?? []) as string[];
|
|
771
|
-
const encoded = encodeKbidList(kbids);
|
|
772
|
-
const bytes = this.callWasmSync('worker_read_sections', encoded);
|
|
773
|
-
return decodeSectionRecords(bytes);
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
private handleGroupSections(
|
|
777
|
-
params: Record<string, unknown>,
|
|
778
|
-
): unknown {
|
|
779
|
-
const title = (params['title'] as string | undefined) ?? '';
|
|
780
|
-
const kbids = (params['kbids'] ?? []) as string[];
|
|
781
|
-
const docType = (params['docType'] as string | undefined) ?? '';
|
|
782
|
-
const encoded = encodeGroupParams(title, kbids, docType);
|
|
783
|
-
const bytes = this.callWasmSync('worker_group_sections', encoded);
|
|
784
|
-
const docid = new TextDecoder().decode(bytes);
|
|
785
|
-
return { docid };
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
private handleCompose(params: Record<string, unknown>): unknown {
|
|
789
|
-
const ids = (params['ids'] ?? []) as string[];
|
|
790
|
-
const encoded = encodeIdentifierList(ids);
|
|
791
|
-
const bytes = this.callWasmSync('worker_compose', encoded);
|
|
792
|
-
const output = decodeComposeOutput(bytes);
|
|
793
|
-
return {
|
|
794
|
-
data: output.markdown,
|
|
795
|
-
total: Number(output.totalChars),
|
|
796
|
-
};
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
// -- Raw UTF-8 string input methods --
|
|
800
|
-
|
|
801
|
-
private handleRemoveSection(
|
|
802
|
-
params: Record<string, unknown>,
|
|
803
|
-
): unknown {
|
|
804
|
-
const kbid = (params['kbid'] as string | undefined) ?? '';
|
|
805
|
-
const encoded = new TextEncoder().encode(kbid);
|
|
806
|
-
const bytes = this.callWasmSync('worker_remove_section', encoded);
|
|
807
|
-
return { removed: decodeRemoveFlag(bytes) };
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
private handleRetrieveDoc(params: Record<string, unknown>): unknown {
|
|
811
|
-
const docid = (params['docid'] as string | undefined) ?? '';
|
|
812
|
-
const encoded = new TextEncoder().encode(docid);
|
|
813
|
-
const bytes = this.callWasmSync('worker_retrieve_doc', encoded);
|
|
814
|
-
return decodeDocumentManifest(bytes);
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
private handleRemoveGrouping(
|
|
818
|
-
params: Record<string, unknown>,
|
|
819
|
-
): unknown {
|
|
820
|
-
const docid = (params['docid'] as string | undefined) ?? '';
|
|
821
|
-
const encoded = new TextEncoder().encode(docid);
|
|
822
|
-
this.callWasmSync('worker_remove_grouping', encoded);
|
|
823
|
-
return { ok: true };
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
private handleInitDirectory(
|
|
827
|
-
params: Record<string, unknown>,
|
|
828
|
-
): unknown {
|
|
829
|
-
const path =
|
|
830
|
-
(params['path'] as string | undefined) ?? this.targetDir;
|
|
831
|
-
const encoded = new TextEncoder().encode(path);
|
|
832
|
-
this.callWasmSync('worker_init_directory', encoded);
|
|
833
|
-
return { ok: true };
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
private handleInvalidate(params: Record<string, unknown>): unknown {
|
|
837
|
-
const kbid = (params['kbid'] as string | undefined) ?? '';
|
|
838
|
-
const encoded = new TextEncoder().encode(kbid);
|
|
839
|
-
const fn = this.getExport('worker_invalidate');
|
|
840
|
-
const ptr = this.wasmAlloc(encoded.length);
|
|
841
|
-
this.wasmWrite(ptr, encoded);
|
|
842
|
-
const rc = fn(ptr, encoded.length) as number;
|
|
843
|
-
this.wasmFree(ptr, encoded.length);
|
|
844
|
-
if (rc === -1) {
|
|
845
|
-
const errBytes = this.readReturnSlot();
|
|
846
|
-
throw new IpcError(
|
|
847
|
-
-32000,
|
|
848
|
-
new TextDecoder().decode(errBytes) || 'invalidate failed',
|
|
849
|
-
);
|
|
850
|
-
}
|
|
851
|
-
return { ok: true };
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
private handleListByType(params: Record<string, unknown>): unknown {
|
|
855
|
-
const typeStr =
|
|
856
|
-
(params['sectionType'] as string | undefined) ?? '';
|
|
857
|
-
const encoded = encodeTypeFilterParam(typeStr);
|
|
858
|
-
const bytes = this.callWasmSync('worker_list_by_type', encoded);
|
|
859
|
-
return decodeSectionRecordList(bytes);
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
private handleListDocsByType(
|
|
863
|
-
params: Record<string, unknown>,
|
|
864
|
-
): unknown {
|
|
865
|
-
const typeStr = (params['docType'] as string | undefined) ?? '';
|
|
866
|
-
const encoded = encodeTypeFilterParam(typeStr);
|
|
867
|
-
const bytes = this.callWasmSync(
|
|
868
|
-
'worker_list_docs_by_type',
|
|
869
|
-
encoded,
|
|
870
|
-
);
|
|
871
|
-
return decodeDocumentManifestList(bytes);
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
private handleRecall(params: Record<string, unknown>): unknown {
|
|
875
|
-
const kbid =
|
|
876
|
-
typeof params['kbid'] === 'string'
|
|
877
|
-
? params['kbid']
|
|
878
|
-
: undefined;
|
|
879
|
-
const kbids = Array.isArray(params['kbids'])
|
|
880
|
-
? (params['kbids'] as string[])
|
|
881
|
-
: undefined;
|
|
882
|
-
const depth = Number(params['depth'] ?? 0);
|
|
883
|
-
const encoded = encodeRecallParams({ kbid, kbids, depth });
|
|
884
|
-
const bytes = this.callWasmSync('worker_recall', encoded);
|
|
885
|
-
return decodeRecallResult(bytes);
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
// -- Zero-arg methods --
|
|
889
|
-
|
|
890
|
-
private handleInvalidateAll(): unknown {
|
|
891
|
-
this.callWasmZeroArg('worker_invalidate_all');
|
|
892
|
-
return { ok: true };
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
private handleDbStatus(): unknown {
|
|
896
|
-
this.callWasmZeroArg('worker_status');
|
|
897
|
-
const bytes = this.readReturnSlot();
|
|
898
|
-
const text = new TextDecoder().decode(bytes);
|
|
899
|
-
return decodeKeyValueText(text);
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
private handleIntegrityCheck(): unknown {
|
|
903
|
-
this.callWasmZeroArg('worker_check_integrity');
|
|
904
|
-
const bytes = this.readReturnSlot();
|
|
905
|
-
const text = new TextDecoder().decode(bytes);
|
|
906
|
-
return decodeKeyValueText(text);
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
private handleGc(): unknown {
|
|
910
|
-
const start = Date.now();
|
|
911
|
-
this.callWasmZeroArg('worker_garbage_collect');
|
|
912
|
-
const bytes = this.readReturnSlot();
|
|
913
|
-
const text = new TextDecoder().decode(bytes);
|
|
914
|
-
const kv = decodeKeyValueText(text);
|
|
915
|
-
const removedCount = Number(kv['removed'] ?? 0);
|
|
916
|
-
const staleSources = Number(kv['stale_sources'] ?? 0);
|
|
917
|
-
return {
|
|
918
|
-
removed_sections: removedCount,
|
|
919
|
-
removed_bytes: 0,
|
|
920
|
-
elapsed_ms: Date.now() - start,
|
|
921
|
-
stale_sources: staleSources,
|
|
922
|
-
};
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
private handleRebuild(): unknown {
|
|
926
|
-
const fn = this.getExport('worker_rebuild_indexes');
|
|
927
|
-
const rc = fn() as number;
|
|
928
|
-
if (rc === -1) {
|
|
929
|
-
const errBytes = this.readReturnSlot();
|
|
930
|
-
const errMsg = new TextDecoder().decode(errBytes);
|
|
931
|
-
throw new IpcError(-32000, errMsg || 'rebuild failed');
|
|
932
|
-
}
|
|
933
|
-
const resultBytes = this.readReturnSlot();
|
|
934
|
-
const reindexed =
|
|
935
|
-
resultBytes.length >= 4
|
|
936
|
-
? new DataView(
|
|
937
|
-
resultBytes.buffer,
|
|
938
|
-
resultBytes.byteOffset,
|
|
939
|
-
resultBytes.byteLength,
|
|
940
|
-
).getUint32(0, true)
|
|
941
|
-
: 0;
|
|
942
|
-
return { ok: true, sections_reindexed: reindexed };
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
// -- Export (read operation, no lock required) --
|
|
946
|
-
|
|
947
|
-
private handleExport(params: Record<string, unknown>): unknown {
|
|
948
|
-
const targetPath =
|
|
949
|
-
(params['targetPath'] as string | undefined) ??
|
|
950
|
-
(params['path'] as string | undefined) ??
|
|
951
|
-
'./kbdb-export/';
|
|
952
|
-
const encoded = new TextEncoder().encode(targetPath);
|
|
953
|
-
const start = Date.now();
|
|
954
|
-
const bytes = this.callWasmSync('worker_export', encoded);
|
|
955
|
-
const elapsed = Date.now() - start;
|
|
956
|
-
const text = new TextDecoder().decode(bytes);
|
|
957
|
-
const kv = decodeKeyValueText(text);
|
|
958
|
-
return {
|
|
959
|
-
path: kv['path'] ?? targetPath,
|
|
960
|
-
sections_exported: Number(kv['sections_exported'] ?? 0),
|
|
961
|
-
documents_exported: Number(kv['documents_exported'] ?? 0),
|
|
962
|
-
elapsed_ms: elapsed,
|
|
963
|
-
};
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
// -- Near-duplicate detection --
|
|
967
|
-
|
|
968
|
-
private scanNearDuplicates(
|
|
969
|
-
content: string,
|
|
970
|
-
newKbid: string,
|
|
971
|
-
): { kbid: string; similarity: number }[] {
|
|
972
|
-
const newTerms = this.extractTermSet(content);
|
|
973
|
-
if (newTerms.size === 0) return [];
|
|
974
|
-
|
|
975
|
-
const sectionsDir = join(this.targetDir, 'sections');
|
|
976
|
-
let shards: string[];
|
|
977
|
-
try {
|
|
978
|
-
shards = readdirSync(sectionsDir);
|
|
979
|
-
} catch {
|
|
980
|
-
return [];
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
const results: { kbid: string; similarity: number }[] = [];
|
|
984
|
-
for (const shard of shards) {
|
|
985
|
-
let files: string[];
|
|
986
|
-
try {
|
|
987
|
-
files = readdirSync(join(sectionsDir, shard));
|
|
988
|
-
} catch {
|
|
989
|
-
continue;
|
|
990
|
-
}
|
|
991
|
-
for (const file of files) {
|
|
992
|
-
if (!file.endsWith('.section')) continue;
|
|
993
|
-
const kbid = file.slice(0, -8);
|
|
994
|
-
if (kbid === newKbid) continue;
|
|
995
|
-
try {
|
|
996
|
-
const data = readFileSync(
|
|
997
|
-
join(sectionsDir, shard, file),
|
|
998
|
-
'utf-8',
|
|
999
|
-
);
|
|
1000
|
-
const sep = data.indexOf('\n---\n');
|
|
1001
|
-
const body = sep >= 0 ? data.slice(sep + 5) : data;
|
|
1002
|
-
const existing = this.extractTermSet(body);
|
|
1003
|
-
let intersection = 0;
|
|
1004
|
-
for (const t of newTerms) {
|
|
1005
|
-
if (existing.has(t)) intersection++;
|
|
1006
|
-
}
|
|
1007
|
-
const union =
|
|
1008
|
-
newTerms.size + existing.size - intersection;
|
|
1009
|
-
const sim = union > 0 ? intersection / union : 0;
|
|
1010
|
-
if (sim >= 0.85) {
|
|
1011
|
-
results.push({
|
|
1012
|
-
kbid,
|
|
1013
|
-
similarity: Math.round(sim * 100) / 100,
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
} catch {
|
|
1017
|
-
continue;
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
return results;
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
private extractTermSet(text: string): Set<string> {
|
|
1025
|
-
return new Set(
|
|
1026
|
-
text
|
|
1027
|
-
.toLowerCase()
|
|
1028
|
-
.split(/\W+/)
|
|
1029
|
-
.filter((w) => w.length > 2),
|
|
1030
|
-
);
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
// -- Single-writer lock --
|
|
1034
|
-
|
|
1035
|
-
/**
|
|
1036
|
-
* Acquires the write lock.
|
|
1037
|
-
*
|
|
1038
|
-
* If the lock is free it is granted immediately. If it is held the
|
|
1039
|
-
* caller is queued and its promise resolves once the lock is
|
|
1040
|
-
* released by the current holder.
|
|
1041
|
-
*/
|
|
1042
|
-
private acquireWriteLock(): Promise<void> {
|
|
1043
|
-
if (!this._writeLocked) {
|
|
1044
|
-
this._writeLocked = true;
|
|
1045
|
-
return Promise.resolve();
|
|
1046
|
-
}
|
|
1047
|
-
return new Promise<void>((resolve) => {
|
|
1048
|
-
this._writeQueue.push({ resolve });
|
|
1049
|
-
});
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
/**
|
|
1053
|
-
* Releases the write lock.
|
|
1054
|
-
*
|
|
1055
|
-
* If waiters are queued the next one is granted the lock
|
|
1056
|
-
* immediately. Otherwise the lock is marked free.
|
|
1057
|
-
*/
|
|
1058
|
-
private releaseWriteLock(): void {
|
|
1059
|
-
const next = this._writeQueue.shift();
|
|
1060
|
-
if (next !== undefined) {
|
|
1061
|
-
next.resolve();
|
|
1062
|
-
} else {
|
|
1063
|
-
this._writeLocked = false;
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
// -- WASM lifecycle --
|
|
1068
|
-
|
|
1069
|
-
private initWorkerContext(): void {
|
|
1070
|
-
const pathBytes = new TextEncoder().encode('.');
|
|
1071
|
-
this.callWasmSync('worker_init', pathBytes);
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
/**
|
|
1075
|
-
* Runs a database integrity check immediately after context
|
|
1076
|
-
* initialisation.
|
|
1077
|
-
*
|
|
1078
|
-
* Stores the result in `_integrityOk` and `_integrityErrors`.
|
|
1079
|
-
* Logs a warning to stderr when issues are found so operators
|
|
1080
|
-
* are alerted without aborting the daemon.
|
|
1081
|
-
*/
|
|
1082
|
-
private runStartupIntegrityCheck(): void {
|
|
1083
|
-
try {
|
|
1084
|
-
this.callWasmZeroArg('worker_check_integrity');
|
|
1085
|
-
const bytes = this.readReturnSlot();
|
|
1086
|
-
const text = new TextDecoder().decode(bytes);
|
|
1087
|
-
const kv = decodeKeyValueText(text);
|
|
1088
|
-
this._integrityOk = kv['ok'] === 'true';
|
|
1089
|
-
if (!this._integrityOk) {
|
|
1090
|
-
this._integrityErrors = Object.entries(kv)
|
|
1091
|
-
.filter(([k]) => k !== 'ok')
|
|
1092
|
-
.map(([k, v]) => `${k}=${v}`);
|
|
1093
|
-
// eslint-disable-next-line no-console
|
|
1094
|
-
console.error(
|
|
1095
|
-
'[kbdb-worker] startup integrity check failed:',
|
|
1096
|
-
this._integrityErrors.join(', '),
|
|
1097
|
-
);
|
|
1098
|
-
}
|
|
1099
|
-
} catch {
|
|
1100
|
-
this._integrityOk = false;
|
|
1101
|
-
this._integrityErrors = ['integrity_check_failed'];
|
|
1102
|
-
// eslint-disable-next-line no-console
|
|
1103
|
-
console.error(
|
|
1104
|
-
'[kbdb-worker] startup integrity check threw an error',
|
|
1105
|
-
);
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
// -- WASM bridge primitives --
|
|
1110
|
-
|
|
1111
|
-
private getExport(name: string): WasmFn {
|
|
1112
|
-
if (this._wasmModules === null) {
|
|
1113
|
-
throw new Error('WASM modules not loaded');
|
|
1114
|
-
}
|
|
1115
|
-
const fn = this._wasmModules.kbWorker.exports[name] as
|
|
1116
|
-
| WasmFn
|
|
1117
|
-
| undefined;
|
|
1118
|
-
if (typeof fn !== 'function') {
|
|
1119
|
-
throw new Error(`WASM export not found: ${name}`);
|
|
1120
|
-
}
|
|
1121
|
-
return fn;
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
private wasmAlloc(size: number): number {
|
|
1125
|
-
if (size === 0) return 0;
|
|
1126
|
-
const allocFn = this._wasmModules?.kbWorker.exports[
|
|
1127
|
-
'kbdb_alloc'
|
|
1128
|
-
] as WasmFn | undefined;
|
|
1129
|
-
if (typeof allocFn !== 'function') return 0;
|
|
1130
|
-
return allocFn(size) as number;
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
private wasmFree(ptr: number, size: number): void {
|
|
1134
|
-
if (ptr === 0 || size === 0) return;
|
|
1135
|
-
const freeFn = this._wasmModules?.kbWorker.exports[
|
|
1136
|
-
'kbdb_free'
|
|
1137
|
-
] as WasmFn | undefined;
|
|
1138
|
-
if (typeof freeFn === 'function') {
|
|
1139
|
-
freeFn(ptr, size);
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
private wasmWrite(ptr: number, data: Uint8Array): void {
|
|
1144
|
-
if (data.length === 0) return;
|
|
1145
|
-
const memory = this._wasmModules?.memory;
|
|
1146
|
-
if (!memory) return;
|
|
1147
|
-
const memView = new Uint8Array(memory.buffer);
|
|
1148
|
-
if (ptr + data.length > memView.length) {
|
|
1149
|
-
throw new Error('WASM memory overflow');
|
|
1150
|
-
}
|
|
1151
|
-
memView.set(data, ptr);
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
private readReturnSlot(): Uint8Array {
|
|
1155
|
-
const getPtrFn = this._wasmModules?.kbWorker.exports[
|
|
1156
|
-
'get_return_ptr'
|
|
1157
|
-
] as WasmFn | undefined;
|
|
1158
|
-
const getLenFn = this._wasmModules?.kbWorker.exports[
|
|
1159
|
-
'get_return_len'
|
|
1160
|
-
] as WasmFn | undefined;
|
|
1161
|
-
if (
|
|
1162
|
-
typeof getPtrFn !== 'function' ||
|
|
1163
|
-
typeof getLenFn !== 'function'
|
|
1164
|
-
) {
|
|
1165
|
-
return new Uint8Array(0);
|
|
1166
|
-
}
|
|
1167
|
-
const ptr = getPtrFn() as number;
|
|
1168
|
-
const len = getLenFn() as number;
|
|
1169
|
-
if (ptr === 0 || len === 0) {
|
|
1170
|
-
return new Uint8Array(0);
|
|
1171
|
-
}
|
|
1172
|
-
const memory = this._wasmModules?.memory;
|
|
1173
|
-
if (!memory) return new Uint8Array(0);
|
|
1174
|
-
const data = new Uint8Array(memory.buffer, ptr, len).slice();
|
|
1175
|
-
this.wasmFree(ptr, len);
|
|
1176
|
-
return data;
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
private callWasmSync(
|
|
1180
|
-
exportName: string,
|
|
1181
|
-
input: Uint8Array,
|
|
1182
|
-
): Uint8Array {
|
|
1183
|
-
const fn = this.getExport(exportName);
|
|
1184
|
-
const ptr = this.wasmAlloc(input.length);
|
|
1185
|
-
this.wasmWrite(ptr, input);
|
|
1186
|
-
const rc = fn(ptr, input.length) as number;
|
|
1187
|
-
this.wasmFree(ptr, input.length);
|
|
1188
|
-
if (rc === -1) {
|
|
1189
|
-
const errBytes = this.readReturnSlot();
|
|
1190
|
-
const errMsg = new TextDecoder().decode(errBytes);
|
|
1191
|
-
throw new IpcError(-32000, errMsg || exportName + ' failed');
|
|
1192
|
-
}
|
|
1193
|
-
return this.readReturnSlot();
|
|
1194
|
-
}
|
|
1195
|
-
|
|
1196
|
-
private callWasmZeroArg(exportName: string): void {
|
|
1197
|
-
const fn = this.getExport(exportName);
|
|
1198
|
-
const rc = fn() as number;
|
|
1199
|
-
if (rc === -1) {
|
|
1200
|
-
const errBytes = this.readReturnSlot();
|
|
1201
|
-
const errMsg = new TextDecoder().decode(errBytes);
|
|
1202
|
-
throw new IpcError(-32000, errMsg || exportName + ' failed');
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
private invokeWasmRaw(
|
|
1207
|
-
exportName: string,
|
|
1208
|
-
input: Uint8Array,
|
|
1209
|
-
): unknown {
|
|
1210
|
-
return this.callWasmSync(exportName, input);
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
private handleCheckVersion(
|
|
1214
|
-
params: Record<string, unknown>,
|
|
1215
|
-
): unknown {
|
|
1216
|
-
const targetPath =
|
|
1217
|
-
typeof params.targetPath === 'string'
|
|
1218
|
-
? params.targetPath
|
|
1219
|
-
: this.targetDir;
|
|
1220
|
-
const catalogPath = join(targetPath, 'catalog.toml');
|
|
1221
|
-
let text: string;
|
|
1222
|
-
try {
|
|
1223
|
-
text = readFileSync(catalogPath, 'utf-8');
|
|
1224
|
-
} catch {
|
|
1225
|
-
return {
|
|
1226
|
-
status: 'needs_migration',
|
|
1227
|
-
currentVersion: 0,
|
|
1228
|
-
requiredVersion: DB_FORMAT_VERSION,
|
|
1229
|
-
};
|
|
1230
|
-
}
|
|
1231
|
-
const version = parseCatalogVersion(text);
|
|
1232
|
-
if (version === null) {
|
|
1233
|
-
return {
|
|
1234
|
-
status: 'needs_migration',
|
|
1235
|
-
currentVersion: 0,
|
|
1236
|
-
requiredVersion: DB_FORMAT_VERSION,
|
|
1237
|
-
};
|
|
1238
|
-
}
|
|
1239
|
-
if (version > DB_FORMAT_VERSION) {
|
|
1240
|
-
return {
|
|
1241
|
-
status: 'too_new',
|
|
1242
|
-
currentVersion: version,
|
|
1243
|
-
requiredVersion: DB_FORMAT_VERSION,
|
|
1244
|
-
};
|
|
1245
|
-
}
|
|
1246
|
-
if (version < DB_FORMAT_VERSION) {
|
|
1247
|
-
return {
|
|
1248
|
-
status: 'needs_migration',
|
|
1249
|
-
currentVersion: version,
|
|
1250
|
-
requiredVersion: DB_FORMAT_VERSION,
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
return {
|
|
1254
|
-
status: 'compatible',
|
|
1255
|
-
currentVersion: version,
|
|
1256
|
-
requiredVersion: DB_FORMAT_VERSION,
|
|
1257
|
-
};
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
/** Returns a daemon config value by config method name. */
|
|
1261
|
-
private handleConfigMethod(method: string): unknown {
|
|
1262
|
-
const key = method.slice(CONFIG_PREFIX.length);
|
|
1263
|
-
const prop = CONFIG_KEY_MAP[key];
|
|
1264
|
-
if (prop === undefined) {
|
|
1265
|
-
throw new IpcError(-32601, `Method not found: ${method}`);
|
|
1266
|
-
}
|
|
1267
|
-
return this.config[prop];
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
// ---------------------------------------------------------------------------
|
|
1272
|
-
// Module-private helpers
|
|
1273
|
-
// ---------------------------------------------------------------------------
|
|
1274
|
-
|
|
1275
|
-
/**
|
|
1276
|
-
* Parses the `version` field from a minimal TOML string.
|
|
1277
|
-
*
|
|
1278
|
-
* Supports only `version = <integer>` syntax. Returns `null` if the
|
|
1279
|
-
* field is absent.
|
|
1280
|
-
*/
|
|
1281
|
-
function parseCatalogVersion(text: string): number | null {
|
|
1282
|
-
for (const line of text.split('\n')) {
|
|
1283
|
-
const trimmed = line.trim();
|
|
1284
|
-
if (trimmed.startsWith('#')) continue;
|
|
1285
|
-
const match = /^version\s*=\s*(\d+)/.exec(trimmed);
|
|
1286
|
-
if (match?.[1] !== undefined) {
|
|
1287
|
-
return parseInt(match[1], 10);
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
return null;
|
|
1291
|
-
}
|