kirograph 0.12.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 +1171 -0
- package/dist/architecture/index.d.ts +11 -0
- package/dist/architecture/index.d.ts.map +1 -0
- package/dist/architecture/index.js +207 -0
- package/dist/architecture/index.js.map +7 -0
- package/dist/architecture/layers/csharp.d.ts +6 -0
- package/dist/architecture/layers/csharp.d.ts.map +1 -0
- package/dist/architecture/layers/csharp.js +100 -0
- package/dist/architecture/layers/csharp.js.map +7 -0
- package/dist/architecture/layers/elixir.js +116 -0
- package/dist/architecture/layers/elixir.js.map +7 -0
- package/dist/architecture/layers/go.d.ts +7 -0
- package/dist/architecture/layers/go.d.ts.map +1 -0
- package/dist/architecture/layers/go.js +117 -0
- package/dist/architecture/layers/go.js.map +7 -0
- package/dist/architecture/layers/index.d.ts +30 -0
- package/dist/architecture/layers/index.d.ts.map +1 -0
- package/dist/architecture/layers/index.js +100 -0
- package/dist/architecture/layers/index.js.map +7 -0
- package/dist/architecture/layers/java.d.ts +7 -0
- package/dist/architecture/layers/java.d.ts.map +1 -0
- package/dist/architecture/layers/java.js +119 -0
- package/dist/architecture/layers/java.js.map +7 -0
- package/dist/architecture/layers/python.d.ts +7 -0
- package/dist/architecture/layers/python.d.ts.map +1 -0
- package/dist/architecture/layers/python.js +111 -0
- package/dist/architecture/layers/python.js.map +7 -0
- package/dist/architecture/layers/ruby.d.ts +6 -0
- package/dist/architecture/layers/ruby.d.ts.map +1 -0
- package/dist/architecture/layers/ruby.js +95 -0
- package/dist/architecture/layers/ruby.js.map +7 -0
- package/dist/architecture/layers/rust.d.ts +6 -0
- package/dist/architecture/layers/rust.d.ts.map +1 -0
- package/dist/architecture/layers/rust.js +98 -0
- package/dist/architecture/layers/rust.js.map +7 -0
- package/dist/architecture/layers/types.d.ts +2 -0
- package/dist/architecture/layers/types.d.ts.map +1 -0
- package/dist/architecture/layers/types.js +17 -0
- package/dist/architecture/layers/types.js.map +7 -0
- package/dist/architecture/layers/typescript.d.ts +9 -0
- package/dist/architecture/layers/typescript.d.ts.map +1 -0
- package/dist/architecture/layers/typescript.js +143 -0
- package/dist/architecture/layers/typescript.js.map +7 -0
- package/dist/architecture/manifest/cargo.d.ts +3 -0
- package/dist/architecture/manifest/cargo.d.ts.map +1 -0
- package/dist/architecture/manifest/cargo.js +94 -0
- package/dist/architecture/manifest/cargo.js.map +7 -0
- package/dist/architecture/manifest/csproj.d.ts +3 -0
- package/dist/architecture/manifest/csproj.d.ts.map +1 -0
- package/dist/architecture/manifest/csproj.js +75 -0
- package/dist/architecture/manifest/csproj.js.map +7 -0
- package/dist/architecture/manifest/go.d.ts +3 -0
- package/dist/architecture/manifest/go.d.ts.map +1 -0
- package/dist/architecture/manifest/go.js +85 -0
- package/dist/architecture/manifest/go.js.map +7 -0
- package/dist/architecture/manifest/gradle.d.ts +3 -0
- package/dist/architecture/manifest/gradle.d.ts.map +1 -0
- package/dist/architecture/manifest/gradle.js +80 -0
- package/dist/architecture/manifest/gradle.js.map +7 -0
- package/dist/architecture/manifest/index.d.ts +12 -0
- package/dist/architecture/manifest/index.d.ts.map +1 -0
- package/dist/architecture/manifest/index.js +130 -0
- package/dist/architecture/manifest/index.js.map +7 -0
- package/dist/architecture/manifest/maven.d.ts +3 -0
- package/dist/architecture/manifest/maven.d.ts.map +1 -0
- package/dist/architecture/manifest/maven.js +76 -0
- package/dist/architecture/manifest/maven.js.map +7 -0
- package/dist/architecture/manifest/npm.d.ts +3 -0
- package/dist/architecture/manifest/npm.d.ts.map +1 -0
- package/dist/architecture/manifest/npm.js +103 -0
- package/dist/architecture/manifest/npm.js.map +7 -0
- package/dist/architecture/manifest/python.d.ts +3 -0
- package/dist/architecture/manifest/python.d.ts.map +1 -0
- package/dist/architecture/manifest/python.js +105 -0
- package/dist/architecture/manifest/python.js.map +7 -0
- package/dist/architecture/manifest/types.d.ts +2 -0
- package/dist/architecture/manifest/types.d.ts.map +1 -0
- package/dist/architecture/manifest/types.js +17 -0
- package/dist/architecture/manifest/types.js.map +7 -0
- package/dist/architecture/types.d.ts +91 -0
- package/dist/architecture/types.d.ts.map +1 -0
- package/dist/architecture/types.js +17 -0
- package/dist/architecture/types.js.map +7 -0
- package/dist/assets/logo.png +0 -0
- package/dist/banner.d.ts +6 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/banner.js +67 -0
- package/dist/banner.js.map +1 -0
- package/dist/bin/banner.d.ts +6 -0
- package/dist/bin/banner.d.ts.map +1 -0
- package/dist/bin/banner.js +88 -0
- package/dist/bin/banner.js.map +7 -0
- package/dist/bin/commands/affected.d.ts +3 -0
- package/dist/bin/commands/affected.d.ts.map +1 -0
- package/dist/bin/commands/affected.js +78 -0
- package/dist/bin/commands/affected.js.map +7 -0
- package/dist/bin/commands/architecture.d.ts +3 -0
- package/dist/bin/commands/architecture.d.ts.map +1 -0
- package/dist/bin/commands/architecture.js +125 -0
- package/dist/bin/commands/architecture.js.map +7 -0
- package/dist/bin/commands/caveman.js +136 -0
- package/dist/bin/commands/caveman.js.map +7 -0
- package/dist/bin/commands/context.d.ts +3 -0
- package/dist/bin/commands/context.d.ts.map +1 -0
- package/dist/bin/commands/context.js +81 -0
- package/dist/bin/commands/context.js.map +7 -0
- package/dist/bin/commands/coupling.d.ts +3 -0
- package/dist/bin/commands/coupling.d.ts.map +1 -0
- package/dist/bin/commands/coupling.js +164 -0
- package/dist/bin/commands/coupling.js.map +7 -0
- package/dist/bin/commands/dashboard.d.ts +3 -0
- package/dist/bin/commands/dashboard.d.ts.map +1 -0
- package/dist/bin/commands/dashboard.js +209 -0
- package/dist/bin/commands/dashboard.js.map +7 -0
- package/dist/bin/commands/dead-code.js +77 -0
- package/dist/bin/commands/dead-code.js.map +7 -0
- package/dist/bin/commands/export.js +2620 -0
- package/dist/bin/commands/export.js.map +7 -0
- package/dist/bin/commands/files.d.ts +3 -0
- package/dist/bin/commands/files.d.ts.map +1 -0
- package/dist/bin/commands/files.js +104 -0
- package/dist/bin/commands/files.js.map +7 -0
- package/dist/bin/commands/help.d.ts +4 -0
- package/dist/bin/commands/help.d.ts.map +1 -0
- package/dist/bin/commands/help.js +212 -0
- package/dist/bin/commands/help.js.map +7 -0
- package/dist/bin/commands/hotspots.js +77 -0
- package/dist/bin/commands/hotspots.js.map +7 -0
- package/dist/bin/commands/index.d.ts +3 -0
- package/dist/bin/commands/index.d.ts.map +1 -0
- package/dist/bin/commands/index.js +58 -0
- package/dist/bin/commands/index.js.map +7 -0
- package/dist/bin/commands/init.d.ts +3 -0
- package/dist/bin/commands/init.d.ts.map +1 -0
- package/dist/bin/commands/init.js +68 -0
- package/dist/bin/commands/init.js.map +7 -0
- package/dist/bin/commands/install.d.ts +3 -0
- package/dist/bin/commands/install.d.ts.map +1 -0
- package/dist/bin/commands/install.js +34 -0
- package/dist/bin/commands/install.js.map +7 -0
- package/dist/bin/commands/mark-dirty.d.ts +3 -0
- package/dist/bin/commands/mark-dirty.d.ts.map +1 -0
- package/dist/bin/commands/mark-dirty.js +51 -0
- package/dist/bin/commands/mark-dirty.js.map +7 -0
- package/dist/bin/commands/package.d.ts +3 -0
- package/dist/bin/commands/package.d.ts.map +1 -0
- package/dist/bin/commands/package.js +139 -0
- package/dist/bin/commands/package.js.map +7 -0
- package/dist/bin/commands/path.js +93 -0
- package/dist/bin/commands/path.js.map +7 -0
- package/dist/bin/commands/qdrant.d.ts +3 -0
- package/dist/bin/commands/qdrant.d.ts.map +1 -0
- package/dist/bin/commands/qdrant.js +159 -0
- package/dist/bin/commands/qdrant.js.map +1 -0
- package/dist/bin/commands/query.d.ts +3 -0
- package/dist/bin/commands/query.d.ts.map +1 -0
- package/dist/bin/commands/query.js +47 -0
- package/dist/bin/commands/query.js.map +7 -0
- package/dist/bin/commands/serve.d.ts +3 -0
- package/dist/bin/commands/serve.d.ts.map +1 -0
- package/dist/bin/commands/serve.js +59 -0
- package/dist/bin/commands/serve.js.map +7 -0
- package/dist/bin/commands/snapshot.js +122 -0
- package/dist/bin/commands/snapshot.js.map +7 -0
- package/dist/bin/commands/status.d.ts +3 -0
- package/dist/bin/commands/status.d.ts.map +1 -0
- package/dist/bin/commands/status.js +107 -0
- package/dist/bin/commands/status.js.map +7 -0
- package/dist/bin/commands/stop.d.ts +3 -0
- package/dist/bin/commands/stop.d.ts.map +1 -0
- package/dist/bin/commands/stop.js +81 -0
- package/dist/bin/commands/stop.js.map +1 -0
- package/dist/bin/commands/surprising.js +79 -0
- package/dist/bin/commands/surprising.js.map +7 -0
- package/dist/bin/commands/sync-if-dirty.d.ts +3 -0
- package/dist/bin/commands/sync-if-dirty.d.ts.map +1 -0
- package/dist/bin/commands/sync-if-dirty.js +67 -0
- package/dist/bin/commands/sync-if-dirty.js.map +7 -0
- package/dist/bin/commands/sync.d.ts +3 -0
- package/dist/bin/commands/sync.d.ts.map +1 -0
- package/dist/bin/commands/sync.js +81 -0
- package/dist/bin/commands/sync.js.map +7 -0
- package/dist/bin/commands/typesense.d.ts +3 -0
- package/dist/bin/commands/typesense.d.ts.map +1 -0
- package/dist/bin/commands/typesense.js +126 -0
- package/dist/bin/commands/typesense.js.map +1 -0
- package/dist/bin/commands/uninit.d.ts +4 -0
- package/dist/bin/commands/uninit.d.ts.map +1 -0
- package/dist/bin/commands/uninit.js +123 -0
- package/dist/bin/commands/uninit.js.map +7 -0
- package/dist/bin/commands/unlock.d.ts +3 -0
- package/dist/bin/commands/unlock.d.ts.map +1 -0
- package/dist/bin/commands/unlock.js +53 -0
- package/dist/bin/commands/unlock.js.map +7 -0
- package/dist/bin/commands/utils.d.ts +12 -0
- package/dist/bin/commands/utils.d.ts.map +1 -0
- package/dist/bin/commands/utils.js +56 -0
- package/dist/bin/commands/utils.js.map +7 -0
- package/dist/bin/installer/archive.js +230 -0
- package/dist/bin/installer/archive.js.map +7 -0
- package/dist/bin/installer/caveman.js +57 -0
- package/dist/bin/installer/caveman.js.map +7 -0
- package/dist/bin/installer/cli-agent.d.ts +15 -0
- package/dist/bin/installer/cli-agent.d.ts.map +1 -0
- package/dist/bin/installer/cli-agent.js +89 -0
- package/dist/bin/installer/cli-agent.js.map +7 -0
- package/dist/bin/installer/config-prompt.d.ts +13 -0
- package/dist/bin/installer/config-prompt.d.ts.map +1 -0
- package/dist/bin/installer/config-prompt.js +158 -0
- package/dist/bin/installer/config-prompt.js.map +7 -0
- package/dist/bin/installer/dashboard.d.ts +3 -0
- package/dist/bin/installer/dashboard.d.ts.map +1 -0
- package/dist/bin/installer/dashboard.js +149 -0
- package/dist/bin/installer/dashboard.js.map +7 -0
- package/dist/bin/installer/hooks.d.ts +5 -0
- package/dist/bin/installer/hooks.d.ts.map +1 -0
- package/dist/bin/installer/hooks.js +155 -0
- package/dist/bin/installer/hooks.js.map +7 -0
- package/dist/bin/installer/index.d.ts +11 -0
- package/dist/bin/installer/index.d.ts.map +1 -0
- package/dist/bin/installer/index.js +228 -0
- package/dist/bin/installer/index.js.map +7 -0
- package/dist/bin/installer/mcp.d.ts +5 -0
- package/dist/bin/installer/mcp.d.ts.map +1 -0
- package/dist/bin/installer/mcp.js +80 -0
- package/dist/bin/installer/mcp.js.map +7 -0
- package/dist/bin/installer/prompts.d.ts +28 -0
- package/dist/bin/installer/prompts.d.ts.map +1 -0
- package/dist/bin/installer/prompts.js +134 -0
- package/dist/bin/installer/prompts.js.map +7 -0
- package/dist/bin/installer/qdrant-dashboard.d.ts +4 -0
- package/dist/bin/installer/qdrant-dashboard.d.ts.map +1 -0
- package/dist/bin/installer/qdrant-dashboard.js +115 -0
- package/dist/bin/installer/qdrant-dashboard.js.map +7 -0
- package/dist/bin/installer/steering.d.ts +5 -0
- package/dist/bin/installer/steering.d.ts.map +1 -0
- package/dist/bin/installer/steering.js +283 -0
- package/dist/bin/installer/steering.js.map +7 -0
- package/dist/bin/kirograph.d.ts +6 -0
- package/dist/bin/kirograph.d.ts.map +1 -0
- package/dist/bin/kirograph.js +95 -0
- package/dist/bin/kirograph.js.map +7 -0
- package/dist/bin/progress.d.ts +14 -0
- package/dist/bin/progress.d.ts.map +1 -0
- package/dist/bin/progress.js +201 -0
- package/dist/bin/progress.js.map +7 -0
- package/dist/bin/ui.d.ts +11 -0
- package/dist/bin/ui.d.ts.map +1 -0
- package/dist/bin/ui.js +71 -0
- package/dist/bin/ui.js.map +7 -0
- package/dist/config.d.ts +48 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +273 -0
- package/dist/config.js.map +7 -0
- package/dist/context/index.d.ts +61 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +224 -0
- package/dist/context/index.js.map +7 -0
- package/dist/core/file-tree.d.ts +15 -0
- package/dist/core/file-tree.d.ts.map +1 -0
- package/dist/core/file-tree.js +69 -0
- package/dist/core/file-tree.js.map +7 -0
- package/dist/core/lock-manager.d.ts +20 -0
- package/dist/core/lock-manager.d.ts.map +1 -0
- package/dist/core/lock-manager.js +120 -0
- package/dist/core/lock-manager.js.map +7 -0
- package/dist/core/pipeline.d.ts +37 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +375 -0
- package/dist/core/pipeline.js.map +7 -0
- package/dist/core/snapshot.js +141 -0
- package/dist/core/snapshot.js.map +7 -0
- package/dist/db/database.d.ts +133 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/database.js +929 -0
- package/dist/db/database.js.map +7 -0
- package/dist/db/schema.sql +174 -0
- package/dist/errors.d.ts +49 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +160 -0
- package/dist/errors.js.map +7 -0
- package/dist/extraction/extractor.d.ts +29 -0
- package/dist/extraction/extractor.d.ts.map +1 -0
- package/dist/extraction/extractor.js +764 -0
- package/dist/extraction/extractor.js.map +7 -0
- package/dist/extraction/grammars.d.ts +48 -0
- package/dist/extraction/grammars.d.ts.map +1 -0
- package/dist/extraction/grammars.js +166 -0
- package/dist/extraction/grammars.js.map +7 -0
- package/dist/extraction/languages.d.ts +9 -0
- package/dist/extraction/languages.d.ts.map +1 -0
- package/dist/extraction/languages.js +103 -0
- package/dist/extraction/languages.js.map +7 -0
- package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/dist/frameworks/csharp.d.ts +8 -0
- package/dist/frameworks/csharp.d.ts.map +1 -0
- package/dist/frameworks/csharp.js +93 -0
- package/dist/frameworks/csharp.js.map +7 -0
- package/dist/frameworks/elixir.js +142 -0
- package/dist/frameworks/elixir.js.map +7 -0
- package/dist/frameworks/express.d.ts +8 -0
- package/dist/frameworks/express.d.ts.map +1 -0
- package/dist/frameworks/express.js +143 -0
- package/dist/frameworks/express.js.map +7 -0
- package/dist/frameworks/go.d.ts +8 -0
- package/dist/frameworks/go.d.ts.map +1 -0
- package/dist/frameworks/go.js +85 -0
- package/dist/frameworks/go.js.map +7 -0
- package/dist/frameworks/index.d.ts +30 -0
- package/dist/frameworks/index.d.ts.map +1 -0
- package/dist/frameworks/index.js +243 -0
- package/dist/frameworks/index.js.map +7 -0
- package/dist/frameworks/java.d.ts +8 -0
- package/dist/frameworks/java.d.ts.map +1 -0
- package/dist/frameworks/java.js +87 -0
- package/dist/frameworks/java.js.map +7 -0
- package/dist/frameworks/laravel.d.ts +9 -0
- package/dist/frameworks/laravel.d.ts.map +1 -0
- package/dist/frameworks/laravel.js +115 -0
- package/dist/frameworks/laravel.js.map +7 -0
- package/dist/frameworks/python.d.ts +10 -0
- package/dist/frameworks/python.d.ts.map +1 -0
- package/dist/frameworks/python.js +158 -0
- package/dist/frameworks/python.js.map +7 -0
- package/dist/frameworks/react.d.ts +9 -0
- package/dist/frameworks/react.d.ts.map +1 -0
- package/dist/frameworks/react.js +230 -0
- package/dist/frameworks/react.js.map +7 -0
- package/dist/frameworks/ruby.d.ts +8 -0
- package/dist/frameworks/ruby.d.ts.map +1 -0
- package/dist/frameworks/ruby.js +136 -0
- package/dist/frameworks/ruby.js.map +7 -0
- package/dist/frameworks/rust.d.ts +8 -0
- package/dist/frameworks/rust.d.ts.map +1 -0
- package/dist/frameworks/rust.js +82 -0
- package/dist/frameworks/rust.js.map +7 -0
- package/dist/frameworks/svelte.d.ts +8 -0
- package/dist/frameworks/svelte.d.ts.map +1 -0
- package/dist/frameworks/svelte.js +174 -0
- package/dist/frameworks/svelte.js.map +7 -0
- package/dist/frameworks/swift.d.ts +10 -0
- package/dist/frameworks/swift.d.ts.map +1 -0
- package/dist/frameworks/swift.js +151 -0
- package/dist/frameworks/swift.js.map +7 -0
- package/dist/frameworks/types.d.ts +37 -0
- package/dist/frameworks/types.d.ts.map +1 -0
- package/dist/frameworks/types.js +17 -0
- package/dist/frameworks/types.js.map +7 -0
- package/dist/graph/queries.d.ts +53 -0
- package/dist/graph/queries.d.ts.map +1 -0
- package/dist/graph/queries.js +224 -0
- package/dist/graph/queries.js.map +7 -0
- package/dist/graph/traversal.d.ts +35 -0
- package/dist/graph/traversal.d.ts.map +1 -0
- package/dist/graph/traversal.js +148 -0
- package/dist/graph/traversal.js.map +7 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +303 -0
- package/dist/index.js.map +7 -0
- package/dist/installer/index.d.ts +10 -0
- package/dist/installer/index.d.ts.map +1 -0
- package/dist/installer/index.js +526 -0
- package/dist/installer/index.js.map +1 -0
- package/dist/mcp/server.d.ts +16 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +116 -0
- package/dist/mcp/server.js.map +7 -0
- package/dist/mcp/tools.d.ts +37 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +779 -0
- package/dist/mcp/tools.js.map +7 -0
- package/dist/mcp/transport.d.ts +29 -0
- package/dist/mcp/transport.d.ts.map +1 -0
- package/dist/mcp/transport.js +70 -0
- package/dist/mcp/transport.js.map +7 -0
- package/dist/resolution/index.d.ts +56 -0
- package/dist/resolution/index.d.ts.map +1 -0
- package/dist/resolution/index.js +384 -0
- package/dist/resolution/index.js.map +7 -0
- package/dist/resolution/name-matcher.d.ts +25 -0
- package/dist/resolution/name-matcher.d.ts.map +1 -0
- package/dist/resolution/name-matcher.js +60 -0
- package/dist/resolution/name-matcher.js.map +7 -0
- package/dist/scripts/postinstall.js +64 -0
- package/dist/search/query-utils.d.ts +21 -0
- package/dist/search/query-utils.d.ts.map +1 -0
- package/dist/search/query-utils.js +219 -0
- package/dist/search/query-utils.js.map +7 -0
- package/dist/search/searcher.d.ts +15 -0
- package/dist/search/searcher.d.ts.map +1 -0
- package/dist/search/searcher.js +49 -0
- package/dist/search/searcher.js.map +7 -0
- package/dist/sync/index.d.ts +33 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +200 -0
- package/dist/sync/index.js.map +7 -0
- package/dist/types.d.ts +131 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +37 -0
- package/dist/types.js.map +7 -0
- package/dist/utils.d.ts +52 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +254 -0
- package/dist/utils.js.map +7 -0
- package/dist/vectors/index.d.ts +71 -0
- package/dist/vectors/index.d.ts.map +1 -0
- package/dist/vectors/index.js +480 -0
- package/dist/vectors/index.js.map +7 -0
- package/dist/vectors/lancedb-index.d.ts +50 -0
- package/dist/vectors/lancedb-index.d.ts.map +1 -0
- package/dist/vectors/lancedb-index.js +153 -0
- package/dist/vectors/lancedb-index.js.map +7 -0
- package/dist/vectors/orama-index.d.ts +54 -0
- package/dist/vectors/orama-index.d.ts.map +1 -0
- package/dist/vectors/orama-index.js +213 -0
- package/dist/vectors/orama-index.js.map +7 -0
- package/dist/vectors/pglite-index.d.ts +53 -0
- package/dist/vectors/pglite-index.d.ts.map +1 -0
- package/dist/vectors/pglite-index.js +194 -0
- package/dist/vectors/pglite-index.js.map +7 -0
- package/dist/vectors/qdrant-index.d.ts +70 -0
- package/dist/vectors/qdrant-index.d.ts.map +1 -0
- package/dist/vectors/qdrant-index.js +364 -0
- package/dist/vectors/qdrant-index.js.map +7 -0
- package/dist/vectors/typesense-index.d.ts +75 -0
- package/dist/vectors/typesense-index.d.ts.map +1 -0
- package/dist/vectors/typesense-index.js +453 -0
- package/dist/vectors/typesense-index.js.map +7 -0
- package/dist/vectors/vec-index.d.ts +52 -0
- package/dist/vectors/vec-index.d.ts.map +1 -0
- package/dist/vectors/vec-index.js +198 -0
- package/dist/vectors/vec-index.js.map +7 -0
- package/package.json +67 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var pglite_index_exports = {};
|
|
30
|
+
__export(pglite_index_exports, {
|
|
31
|
+
PGliteIndex: () => PGliteIndex
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(pglite_index_exports);
|
|
34
|
+
var path = __toESM(require("path"));
|
|
35
|
+
var import_errors = require("../errors");
|
|
36
|
+
const DEFAULT_DIM = 768;
|
|
37
|
+
const DB_DIR = "pglite";
|
|
38
|
+
const VECTOR_WEIGHT = 0.7;
|
|
39
|
+
const FTS_WEIGHT = 0.3;
|
|
40
|
+
class PGliteIndex {
|
|
41
|
+
constructor(kirographDir, dim = DEFAULT_DIM) {
|
|
42
|
+
this.kirographDir = kirographDir;
|
|
43
|
+
this.dim = dim;
|
|
44
|
+
this.db = null;
|
|
45
|
+
this._available = false;
|
|
46
|
+
this.dbPath = path.join(kirographDir, DB_DIR);
|
|
47
|
+
}
|
|
48
|
+
isAvailable() {
|
|
49
|
+
return this._available;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Load @electric-sql/pglite, open the file-persisted database, enable pgvector,
|
|
53
|
+
* and apply the schema (idempotent — safe to call on every startup).
|
|
54
|
+
* Silent no-op when the optional dep is missing.
|
|
55
|
+
*/
|
|
56
|
+
async initialize() {
|
|
57
|
+
if (this._available) return;
|
|
58
|
+
let PGlite;
|
|
59
|
+
let vector;
|
|
60
|
+
try {
|
|
61
|
+
const mod = require("@electric-sql/pglite");
|
|
62
|
+
PGlite = mod.PGlite;
|
|
63
|
+
} catch {
|
|
64
|
+
(0, import_errors.logDebug)("PGliteIndex: @electric-sql/pglite not installed \u2014 PGlite engine unavailable");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const vectorMod = require("@electric-sql/pglite/vector");
|
|
69
|
+
vector = vectorMod.vector ?? vectorMod;
|
|
70
|
+
} catch {
|
|
71
|
+
(0, import_errors.logDebug)("PGliteIndex: @electric-sql/pglite/vector not available \u2014 PGlite engine unavailable");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
this.db = new PGlite(`file://${this.dbPath}`, { extensions: { vector } });
|
|
76
|
+
await this.db.waitReady;
|
|
77
|
+
await this.db.exec(`
|
|
78
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
79
|
+
|
|
80
|
+
CREATE TABLE IF NOT EXISTS kg_nodes (
|
|
81
|
+
node_id TEXT PRIMARY KEY,
|
|
82
|
+
name TEXT NOT NULL DEFAULT '',
|
|
83
|
+
kind TEXT NOT NULL DEFAULT '',
|
|
84
|
+
file_path TEXT NOT NULL DEFAULT '',
|
|
85
|
+
signature TEXT NOT NULL DEFAULT '',
|
|
86
|
+
embedding vector(${this.dim}) NOT NULL
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE INDEX IF NOT EXISTS kg_nodes_hnsw_idx
|
|
90
|
+
ON kg_nodes USING hnsw (embedding vector_cosine_ops);
|
|
91
|
+
|
|
92
|
+
CREATE INDEX IF NOT EXISTS kg_nodes_name_idx
|
|
93
|
+
ON kg_nodes USING GIN (to_tsvector('english', name || ' ' || signature));
|
|
94
|
+
`);
|
|
95
|
+
this._available = true;
|
|
96
|
+
(0, import_errors.logDebug)("PGliteIndex: ready", { path: this.dbPath, dim: this.dim });
|
|
97
|
+
} catch (err) {
|
|
98
|
+
(0, import_errors.logError)("PGliteIndex: initialization failed", { error: String(err) });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Insert or update a node's record using PostgreSQL's native ON CONFLICT upsert.
|
|
103
|
+
*/
|
|
104
|
+
async upsert(node, embedding) {
|
|
105
|
+
if (!this._available || !this.db) return;
|
|
106
|
+
try {
|
|
107
|
+
await this.db.query(
|
|
108
|
+
`INSERT INTO kg_nodes (node_id, name, kind, file_path, signature, embedding)
|
|
109
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
110
|
+
ON CONFLICT (node_id) DO UPDATE SET
|
|
111
|
+
name = EXCLUDED.name,
|
|
112
|
+
kind = EXCLUDED.kind,
|
|
113
|
+
file_path = EXCLUDED.file_path,
|
|
114
|
+
signature = EXCLUDED.signature,
|
|
115
|
+
embedding = EXCLUDED.embedding`,
|
|
116
|
+
[
|
|
117
|
+
node.id,
|
|
118
|
+
node.name,
|
|
119
|
+
node.kind,
|
|
120
|
+
node.filePath,
|
|
121
|
+
node.signature ?? "",
|
|
122
|
+
`[${Array.from(embedding).join(",")}]`
|
|
123
|
+
]
|
|
124
|
+
);
|
|
125
|
+
} catch (err) {
|
|
126
|
+
(0, import_errors.logWarn)("PGliteIndex: upsert failed", { nodeId: node.id, error: String(err) });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Remove a node's record from the index.
|
|
131
|
+
*/
|
|
132
|
+
async delete(nodeId) {
|
|
133
|
+
if (!this._available || !this.db) return;
|
|
134
|
+
try {
|
|
135
|
+
await this.db.query("DELETE FROM kg_nodes WHERE node_id = $1", [nodeId]);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
(0, import_errors.logWarn)("PGliteIndex: delete failed", { nodeId, error: String(err) });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Hybrid search: combines pgvector cosine distance with PostgreSQL full-text
|
|
142
|
+
* ranking in a single SQL query. Returns node IDs ordered by combined score.
|
|
143
|
+
*
|
|
144
|
+
* Score = VECTOR_WEIGHT × (1 - cosine_distance) + FTS_WEIGHT × ts_rank
|
|
145
|
+
*/
|
|
146
|
+
async search(queryText, queryVec, topN = 10) {
|
|
147
|
+
if (!this._available || !this.db) return [];
|
|
148
|
+
try {
|
|
149
|
+
const vecLiteral = `[${Array.from(queryVec).join(",")}]`;
|
|
150
|
+
const result = await this.db.query(
|
|
151
|
+
`SELECT node_id,
|
|
152
|
+
(${VECTOR_WEIGHT} * (1 - (embedding <=> $1::vector))
|
|
153
|
+
+ ${FTS_WEIGHT} * ts_rank(
|
|
154
|
+
to_tsvector('english', name || ' ' || signature),
|
|
155
|
+
plainto_tsquery('english', $2)
|
|
156
|
+
)
|
|
157
|
+
) AS score
|
|
158
|
+
FROM kg_nodes
|
|
159
|
+
ORDER BY score DESC
|
|
160
|
+
LIMIT $3`,
|
|
161
|
+
[vecLiteral, queryText, topN]
|
|
162
|
+
);
|
|
163
|
+
return (result.rows ?? []).map((row) => row.node_id);
|
|
164
|
+
} catch (err) {
|
|
165
|
+
(0, import_errors.logWarn)("PGliteIndex: search failed", { error: String(err) });
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/** Return all node IDs currently stored in the index. */
|
|
170
|
+
async getEmbeddedNodeIds() {
|
|
171
|
+
if (!this._available || !this.db) return [];
|
|
172
|
+
try {
|
|
173
|
+
const result = await this.db.query("SELECT node_id FROM kg_nodes");
|
|
174
|
+
return (result.rows ?? []).map((row) => row.node_id);
|
|
175
|
+
} catch {
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/** Number of documents currently in the index. */
|
|
180
|
+
async count() {
|
|
181
|
+
if (!this._available || !this.db) return 0;
|
|
182
|
+
try {
|
|
183
|
+
const result = await this.db.query("SELECT COUNT(*) AS count FROM kg_nodes");
|
|
184
|
+
return parseInt(result.rows[0]?.count ?? "0", 10);
|
|
185
|
+
} catch {
|
|
186
|
+
return 0;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
191
|
+
0 && (module.exports = {
|
|
192
|
+
PGliteIndex
|
|
193
|
+
});
|
|
194
|
+
//# sourceMappingURL=pglite-index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/vectors/pglite-index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph PGLite Index\n *\n * Hybrid search (full-text + exact vector) backed by @electric-sql/pglite + pgvector.\n * The database is persisted to .kirograph/pglite/ (PGLite's WAL-based file storage).\n *\n * Opt-in: set config.semanticEngine = 'pglite'\n * Required optional dependency (not installed by default):\n * npm install @electric-sql/pglite\n *\n * Key advantages over other engines:\n * - Pure WASM, no native compilation required (unlike sqlite-vec)\n * - Exact nearest-neighbour search (deterministic, unlike ANN approximation)\n * - Native SQL upsert via ON CONFLICT \u2014 no remove+insert dance (unlike Orama)\n * - HNSW index for fast approximate search when the table grows large\n * - Full-text search via PostgreSQL tsvector + ts_rank combined in one query\n */\n\nimport * as path from 'path';\nimport { logDebug, logWarn, logError } from '../errors';\nimport type { Node } from '../types';\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst DEFAULT_DIM = 768;\nconst DB_DIR = 'pglite';\n\n// Weight for vector score vs full-text score in hybrid ranking (must sum to 1.0)\nconst VECTOR_WEIGHT = 0.7;\nconst FTS_WEIGHT = 0.3;\n\n// \u2500\u2500 PGliteIndex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class PGliteIndex {\n private db: any = null;\n private _available = false;\n private dbPath: string;\n\n constructor(\n private readonly kirographDir: string,\n private readonly dim = DEFAULT_DIM,\n ) {\n this.dbPath = path.join(kirographDir, DB_DIR);\n }\n\n isAvailable(): boolean {\n return this._available;\n }\n\n /**\n * Load @electric-sql/pglite, open the file-persisted database, enable pgvector,\n * and apply the schema (idempotent \u2014 safe to call on every startup).\n * Silent no-op when the optional dep is missing.\n */\n async initialize(): Promise<void> {\n if (this._available) return;\n\n let PGlite: any;\n let vector: any;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const mod = require('@electric-sql/pglite');\n PGlite = mod.PGlite;\n } catch {\n logDebug('PGliteIndex: @electric-sql/pglite not installed \u2014 PGlite engine unavailable');\n return;\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const vectorMod = require('@electric-sql/pglite/vector');\n vector = vectorMod.vector ?? vectorMod;\n } catch {\n logDebug('PGliteIndex: @electric-sql/pglite/vector not available \u2014 PGlite engine unavailable');\n return;\n }\n\n try {\n this.db = new PGlite(`file://${this.dbPath}`, { extensions: { vector } });\n await this.db.waitReady;\n\n await this.db.exec(`\n CREATE EXTENSION IF NOT EXISTS vector;\n\n CREATE TABLE IF NOT EXISTS kg_nodes (\n node_id TEXT PRIMARY KEY,\n name TEXT NOT NULL DEFAULT '',\n kind TEXT NOT NULL DEFAULT '',\n file_path TEXT NOT NULL DEFAULT '',\n signature TEXT NOT NULL DEFAULT '',\n embedding vector(${this.dim}) NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS kg_nodes_hnsw_idx\n ON kg_nodes USING hnsw (embedding vector_cosine_ops);\n\n CREATE INDEX IF NOT EXISTS kg_nodes_name_idx\n ON kg_nodes USING GIN (to_tsvector('english', name || ' ' || signature));\n `);\n\n this._available = true;\n logDebug('PGliteIndex: ready', { path: this.dbPath, dim: this.dim });\n } catch (err) {\n logError('PGliteIndex: initialization failed', { error: String(err) });\n }\n }\n\n /**\n * Insert or update a node's record using PostgreSQL's native ON CONFLICT upsert.\n */\n async upsert(node: Node, embedding: Float32Array): Promise<void> {\n if (!this._available || !this.db) return;\n\n try {\n await this.db.query(\n `INSERT INTO kg_nodes (node_id, name, kind, file_path, signature, embedding)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT (node_id) DO UPDATE SET\n name = EXCLUDED.name,\n kind = EXCLUDED.kind,\n file_path = EXCLUDED.file_path,\n signature = EXCLUDED.signature,\n embedding = EXCLUDED.embedding`,\n [\n node.id,\n node.name,\n node.kind,\n node.filePath,\n node.signature ?? '',\n `[${Array.from(embedding).join(',')}]`,\n ],\n );\n } catch (err) {\n logWarn('PGliteIndex: upsert failed', { nodeId: node.id, error: String(err) });\n }\n }\n\n /**\n * Remove a node's record from the index.\n */\n async delete(nodeId: string): Promise<void> {\n if (!this._available || !this.db) return;\n\n try {\n await this.db.query('DELETE FROM kg_nodes WHERE node_id = $1', [nodeId]);\n } catch (err) {\n logWarn('PGliteIndex: delete failed', { nodeId, error: String(err) });\n }\n }\n\n /**\n * Hybrid search: combines pgvector cosine distance with PostgreSQL full-text\n * ranking in a single SQL query. Returns node IDs ordered by combined score.\n *\n * Score = VECTOR_WEIGHT \u00D7 (1 - cosine_distance) + FTS_WEIGHT \u00D7 ts_rank\n */\n async search(queryText: string, queryVec: Float32Array, topN = 10): Promise<string[]> {\n if (!this._available || !this.db) return [];\n\n try {\n const vecLiteral = `[${Array.from(queryVec).join(',')}]`;\n const result = await this.db.query(\n `SELECT node_id,\n (${VECTOR_WEIGHT} * (1 - (embedding <=> $1::vector))\n + ${FTS_WEIGHT} * ts_rank(\n to_tsvector('english', name || ' ' || signature),\n plainto_tsquery('english', $2)\n )\n ) AS score\n FROM kg_nodes\n ORDER BY score DESC\n LIMIT $3`,\n [vecLiteral, queryText, topN],\n );\n\n return (result.rows ?? []).map((row: any) => row.node_id as string);\n } catch (err) {\n logWarn('PGliteIndex: search failed', { error: String(err) });\n return [];\n }\n }\n\n /** Return all node IDs currently stored in the index. */\n async getEmbeddedNodeIds(): Promise<string[]> {\n if (!this._available || !this.db) return [];\n try {\n const result = await this.db.query('SELECT node_id FROM kg_nodes');\n return (result.rows ?? []).map((row: any) => row.node_id as string);\n } catch {\n return [];\n }\n }\n\n /** Number of documents currently in the index. */\n async count(): Promise<number> {\n if (!this._available || !this.db) return 0;\n try {\n const result = await this.db.query('SELECT COUNT(*) AS count FROM kg_nodes');\n return parseInt(result.rows[0]?.count ?? '0', 10);\n } catch {\n return 0;\n }\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBA,WAAsB;AACtB,oBAA4C;AAK5C,MAAM,cAAc;AACpB,MAAM,SAAc;AAGpB,MAAM,gBAAgB;AACtB,MAAM,aAAgB;AAIf,MAAM,YAAY;AAAA,EAKvB,YACmB,cACA,MAAM,aACvB;AAFiB;AACA;AANnB,SAAQ,KAAU;AAClB,SAAQ,aAAa;AAOnB,SAAK,SAAS,KAAK,KAAK,cAAc,MAAM;AAAA,EAC9C;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAA4B;AAChC,QAAI,KAAK,WAAY;AAErB,QAAI;AACJ,QAAI;AACJ,QAAI;AAEF,YAAM,MAAM,QAAQ,sBAAsB;AAC1C,eAAS,IAAI;AAAA,IACf,QAAQ;AACN,kCAAS,kFAA6E;AACtF;AAAA,IACF;AAEA,QAAI;AAEF,YAAM,YAAY,QAAQ,6BAA6B;AACvD,eAAS,UAAU,UAAU;AAAA,IAC/B,QAAQ;AACN,kCAAS,yFAAoF;AAC7F;AAAA,IACF;AAEA,QAAI;AACF,WAAK,KAAK,IAAI,OAAO,UAAU,KAAK,MAAM,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;AACxE,YAAM,KAAK,GAAG;AAEd,YAAM,KAAK,GAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BASI,KAAK,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAQ9B;AAED,WAAK,aAAa;AAClB,kCAAS,sBAAsB,EAAE,MAAM,KAAK,QAAQ,KAAK,KAAK,IAAI,CAAC;AAAA,IACrE,SAAS,KAAK;AACZ,kCAAS,sCAAsC,EAAE,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,MAAY,WAAwC;AAC/D,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,GAAI;AAElC,QAAI;AACF,YAAM,KAAK,GAAG;AAAA,QACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA;AAAA,UACE,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK,aAAa;AAAA,UAClB,IAAI,MAAM,KAAK,SAAS,EAAE,KAAK,GAAG,CAAC;AAAA,QACrC;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,iCAAQ,8BAA8B,EAAE,QAAQ,KAAK,IAAI,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,IAC/E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,QAA+B;AAC1C,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,GAAI;AAElC,QAAI;AACF,YAAM,KAAK,GAAG,MAAM,2CAA2C,CAAC,MAAM,CAAC;AAAA,IACzE,SAAS,KAAK;AACZ,iCAAQ,8BAA8B,EAAE,QAAQ,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,IACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,WAAmB,UAAwB,OAAO,IAAuB;AACpF,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,GAAI,QAAO,CAAC;AAE1C,QAAI;AACF,YAAM,aAAa,IAAI,MAAM,KAAK,QAAQ,EAAE,KAAK,GAAG,CAAC;AACrD,YAAM,SAAS,MAAM,KAAK,GAAG;AAAA,QAC3B;AAAA,mBACW,aAAa;AAAA,qBACX,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQvB,CAAC,YAAY,WAAW,IAAI;AAAA,MAC9B;AAEA,cAAQ,OAAO,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAa,IAAI,OAAiB;AAAA,IACpE,SAAS,KAAK;AACZ,iCAAQ,8BAA8B,EAAE,OAAO,OAAO,GAAG,EAAE,CAAC;AAC5D,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,qBAAwC;AAC5C,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,GAAI,QAAO,CAAC;AAC1C,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,GAAG,MAAM,8BAA8B;AACjE,cAAQ,OAAO,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAa,IAAI,OAAiB;AAAA,IACpE,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,QAAyB;AAC7B,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,GAAI,QAAO;AACzC,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,GAAG,MAAM,wCAAwC;AAC3E,aAAO,SAAS,OAAO,KAAK,CAAC,GAAG,SAAS,KAAK,EAAE;AAAA,IAClD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KiroGraph Qdrant Index
|
|
3
|
+
*
|
|
4
|
+
* ANN vector search backed by Qdrant running in embedded mode.
|
|
5
|
+
* The engine spawns the Qdrant binary as a managed child process, persisting
|
|
6
|
+
* data to .kirograph/qdrant/ via QDRANT__STORAGE__STORAGE_PATH.
|
|
7
|
+
*
|
|
8
|
+
* Opt-in: set config.semanticEngine = 'qdrant'
|
|
9
|
+
* Required optional dependency (not installed by default):
|
|
10
|
+
* npm install qdrant-local
|
|
11
|
+
*
|
|
12
|
+
* Uses @qdrant/qdrant-js (QdrantClient) for the REST API — available as a
|
|
13
|
+
* transitive dependency of qdrant-local.
|
|
14
|
+
*
|
|
15
|
+
* Key characteristics:
|
|
16
|
+
* - Full Qdrant feature set: filtering, payload indexing, HNSW ANN search
|
|
17
|
+
* - Data persisted to disk across restarts
|
|
18
|
+
* - Async startup check via /readyz (no blocking sleep)
|
|
19
|
+
* - Cosine distance metric
|
|
20
|
+
* - Node IDs stored in payload; deterministic UUIDs used as Qdrant point IDs
|
|
21
|
+
*/
|
|
22
|
+
import type { Node } from '../types';
|
|
23
|
+
export declare const DASHBOARD_SUBDIR = "qdrant/dashboard";
|
|
24
|
+
export declare class QdrantIndex {
|
|
25
|
+
private readonly kirographDir;
|
|
26
|
+
private readonly dim;
|
|
27
|
+
private client;
|
|
28
|
+
private child;
|
|
29
|
+
private _available;
|
|
30
|
+
private _ownedProcess;
|
|
31
|
+
private storagePath;
|
|
32
|
+
private stateFile;
|
|
33
|
+
constructor(kirographDir: string, dim?: number);
|
|
34
|
+
isAvailable(): boolean;
|
|
35
|
+
private readState;
|
|
36
|
+
private writeState;
|
|
37
|
+
private clearState;
|
|
38
|
+
private isProcessAlive;
|
|
39
|
+
/** The HTTP port of the running server, or null if not available. */
|
|
40
|
+
getPort(): number | null;
|
|
41
|
+
/**
|
|
42
|
+
* Locate the Qdrant binary (via qdrant-local), spawn it with a project-scoped
|
|
43
|
+
* storage path, wait until /readyz responds, then ensure the collection exists.
|
|
44
|
+
* Silent no-op when qdrant-local is not installed.
|
|
45
|
+
*/
|
|
46
|
+
initialize(): Promise<void>;
|
|
47
|
+
private ensureCollection;
|
|
48
|
+
/**
|
|
49
|
+
* Upsert a node's embedding. Qdrant's upsert is idempotent — the same point
|
|
50
|
+
* ID is overwritten if it already exists.
|
|
51
|
+
*/
|
|
52
|
+
upsert(node: Node, embedding: Float32Array): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Remove a point from the collection.
|
|
55
|
+
*/
|
|
56
|
+
delete(nodeId: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* ANN vector search. Returns node IDs ordered by cosine similarity (descending).
|
|
59
|
+
*/
|
|
60
|
+
search(queryVec: Float32Array, topN?: number): Promise<string[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Return all node IDs currently stored in the collection (paginated scroll).
|
|
63
|
+
*/
|
|
64
|
+
getEmbeddedNodeIds(): Promise<string[]>;
|
|
65
|
+
/** Disconnect the client. The Qdrant server keeps running as a daemon. */
|
|
66
|
+
close(): void;
|
|
67
|
+
/** Number of points currently in the collection. */
|
|
68
|
+
count(): Promise<number>;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=qdrant-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qdrant-index.d.ts","sourceRoot":"","sources":["../../src/vectors/qdrant-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAUrC,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAgDnD,qBAAa,WAAW;IASpB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,GAAG;IATtB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,SAAS,CAAgB;gBAGd,YAAY,EAAE,MAAM,EACpB,GAAG,SAAc;IAMpC,WAAW,IAAI,OAAO;IAEtB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,UAAU;IAGlB,OAAO,CAAC,UAAU;IAGlB,OAAO,CAAC,cAAc;IAItB,qEAAqE;IACrE,OAAO,IAAI,MAAM,GAAG,IAAI;IAUxB;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAiGnB,gBAAgB;IAU9B;;;OAGG;IACG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBhE;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU3C;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,SAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBlE;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA2B7C,0EAA0E;IAC1E,KAAK,IAAI,IAAI;IAMb,oDAAoD;IAC9C,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;CAS/B"}
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var qdrant_index_exports = {};
|
|
30
|
+
__export(qdrant_index_exports, {
|
|
31
|
+
DASHBOARD_SUBDIR: () => DASHBOARD_SUBDIR,
|
|
32
|
+
QdrantIndex: () => QdrantIndex
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(qdrant_index_exports);
|
|
35
|
+
var path = __toESM(require("path"));
|
|
36
|
+
var crypto = __toESM(require("crypto"));
|
|
37
|
+
var http = __toESM(require("http"));
|
|
38
|
+
var fs = __toESM(require("fs"));
|
|
39
|
+
var import_errors = require("../errors");
|
|
40
|
+
const DEFAULT_DIM = 768;
|
|
41
|
+
const STORAGE_DIR = "qdrant";
|
|
42
|
+
const COLLECTION = "kg_nodes";
|
|
43
|
+
const READYZ_TIMEOUT_MS = 1e4;
|
|
44
|
+
const READYZ_POLL_MS = 100;
|
|
45
|
+
const SERVER_STATE_FILE = "qdrant-server.json";
|
|
46
|
+
const DASHBOARD_SUBDIR = "qdrant/dashboard";
|
|
47
|
+
function toUuid(nodeId) {
|
|
48
|
+
const h = crypto.createHash("md5").update(nodeId).digest("hex");
|
|
49
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`;
|
|
50
|
+
}
|
|
51
|
+
function getFreePort() {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const srv = http.createServer().listen(0, "127.0.0.1", () => {
|
|
54
|
+
const port = srv.address().port;
|
|
55
|
+
srv.close(() => resolve(port));
|
|
56
|
+
});
|
|
57
|
+
srv.on("error", reject);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function waitReady(port, timeoutMs) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const deadline = Date.now() + timeoutMs;
|
|
63
|
+
function check() {
|
|
64
|
+
const req = http.get(`http://127.0.0.1:${port}/readyz`, (res) => {
|
|
65
|
+
if (res.statusCode === 200) return resolve();
|
|
66
|
+
scheduleRetry();
|
|
67
|
+
});
|
|
68
|
+
req.on("error", scheduleRetry);
|
|
69
|
+
req.setTimeout(200, () => {
|
|
70
|
+
req.destroy();
|
|
71
|
+
scheduleRetry();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function scheduleRetry() {
|
|
75
|
+
if (Date.now() >= deadline) return reject(new Error("Qdrant readyz timeout"));
|
|
76
|
+
setTimeout(check, READYZ_POLL_MS);
|
|
77
|
+
}
|
|
78
|
+
check();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
class QdrantIndex {
|
|
82
|
+
constructor(kirographDir, dim = DEFAULT_DIM) {
|
|
83
|
+
this.kirographDir = kirographDir;
|
|
84
|
+
this.dim = dim;
|
|
85
|
+
this.client = null;
|
|
86
|
+
this.child = null;
|
|
87
|
+
this._available = false;
|
|
88
|
+
this._ownedProcess = false;
|
|
89
|
+
this.storagePath = path.join(kirographDir, STORAGE_DIR);
|
|
90
|
+
this.stateFile = path.join(kirographDir, SERVER_STATE_FILE);
|
|
91
|
+
}
|
|
92
|
+
isAvailable() {
|
|
93
|
+
return this._available;
|
|
94
|
+
}
|
|
95
|
+
readState() {
|
|
96
|
+
try {
|
|
97
|
+
return JSON.parse(fs.readFileSync(this.stateFile, "utf8"));
|
|
98
|
+
} catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
writeState(s) {
|
|
103
|
+
try {
|
|
104
|
+
fs.writeFileSync(this.stateFile, JSON.stringify(s));
|
|
105
|
+
} catch {
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
clearState() {
|
|
109
|
+
try {
|
|
110
|
+
fs.unlinkSync(this.stateFile);
|
|
111
|
+
} catch {
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
isProcessAlive(pid) {
|
|
115
|
+
try {
|
|
116
|
+
process.kill(pid, 0);
|
|
117
|
+
return true;
|
|
118
|
+
} catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** The HTTP port of the running server, or null if not available. */
|
|
123
|
+
getPort() {
|
|
124
|
+
if (this._available) {
|
|
125
|
+
const s2 = this.readState();
|
|
126
|
+
return s2?.port ?? null;
|
|
127
|
+
}
|
|
128
|
+
const s = this.readState();
|
|
129
|
+
if (s && this.isProcessAlive(s.pid)) return s.port;
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Locate the Qdrant binary (via qdrant-local), spawn it with a project-scoped
|
|
134
|
+
* storage path, wait until /readyz responds, then ensure the collection exists.
|
|
135
|
+
* Silent no-op when qdrant-local is not installed.
|
|
136
|
+
*/
|
|
137
|
+
async initialize() {
|
|
138
|
+
if (this._available) return;
|
|
139
|
+
let binPath;
|
|
140
|
+
try {
|
|
141
|
+
const pkgPath = require.resolve("qdrant-local/package.json");
|
|
142
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
143
|
+
const { directory, name } = pkg.qdrantBinary;
|
|
144
|
+
const exeName = ["win32", "cygwin"].includes(process.platform) ? `${name}.exe` : name;
|
|
145
|
+
binPath = path.join(path.dirname(pkgPath), directory, exeName);
|
|
146
|
+
if (!fs.existsSync(binPath)) {
|
|
147
|
+
(0, import_errors.logDebug)("QdrantIndex: qdrant binary not found \u2014 run: npm install qdrant-local");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
} catch {
|
|
151
|
+
(0, import_errors.logDebug)("QdrantIndex: qdrant-local not installed \u2014 Qdrant engine unavailable");
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
let QdrantClient;
|
|
155
|
+
try {
|
|
156
|
+
QdrantClient = require("@qdrant/qdrant-js").QdrantClient;
|
|
157
|
+
} catch {
|
|
158
|
+
(0, import_errors.logDebug)("QdrantIndex: @qdrant/qdrant-js not available \u2014 Qdrant engine unavailable");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const saved = this.readState();
|
|
162
|
+
if (saved) {
|
|
163
|
+
if (this.isProcessAlive(saved.pid)) {
|
|
164
|
+
try {
|
|
165
|
+
await waitReady(saved.port, 3e3);
|
|
166
|
+
this.client = new QdrantClient({ host: "127.0.0.1", port: saved.port, checkCompatibility: false });
|
|
167
|
+
await this.ensureCollection();
|
|
168
|
+
this._available = true;
|
|
169
|
+
this._ownedProcess = false;
|
|
170
|
+
(0, import_errors.logDebug)("QdrantIndex: reused running server", { pid: saved.pid, port: saved.port });
|
|
171
|
+
return;
|
|
172
|
+
} catch {
|
|
173
|
+
try {
|
|
174
|
+
process.kill(saved.pid, "SIGKILL");
|
|
175
|
+
} catch {
|
|
176
|
+
}
|
|
177
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
this.clearState();
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
fs.mkdirSync(this.storagePath, { recursive: true });
|
|
184
|
+
const port = await getFreePort();
|
|
185
|
+
const dashboardDir = path.join(this.kirographDir, DASHBOARD_SUBDIR);
|
|
186
|
+
const staticEnv = fs.existsSync(dashboardDir) ? { QDRANT__SERVICE__STATIC_CONTENT_DIR: dashboardDir } : {};
|
|
187
|
+
const { spawn } = require("child_process");
|
|
188
|
+
this.child = spawn(binPath, [], {
|
|
189
|
+
stdio: "ignore",
|
|
190
|
+
env: {
|
|
191
|
+
...process.env,
|
|
192
|
+
QDRANT__SERVICE__HTTP_PORT: String(port),
|
|
193
|
+
QDRANT__STORAGE__STORAGE_PATH: this.storagePath,
|
|
194
|
+
QDRANT__LOG_LEVEL: "WARN",
|
|
195
|
+
...staticEnv
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
this.child.unref();
|
|
199
|
+
await waitReady(port, READYZ_TIMEOUT_MS);
|
|
200
|
+
this.writeState({ pid: this.child.pid, port });
|
|
201
|
+
this.client = new QdrantClient({ host: "127.0.0.1", port, checkCompatibility: false });
|
|
202
|
+
await this.ensureCollection();
|
|
203
|
+
this._available = true;
|
|
204
|
+
this._ownedProcess = true;
|
|
205
|
+
(0, import_errors.logDebug)("QdrantIndex: ready", { storagePath: this.storagePath, port, dim: this.dim });
|
|
206
|
+
} catch (err) {
|
|
207
|
+
(0, import_errors.logError)("QdrantIndex: initialization failed", { error: String(err) });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async ensureCollection() {
|
|
211
|
+
const existsResult = await this.client.collectionExists(COLLECTION);
|
|
212
|
+
const exists = typeof existsResult === "object" ? existsResult.exists : existsResult;
|
|
213
|
+
if (!exists) {
|
|
214
|
+
await this.client.createCollection(COLLECTION, {
|
|
215
|
+
vectors: { size: this.dim, distance: "Cosine" }
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Upsert a node's embedding with retry logic.
|
|
221
|
+
* Qdrant's upsert is idempotent — the same point ID is overwritten if it already exists.
|
|
222
|
+
* Retries up to 3 times with exponential backoff to handle transient connection failures.
|
|
223
|
+
*/
|
|
224
|
+
async upsert(node, embedding) {
|
|
225
|
+
if (!this._available || !this.client) return;
|
|
226
|
+
const point = {
|
|
227
|
+
id: toUuid(node.id),
|
|
228
|
+
vector: Array.from(embedding),
|
|
229
|
+
payload: {
|
|
230
|
+
node_id: node.id,
|
|
231
|
+
name: node.name,
|
|
232
|
+
kind: node.kind,
|
|
233
|
+
file_path: node.filePath,
|
|
234
|
+
signature: node.signature ?? ""
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
238
|
+
try {
|
|
239
|
+
await this.client.upsert(COLLECTION, { points: [point] });
|
|
240
|
+
return;
|
|
241
|
+
} catch (err) {
|
|
242
|
+
if (attempt < 2) {
|
|
243
|
+
await new Promise((r) => setTimeout(r, 100 * (attempt + 1)));
|
|
244
|
+
} else {
|
|
245
|
+
(0, import_errors.logWarn)("QdrantIndex: upsert failed", { nodeId: node.id, error: String(err) });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Batch upsert multiple nodes' embeddings in a single HTTP request.
|
|
252
|
+
* Much more efficient than individual upserts for bulk indexing.
|
|
253
|
+
* Retries up to 3 times with exponential backoff.
|
|
254
|
+
*/
|
|
255
|
+
async bulkUpsert(nodes, embeddings) {
|
|
256
|
+
if (!this._available || !this.client) return;
|
|
257
|
+
if (nodes.length === 0) return;
|
|
258
|
+
const points = nodes.map((node, i) => ({
|
|
259
|
+
id: toUuid(node.id),
|
|
260
|
+
vector: Array.from(embeddings[i]),
|
|
261
|
+
payload: {
|
|
262
|
+
node_id: node.id,
|
|
263
|
+
name: node.name,
|
|
264
|
+
kind: node.kind,
|
|
265
|
+
file_path: node.filePath,
|
|
266
|
+
signature: node.signature ?? ""
|
|
267
|
+
}
|
|
268
|
+
}));
|
|
269
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
270
|
+
try {
|
|
271
|
+
await this.client.upsert(COLLECTION, { points });
|
|
272
|
+
return;
|
|
273
|
+
} catch (err) {
|
|
274
|
+
if (attempt < 2) {
|
|
275
|
+
await new Promise((r) => setTimeout(r, 200 * (attempt + 1)));
|
|
276
|
+
} else {
|
|
277
|
+
(0, import_errors.logWarn)("QdrantIndex: bulk upsert failed", { count: nodes.length, error: String(err) });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Remove a point from the collection with retry logic.
|
|
284
|
+
*/
|
|
285
|
+
async delete(nodeId) {
|
|
286
|
+
if (!this._available || !this.client) return;
|
|
287
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
288
|
+
try {
|
|
289
|
+
await this.client.delete(COLLECTION, { points: [toUuid(nodeId)] });
|
|
290
|
+
return;
|
|
291
|
+
} catch (err) {
|
|
292
|
+
if (attempt < 2) {
|
|
293
|
+
await new Promise((r) => setTimeout(r, 100 * (attempt + 1)));
|
|
294
|
+
} else {
|
|
295
|
+
(0, import_errors.logWarn)("QdrantIndex: delete failed", { nodeId, error: String(err) });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* ANN vector search. Returns node IDs ordered by cosine similarity (descending).
|
|
302
|
+
*/
|
|
303
|
+
async search(queryVec, topN = 10) {
|
|
304
|
+
if (!this._available || !this.client) return [];
|
|
305
|
+
try {
|
|
306
|
+
const results = await this.client.search(COLLECTION, {
|
|
307
|
+
vector: Array.from(queryVec),
|
|
308
|
+
limit: topN,
|
|
309
|
+
with_payload: ["node_id"]
|
|
310
|
+
});
|
|
311
|
+
return results.map((r) => r.payload.node_id);
|
|
312
|
+
} catch (err) {
|
|
313
|
+
(0, import_errors.logWarn)("QdrantIndex: search failed", { error: String(err) });
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Return all node IDs currently stored in the collection (paginated scroll).
|
|
319
|
+
*/
|
|
320
|
+
async getEmbeddedNodeIds() {
|
|
321
|
+
if (!this._available || !this.client) return [];
|
|
322
|
+
const ids = [];
|
|
323
|
+
let offset = null;
|
|
324
|
+
try {
|
|
325
|
+
do {
|
|
326
|
+
const page = await this.client.scroll(COLLECTION, {
|
|
327
|
+
with_payload: ["node_id"],
|
|
328
|
+
with_vector: false,
|
|
329
|
+
limit: 1e3,
|
|
330
|
+
...offset !== null ? { offset } : {}
|
|
331
|
+
});
|
|
332
|
+
for (const pt of page.points) {
|
|
333
|
+
if (pt.payload?.node_id) ids.push(pt.payload.node_id);
|
|
334
|
+
}
|
|
335
|
+
offset = page.next_page_offset ?? null;
|
|
336
|
+
} while (offset !== null);
|
|
337
|
+
} catch {
|
|
338
|
+
return ids;
|
|
339
|
+
}
|
|
340
|
+
return ids;
|
|
341
|
+
}
|
|
342
|
+
/** Disconnect the client. The Qdrant server keeps running as a daemon. */
|
|
343
|
+
close() {
|
|
344
|
+
this._available = false;
|
|
345
|
+
this.child = null;
|
|
346
|
+
this.client = null;
|
|
347
|
+
}
|
|
348
|
+
/** Number of points currently in the collection. */
|
|
349
|
+
async count() {
|
|
350
|
+
if (!this._available || !this.client) return 0;
|
|
351
|
+
try {
|
|
352
|
+
const result = await this.client.count(COLLECTION, { exact: true });
|
|
353
|
+
return result.count;
|
|
354
|
+
} catch {
|
|
355
|
+
return 0;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
360
|
+
0 && (module.exports = {
|
|
361
|
+
DASHBOARD_SUBDIR,
|
|
362
|
+
QdrantIndex
|
|
363
|
+
});
|
|
364
|
+
//# sourceMappingURL=qdrant-index.js.map
|