@nhtio/adk 1.20260604.0 → 1.20260607.0
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/CHANGELOG.md +261 -0
- package/adk-mcp.mjs +1 -1
- package/batteries/embeddings/openai/adapter.cjs +1 -1
- package/batteries/embeddings/openai/adapter.mjs +1 -1
- package/batteries/embeddings/webllm/adapter.cjs +1 -1
- package/batteries/embeddings/webllm/adapter.mjs +1 -1
- package/batteries/index.d.ts +1 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs +6 -6
- package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/adapter.mjs +6 -6
- package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/helpers.cjs +2 -2
- package/batteries/llm/openai_chat_completions/helpers.mjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.cjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/validation.mjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.cjs +6 -6
- package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.mjs +6 -6
- package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/validation.cjs +2 -2
- package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/validation.mjs +2 -2
- package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -1
- package/batteries/storage/flydrive.cjs +1 -1
- package/batteries/storage/flydrive.mjs +2 -2
- package/batteries/storage/in_memory.cjs +1 -1
- package/batteries/storage/in_memory.mjs +1 -1
- package/batteries/storage/opfs.cjs +1 -1
- package/batteries/storage/opfs.mjs +1 -1
- package/batteries/tools/color.cjs +2 -2
- package/batteries/tools/color.mjs +2 -2
- package/batteries/tools/comparison.cjs +3 -3
- package/batteries/tools/comparison.mjs +3 -3
- package/batteries/tools/data_structure.cjs +3 -3
- package/batteries/tools/data_structure.mjs +3 -3
- package/batteries/tools/datetime_extended.cjs +2 -2
- package/batteries/tools/datetime_extended.mjs +2 -2
- package/batteries/tools/datetime_math.cjs +2 -2
- package/batteries/tools/datetime_math.mjs +2 -2
- package/batteries/tools/encoding.cjs +3 -3
- package/batteries/tools/encoding.mjs +3 -3
- package/batteries/tools/formatting.cjs +3 -3
- package/batteries/tools/formatting.mjs +3 -3
- package/batteries/tools/geo_basics.cjs +2 -2
- package/batteries/tools/geo_basics.mjs +2 -2
- package/batteries/tools/math/index.d.ts +16 -5
- package/batteries/tools/math.cjs +340 -22
- package/batteries/tools/math.cjs.map +1 -1
- package/batteries/tools/math.mjs +338 -21
- package/batteries/tools/math.mjs.map +1 -1
- package/batteries/tools/memory.cjs +5 -5
- package/batteries/tools/memory.mjs +5 -5
- package/batteries/tools/parsing.cjs +4 -4
- package/batteries/tools/parsing.mjs +4 -4
- package/batteries/tools/retrievables.cjs +4 -4
- package/batteries/tools/retrievables.mjs +4 -4
- package/batteries/tools/standing_instructions.cjs +4 -4
- package/batteries/tools/standing_instructions.mjs +4 -4
- package/batteries/tools/statistics.cjs +4 -4
- package/batteries/tools/statistics.mjs +4 -4
- package/batteries/tools/string_processing.cjs +3 -3
- package/batteries/tools/string_processing.mjs +3 -3
- package/batteries/tools/structured_data.cjs +3 -3
- package/batteries/tools/structured_data.mjs +3 -3
- package/batteries/tools/text_analysis.cjs +3 -3
- package/batteries/tools/text_analysis.mjs +3 -3
- package/batteries/tools/text_comparison.cjs +2 -2
- package/batteries/tools/text_comparison.mjs +2 -2
- package/batteries/tools/time.cjs +2 -2
- package/batteries/tools/time.mjs +2 -2
- package/batteries/tools/unit_conversion.cjs +2 -2
- package/batteries/tools/unit_conversion.mjs +2 -2
- package/batteries/vector/arangodb/index.d.ts +38 -0
- package/batteries/vector/arangodb.cjs +257 -0
- package/batteries/vector/arangodb.cjs.map +1 -0
- package/batteries/vector/arangodb.mjs +255 -0
- package/batteries/vector/arangodb.mjs.map +1 -0
- package/batteries/vector/builder.cjs +297 -0
- package/batteries/vector/builder.cjs.map +1 -0
- package/batteries/vector/builder.d.ts +87 -0
- package/batteries/vector/builder.mjs +294 -0
- package/batteries/vector/builder.mjs.map +1 -0
- package/batteries/vector/chroma/index.d.ts +32 -0
- package/batteries/vector/chroma.cjs +305 -0
- package/batteries/vector/chroma.cjs.map +1 -0
- package/batteries/vector/chroma.mjs +302 -0
- package/batteries/vector/chroma.mjs.map +1 -0
- package/batteries/vector/clickhouse/index.d.ts +39 -0
- package/batteries/vector/clickhouse.cjs +246 -0
- package/batteries/vector/clickhouse.cjs.map +1 -0
- package/batteries/vector/clickhouse.mjs +244 -0
- package/batteries/vector/clickhouse.mjs.map +1 -0
- package/batteries/vector/cloudflare/index.d.ts +43 -0
- package/batteries/vector/cloudflare.cjs +397 -0
- package/batteries/vector/cloudflare.cjs.map +1 -0
- package/batteries/vector/cloudflare.mjs +395 -0
- package/batteries/vector/cloudflare.mjs.map +1 -0
- package/batteries/vector/conformance/index.d.ts +15 -0
- package/batteries/vector/conformance.cjs +209 -0
- package/batteries/vector/conformance.cjs.map +1 -0
- package/batteries/vector/conformance.mjs +205 -0
- package/batteries/vector/conformance.mjs.map +1 -0
- package/batteries/vector/contract.cjs +42 -0
- package/batteries/vector/contract.cjs.map +1 -0
- package/batteries/vector/contract.d.ts +39 -0
- package/batteries/vector/contract.mjs +40 -0
- package/batteries/vector/contract.mjs.map +1 -0
- package/batteries/vector/couchbase/index.d.ts +49 -0
- package/batteries/vector/couchbase.cjs +401 -0
- package/batteries/vector/couchbase.cjs.map +1 -0
- package/batteries/vector/couchbase.mjs +399 -0
- package/batteries/vector/couchbase.mjs.map +1 -0
- package/batteries/vector/duckdb/index.d.ts +33 -0
- package/batteries/vector/duckdb.cjs +218 -0
- package/batteries/vector/duckdb.cjs.map +1 -0
- package/batteries/vector/duckdb.mjs +216 -0
- package/batteries/vector/duckdb.mjs.map +1 -0
- package/batteries/vector/elasticsearch/index.d.ts +43 -0
- package/batteries/vector/elasticsearch.cjs +306 -0
- package/batteries/vector/elasticsearch.cjs.map +1 -0
- package/batteries/vector/elasticsearch.mjs +303 -0
- package/batteries/vector/elasticsearch.mjs.map +1 -0
- package/batteries/vector/exceptions.cjs +126 -0
- package/batteries/vector/exceptions.cjs.map +1 -0
- package/batteries/vector/exceptions.d.ts +142 -0
- package/batteries/vector/exceptions.mjs +107 -0
- package/batteries/vector/exceptions.mjs.map +1 -0
- package/batteries/vector/factory.cjs +28 -0
- package/batteries/vector/factory.cjs.map +1 -0
- package/batteries/vector/factory.d.ts +38 -0
- package/batteries/vector/factory.mjs +25 -0
- package/batteries/vector/factory.mjs.map +1 -0
- package/batteries/vector/filters.cjs +107 -0
- package/batteries/vector/filters.cjs.map +1 -0
- package/batteries/vector/filters.d.ts +34 -0
- package/batteries/vector/filters.mjs +99 -0
- package/batteries/vector/filters.mjs.map +1 -0
- package/batteries/vector/helpers.cjs +23 -0
- package/batteries/vector/helpers.cjs.map +1 -0
- package/batteries/vector/helpers.d.ts +12 -0
- package/batteries/vector/helpers.mjs +17 -0
- package/batteries/vector/helpers.mjs.map +1 -0
- package/batteries/vector/hnswlib/index.d.ts +35 -0
- package/batteries/vector/hnswlib.cjs +237 -0
- package/batteries/vector/hnswlib.cjs.map +1 -0
- package/batteries/vector/hnswlib.mjs +235 -0
- package/batteries/vector/hnswlib.mjs.map +1 -0
- package/batteries/vector/in_memory/index.d.ts +23 -0
- package/batteries/vector/in_memory.cjs +178 -0
- package/batteries/vector/in_memory.cjs.map +1 -0
- package/batteries/vector/in_memory.mjs +176 -0
- package/batteries/vector/in_memory.mjs.map +1 -0
- package/batteries/vector/index.d.ts +18 -0
- package/batteries/vector/lancedb/index.d.ts +34 -0
- package/batteries/vector/lancedb.cjs +224 -0
- package/batteries/vector/lancedb.cjs.map +1 -0
- package/batteries/vector/lancedb.mjs +222 -0
- package/batteries/vector/lancedb.mjs.map +1 -0
- package/batteries/vector/mariadb/index.d.ts +39 -0
- package/batteries/vector/mariadb.cjs +228 -0
- package/batteries/vector/mariadb.cjs.map +1 -0
- package/batteries/vector/mariadb.mjs +226 -0
- package/batteries/vector/mariadb.mjs.map +1 -0
- package/batteries/vector/meilisearch/index.d.ts +36 -0
- package/batteries/vector/meilisearch.cjs +242 -0
- package/batteries/vector/meilisearch.cjs.map +1 -0
- package/batteries/vector/meilisearch.mjs +240 -0
- package/batteries/vector/meilisearch.mjs.map +1 -0
- package/batteries/vector/migrate.cjs +54 -0
- package/batteries/vector/migrate.cjs.map +1 -0
- package/batteries/vector/migrate.d.ts +30 -0
- package/batteries/vector/migrate.mjs +52 -0
- package/batteries/vector/migrate.mjs.map +1 -0
- package/batteries/vector/milvus/index.d.ts +35 -0
- package/batteries/vector/milvus.cjs +357 -0
- package/batteries/vector/milvus.cjs.map +1 -0
- package/batteries/vector/milvus.mjs +354 -0
- package/batteries/vector/milvus.mjs.map +1 -0
- package/batteries/vector/mongodb/index.d.ts +46 -0
- package/batteries/vector/mongodb.cjs +270 -0
- package/batteries/vector/mongodb.cjs.map +1 -0
- package/batteries/vector/mongodb.mjs +268 -0
- package/batteries/vector/mongodb.mjs.map +1 -0
- package/batteries/vector/neo4j/index.d.ts +38 -0
- package/batteries/vector/neo4j.cjs +231 -0
- package/batteries/vector/neo4j.cjs.map +1 -0
- package/batteries/vector/neo4j.mjs +229 -0
- package/batteries/vector/neo4j.mjs.map +1 -0
- package/batteries/vector/opensearch/index.d.ts +46 -0
- package/batteries/vector/opensearch.cjs +316 -0
- package/batteries/vector/opensearch.cjs.map +1 -0
- package/batteries/vector/opensearch.mjs +313 -0
- package/batteries/vector/opensearch.mjs.map +1 -0
- package/batteries/vector/oracle23ai/index.d.ts +45 -0
- package/batteries/vector/oracle23ai.cjs +340 -0
- package/batteries/vector/oracle23ai.cjs.map +1 -0
- package/batteries/vector/oracle23ai.mjs +338 -0
- package/batteries/vector/oracle23ai.mjs.map +1 -0
- package/batteries/vector/orama/index.d.ts +23 -0
- package/batteries/vector/orama.cjs +272 -0
- package/batteries/vector/orama.cjs.map +1 -0
- package/batteries/vector/orama.mjs +270 -0
- package/batteries/vector/orama.mjs.map +1 -0
- package/batteries/vector/pgvector/index.d.ts +43 -0
- package/batteries/vector/pgvector.cjs +411 -0
- package/batteries/vector/pgvector.cjs.map +1 -0
- package/batteries/vector/pgvector.mjs +408 -0
- package/batteries/vector/pgvector.mjs.map +1 -0
- package/batteries/vector/pinecone/index.d.ts +38 -0
- package/batteries/vector/pinecone.cjs +415 -0
- package/batteries/vector/pinecone.cjs.map +1 -0
- package/batteries/vector/pinecone.mjs +412 -0
- package/batteries/vector/pinecone.mjs.map +1 -0
- package/batteries/vector/plan.cjs +2 -0
- package/batteries/vector/plan.d.ts +65 -0
- package/batteries/vector/plan.mjs +0 -0
- package/batteries/vector/qdrant/index.d.ts +34 -0
- package/batteries/vector/qdrant.cjs +286 -0
- package/batteries/vector/qdrant.cjs.map +1 -0
- package/batteries/vector/qdrant.mjs +284 -0
- package/batteries/vector/qdrant.mjs.map +1 -0
- package/batteries/vector/redis/index.d.ts +44 -0
- package/batteries/vector/redis.cjs +391 -0
- package/batteries/vector/redis.cjs.map +1 -0
- package/batteries/vector/redis.mjs +388 -0
- package/batteries/vector/redis.mjs.map +1 -0
- package/batteries/vector/retrievable.cjs +69 -0
- package/batteries/vector/retrievable.cjs.map +1 -0
- package/batteries/vector/retrievable.mjs +67 -0
- package/batteries/vector/retrievable.mjs.map +1 -0
- package/batteries/vector/retrievable_glue.d.ts +24 -0
- package/batteries/vector/s3vectors/index.d.ts +52 -0
- package/batteries/vector/s3vectors.cjs +438 -0
- package/batteries/vector/s3vectors.cjs.map +1 -0
- package/batteries/vector/s3vectors.mjs +436 -0
- package/batteries/vector/s3vectors.mjs.map +1 -0
- package/batteries/vector/schema.cjs +96 -0
- package/batteries/vector/schema.cjs.map +1 -0
- package/batteries/vector/schema.d.ts +40 -0
- package/batteries/vector/schema.mjs +93 -0
- package/batteries/vector/schema.mjs.map +1 -0
- package/batteries/vector/solr/index.d.ts +36 -0
- package/batteries/vector/solr.cjs +230 -0
- package/batteries/vector/solr.cjs.map +1 -0
- package/batteries/vector/solr.mjs +228 -0
- package/batteries/vector/solr.mjs.map +1 -0
- package/batteries/vector/sqlite_vec/index.d.ts +30 -0
- package/batteries/vector/sqlite_vec.cjs +318 -0
- package/batteries/vector/sqlite_vec.cjs.map +1 -0
- package/batteries/vector/sqlite_vec.mjs +316 -0
- package/batteries/vector/sqlite_vec.mjs.map +1 -0
- package/batteries/vector/surrealdb/index.d.ts +37 -0
- package/batteries/vector/surrealdb.cjs +230 -0
- package/batteries/vector/surrealdb.cjs.map +1 -0
- package/batteries/vector/surrealdb.mjs +228 -0
- package/batteries/vector/surrealdb.mjs.map +1 -0
- package/batteries/vector/types.cjs +2 -0
- package/batteries/vector/types.d.ts +100 -0
- package/batteries/vector/types.mjs +0 -0
- package/batteries/vector/typesense/index.d.ts +38 -0
- package/batteries/vector/typesense.cjs +272 -0
- package/batteries/vector/typesense.cjs.map +1 -0
- package/batteries/vector/typesense.mjs +270 -0
- package/batteries/vector/typesense.mjs.map +1 -0
- package/batteries/vector/validation.cjs +90 -0
- package/batteries/vector/validation.cjs.map +1 -0
- package/batteries/vector/validation.d.ts +18 -0
- package/batteries/vector/validation.mjs +83 -0
- package/batteries/vector/validation.mjs.map +1 -0
- package/batteries/vector/vector_store_constructor.cjs +56 -0
- package/batteries/vector/vector_store_constructor.cjs.map +1 -0
- package/batteries/vector/vector_store_constructor.d.ts +30 -0
- package/batteries/vector/vector_store_constructor.mjs +53 -0
- package/batteries/vector/vector_store_constructor.mjs.map +1 -0
- package/batteries/vector/vespa/index.d.ts +39 -0
- package/batteries/vector/vespa.cjs +423 -0
- package/batteries/vector/vespa.cjs.map +1 -0
- package/batteries/vector/vespa.mjs +421 -0
- package/batteries/vector/vespa.mjs.map +1 -0
- package/batteries/vector/weaviate/index.d.ts +57 -0
- package/batteries/vector/weaviate.cjs +325 -0
- package/batteries/vector/weaviate.cjs.map +1 -0
- package/batteries/vector/weaviate.mjs +322 -0
- package/batteries/vector/weaviate.mjs.map +1 -0
- package/batteries/vector.cjs +63 -0
- package/batteries/vector.mjs +14 -0
- package/batteries.cjs +62 -0
- package/batteries.mjs +15 -1
- package/{chunk-kRvK8_k2.mjs → chunk-Bpcn9VDT.mjs} +5 -1
- package/{common-lMrnzoyn.mjs → common-BT0nfCi9.mjs} +8 -8
- package/{common-lMrnzoyn.mjs.map → common-BT0nfCi9.mjs.map} +1 -1
- package/{common-D_e5zYsG.js → common-Cj8TaQ9U.js} +8 -8
- package/{common-D_e5zYsG.js.map → common-Cj8TaQ9U.js.map} +1 -1
- package/common.cjs +7 -7
- package/common.mjs +7 -7
- package/{dispatch_runner-CpuyATj1.js → dispatch_runner-BHBNupqp.js} +2 -2
- package/dispatch_runner-BHBNupqp.js.map +1 -0
- package/{dispatch_runner-CDF3X0nv.mjs → dispatch_runner-DPcS7Y_M.mjs} +2 -2
- package/dispatch_runner-DPcS7Y_M.mjs.map +1 -0
- package/dispatch_runner.cjs +1 -1
- package/dispatch_runner.mjs +1 -1
- package/forge.cjs +4 -4
- package/forge.mjs +4 -4
- package/guards.cjs +8 -8
- package/guards.mjs +8 -8
- package/index.cjs +12 -12
- package/index.mjs +12 -12
- package/lib/classes/tool_registry.d.ts +70 -4
- package/mcp/adk-docs-corpus.json +1 -1
- package/package.json +424 -88
- package/skills/adk-assembly/SKILL.md +2 -2
- package/{spooled_artifact-B8gIIn9h.js → spooled_artifact-BTq6Nzfy.js} +4 -4
- package/spooled_artifact-BTq6Nzfy.js.map +1 -0
- package/{spooled_artifact-CWoKUDEm.mjs → spooled_artifact-CHoZgWwI.mjs} +4 -4
- package/spooled_artifact-CHoZgWwI.mjs.map +1 -0
- package/spooled_artifact.cjs +2 -2
- package/spooled_artifact.mjs +2 -2
- package/{spooled_markdown_artifact-DQX0RCdI.js → spooled_markdown_artifact-CALSDxIx.js} +3 -3
- package/{spooled_markdown_artifact-DQX0RCdI.js.map → spooled_markdown_artifact-CALSDxIx.js.map} +1 -1
- package/{spooled_markdown_artifact-CNle4jXN.mjs → spooled_markdown_artifact-Ci5UL7l4.mjs} +3 -3
- package/{spooled_markdown_artifact-CNle4jXN.mjs.map → spooled_markdown_artifact-Ci5UL7l4.mjs.map} +1 -1
- package/src/types/evaluatex.d.ts +31 -0
- package/{thought-BD6AkkOr.js → thought-BbwhJ1wb.js} +4 -4
- package/thought-BbwhJ1wb.js.map +1 -0
- package/{thought-B_P8LiB6.mjs → thought-D34QQZZ9.mjs} +4 -4
- package/thought-D34QQZZ9.mjs.map +1 -0
- package/{tool-CRZSUcdP.mjs → tool-CMhaDRNd.mjs} +3 -3
- package/tool-CMhaDRNd.mjs.map +1 -0
- package/{tool-CX9vNHAw.js → tool-CVyZkFC7.js} +3 -3
- package/tool-CVyZkFC7.js.map +1 -0
- package/{tool_call-BUeMuCc6.mjs → tool_call-CV5qVNlb.mjs} +3 -3
- package/{tool_call-BUeMuCc6.mjs.map → tool_call-CV5qVNlb.mjs.map} +1 -1
- package/{tool_call--7ti-frB.js → tool_call-Db68hB7y.js} +3 -3
- package/{tool_call--7ti-frB.js.map → tool_call-Db68hB7y.js.map} +1 -1
- package/{tool_registry-BGHg6KTq.mjs → tool_registry-D1pSSlsd.mjs} +109 -22
- package/tool_registry-D1pSSlsd.mjs.map +1 -0
- package/{tool_registry-CtCQ4Xoz.js → tool_registry-DYUYqXvo.js} +109 -22
- package/tool_registry-DYUYqXvo.js.map +1 -0
- package/{turn_runner-BJTtAORU.js → turn_runner-DqWHNP80.js} +5 -5
- package/turn_runner-DqWHNP80.js.map +1 -0
- package/{turn_runner-C02LZHjt.mjs → turn_runner-fg1Wc3dK.mjs} +5 -5
- package/turn_runner-fg1Wc3dK.mjs.map +1 -0
- package/turn_runner.cjs +1 -1
- package/turn_runner.mjs +1 -1
- package/dispatch_runner-CDF3X0nv.mjs.map +0 -1
- package/dispatch_runner-CpuyATj1.js.map +0 -1
- package/spooled_artifact-B8gIIn9h.js.map +0 -1
- package/spooled_artifact-CWoKUDEm.mjs.map +0 -1
- package/thought-BD6AkkOr.js.map +0 -1
- package/thought-B_P8LiB6.mjs.map +0 -1
- package/tool-CRZSUcdP.mjs.map +0 -1
- package/tool-CX9vNHAw.js.map +0 -1
- package/tool_registry-BGHg6KTq.mjs.map +0 -1
- package/tool_registry-CtCQ4Xoz.js.map +0 -1
- package/turn_runner-BJTtAORU.js.map +0 -1
- package/turn_runner-C02LZHjt.mjs.map +0 -1
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("../../chunk-Ble4zEEl.js");
|
|
3
|
+
const require_tool_registry = require("../../tool_registry-DYUYqXvo.js");
|
|
4
|
+
require("../../guards.cjs");
|
|
5
|
+
const require_batteries_vector_filters = require("./filters.cjs");
|
|
6
|
+
const require_batteries_vector_helpers = require("./helpers.cjs");
|
|
7
|
+
const require_batteries_vector_exceptions = require("./exceptions.cjs");
|
|
8
|
+
const require_batteries_vector_contract = require("./contract.cjs");
|
|
9
|
+
const require_batteries_vector_validation = require("./validation.cjs");
|
|
10
|
+
//#region src/batteries/vector/elasticsearch/index.ts
|
|
11
|
+
/**
|
|
12
|
+
* @module @nhtio/adk/batteries/vector/elasticsearch
|
|
13
|
+
*
|
|
14
|
+
* Elasticsearch 8 adapter — each collection is an index with a `dense_vector` field; KNN uses ES8's
|
|
15
|
+
* top-level `knn` search clause with an optional `filter`; the neutral filter tree compiles to bool/term/range
|
|
16
|
+
* over `metadata.*`. Distinct from the opensearch adapter (which speaks OpenSearch's `knn_vector`/`query.knn` dialect).
|
|
17
|
+
*/
|
|
18
|
+
var getElasticsearchClient = async () => {
|
|
19
|
+
try {
|
|
20
|
+
return (await import("@elastic/elasticsearch")).Client;
|
|
21
|
+
} catch {
|
|
22
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_DRIVER_UNAVAILABLE(["@elastic/elasticsearch"]);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var similarity = (metric) => metric === "cosine" ? "cosine" : metric === "dot" ? "dot_product" : "l2_norm";
|
|
26
|
+
/**
|
|
27
|
+
* Compile the neutral filter tree to an Elasticsearch bool-query clause over `metadata.*`.
|
|
28
|
+
* String values use the `.keyword` sub-field for exact match; numbers use range/term.
|
|
29
|
+
*/
|
|
30
|
+
var translateElasticsearchFilter = (filter) => {
|
|
31
|
+
if (!filter) return void 0;
|
|
32
|
+
if (require_batteries_vector_filters.isRawFilter(filter)) {
|
|
33
|
+
if (filter.$dialect === "elasticsearch" || filter.$dialect === "opensearch") return filter.$raw;
|
|
34
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(["elasticsearch", String(filter.$dialect)]);
|
|
35
|
+
}
|
|
36
|
+
if (require_batteries_vector_filters.isFilterCondition(filter)) {
|
|
37
|
+
const { field, op, value } = filter;
|
|
38
|
+
const f = `metadata.${field}`;
|
|
39
|
+
const kw = `metadata.${field}.keyword`;
|
|
40
|
+
const term = (v) => typeof v === "number" || typeof v === "boolean" ? { term: { [f]: v } } : { term: { [kw]: v } };
|
|
41
|
+
switch (op) {
|
|
42
|
+
case "eq": return term(value);
|
|
43
|
+
case "ne": return { bool: { must_not: [term(value)] } };
|
|
44
|
+
case "gt": return { range: { [f]: { gt: value } } };
|
|
45
|
+
case "gte": return { range: { [f]: { gte: value } } };
|
|
46
|
+
case "lt": return { range: { [f]: { lt: value } } };
|
|
47
|
+
case "lte": return { range: { [f]: { lte: value } } };
|
|
48
|
+
case "in": {
|
|
49
|
+
const arr = Array.isArray(value) ? value : [value];
|
|
50
|
+
return { terms: { [arr.every((v) => typeof v === "number" || typeof v === "boolean") ? f : kw]: arr } };
|
|
51
|
+
}
|
|
52
|
+
case "nin": {
|
|
53
|
+
const arr = Array.isArray(value) ? value : [value];
|
|
54
|
+
return { bool: { must_not: [{ terms: { [arr.every((v) => typeof v === "number" || typeof v === "boolean") ? f : kw]: arr } }] } };
|
|
55
|
+
}
|
|
56
|
+
case "exists": return { exists: { field: f } };
|
|
57
|
+
default: throw new require_batteries_vector_exceptions.E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(["elasticsearch", op]);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (require_batteries_vector_filters.isFilterGroup(filter)) {
|
|
61
|
+
const { and, or, not } = filter;
|
|
62
|
+
if (and) return { bool: { must: and.map(translateElasticsearchFilter).filter(Boolean) } };
|
|
63
|
+
if (or) return { bool: {
|
|
64
|
+
should: or.map(translateElasticsearchFilter).filter(Boolean),
|
|
65
|
+
minimum_should_match: 1
|
|
66
|
+
} };
|
|
67
|
+
if (not) {
|
|
68
|
+
const inner = translateElasticsearchFilter(not);
|
|
69
|
+
return inner ? { bool: { must_not: [inner] } } : void 0;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var ElasticsearchVectorStore = class extends require_batteries_vector_contract.BaseVectorStore {
|
|
74
|
+
capabilities = {
|
|
75
|
+
transactions: false,
|
|
76
|
+
namedVectors: false,
|
|
77
|
+
rename: false,
|
|
78
|
+
rawSql: false,
|
|
79
|
+
builtInEncoding: false,
|
|
80
|
+
consistency: {
|
|
81
|
+
configurable: false,
|
|
82
|
+
default: "strong",
|
|
83
|
+
modes: ["strong"]
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
#client = null;
|
|
87
|
+
#dims = /* @__PURE__ */ new Map();
|
|
88
|
+
get #opts() {
|
|
89
|
+
return this.options;
|
|
90
|
+
}
|
|
91
|
+
static isAvailable() {
|
|
92
|
+
return typeof process !== "undefined";
|
|
93
|
+
}
|
|
94
|
+
isAvailable() {
|
|
95
|
+
return typeof process !== "undefined";
|
|
96
|
+
}
|
|
97
|
+
async connect() {
|
|
98
|
+
if (this.#client) return;
|
|
99
|
+
const c = this.#opts.connection || {};
|
|
100
|
+
if (c.client) {
|
|
101
|
+
this.#client = c.client;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const Client = await getElasticsearchClient();
|
|
105
|
+
try {
|
|
106
|
+
this.#client = new Client({
|
|
107
|
+
node: c.node ?? "http://localhost:9200",
|
|
108
|
+
auth: c.auth
|
|
109
|
+
});
|
|
110
|
+
} catch (err) {
|
|
111
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_CONNECTION_FAILED([String(err)]);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async close() {
|
|
115
|
+
if (this.#client && typeof this.#client.close === "function" && !this.#opts.connection?.client) await this.#client.close();
|
|
116
|
+
this.#client = null;
|
|
117
|
+
}
|
|
118
|
+
async #ensure() {
|
|
119
|
+
if (!this.#client) await this.connect();
|
|
120
|
+
return this.#client;
|
|
121
|
+
}
|
|
122
|
+
#body(res) {
|
|
123
|
+
return res && res.body !== void 0 ? res.body : res;
|
|
124
|
+
}
|
|
125
|
+
async createCollection(spec, ifNotExists) {
|
|
126
|
+
const client = await this.#ensure();
|
|
127
|
+
this.#dims.set(spec.collection, spec.vector.dimensions);
|
|
128
|
+
if (ifNotExists && await this.hasCollection(spec.collection)) return;
|
|
129
|
+
try {
|
|
130
|
+
await client.indices.create({
|
|
131
|
+
index: spec.collection,
|
|
132
|
+
mappings: { properties: {
|
|
133
|
+
vec: {
|
|
134
|
+
type: "dense_vector",
|
|
135
|
+
dims: spec.vector.dimensions,
|
|
136
|
+
index: true,
|
|
137
|
+
similarity: similarity(spec.vector.metric)
|
|
138
|
+
},
|
|
139
|
+
document: { type: "text" },
|
|
140
|
+
metadata: {
|
|
141
|
+
type: "object",
|
|
142
|
+
enabled: true
|
|
143
|
+
}
|
|
144
|
+
} }
|
|
145
|
+
});
|
|
146
|
+
} catch (err) {
|
|
147
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_COLLECTION_FAILED(["createCollection", String(err)]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async dropCollection(collection, ifExists) {
|
|
151
|
+
const client = await this.#ensure();
|
|
152
|
+
if (ifExists && !await this.hasCollection(collection)) return;
|
|
153
|
+
try {
|
|
154
|
+
await client.indices.delete({ index: collection });
|
|
155
|
+
this.#dims.delete(collection);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
const msg = String(err);
|
|
158
|
+
if (ifExists && msg.includes("index_not_found")) return;
|
|
159
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_COLLECTION_FAILED(["dropCollection", msg]);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async hasCollection(collection) {
|
|
163
|
+
const client = await this.#ensure();
|
|
164
|
+
try {
|
|
165
|
+
const res = await client.indices.exists({ index: collection });
|
|
166
|
+
const body = this.#body(res);
|
|
167
|
+
return body === true || body === 200 || res?.statusCode === 200;
|
|
168
|
+
} catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async renameCollection(_from, _to) {
|
|
173
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_UNSUPPORTED_OPERATION(["renameCollection", "elasticsearch"]);
|
|
174
|
+
}
|
|
175
|
+
async executeUpsert(plan) {
|
|
176
|
+
if (plan.records.length === 0) return;
|
|
177
|
+
require_batteries_vector_validation.validateRecords(plan.records);
|
|
178
|
+
const client = await this.#ensure();
|
|
179
|
+
const expected = this.#opts.dimensions ?? this.#dims.get(plan.collection);
|
|
180
|
+
try {
|
|
181
|
+
const operations = [];
|
|
182
|
+
for (const r of plan.records) {
|
|
183
|
+
let vector = r.vector;
|
|
184
|
+
if (!vector && r.document) {
|
|
185
|
+
const [v] = await this.encode([r.document], "document");
|
|
186
|
+
vector = v;
|
|
187
|
+
}
|
|
188
|
+
if (!vector) throw new require_batteries_vector_exceptions.E_VECTOR_STORE_UPSERT_FAILED(["Record missing vector and document"]);
|
|
189
|
+
if (expected !== void 0 && vector.length !== expected) throw new require_batteries_vector_exceptions.E_VECTOR_STORE_DIMENSION_MISMATCH([expected, vector.length]);
|
|
190
|
+
operations.push({ index: {
|
|
191
|
+
_index: plan.collection,
|
|
192
|
+
_id: r.id
|
|
193
|
+
} });
|
|
194
|
+
operations.push({
|
|
195
|
+
vec: vector,
|
|
196
|
+
document: r.document ?? "",
|
|
197
|
+
metadata: r.metadata ?? {}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
await client.bulk({
|
|
201
|
+
operations,
|
|
202
|
+
refresh: true
|
|
203
|
+
});
|
|
204
|
+
} catch (err) {
|
|
205
|
+
if (require_tool_registry.isInstanceOf(err, "E_VECTOR_STORE_DIMENSION_MISMATCH", require_batteries_vector_exceptions.E_VECTOR_STORE_DIMENSION_MISMATCH) || require_tool_registry.isInstanceOf(err, "E_VECTOR_STORE_UPSERT_FAILED", require_batteries_vector_exceptions.E_VECTOR_STORE_UPSERT_FAILED)) throw err;
|
|
206
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_UPSERT_FAILED([String(err)]);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async executeSearch(plan) {
|
|
210
|
+
const client = await this.#ensure();
|
|
211
|
+
const metric = this.#opts.metric ?? "cosine";
|
|
212
|
+
let queryVector;
|
|
213
|
+
if (plan.near) {
|
|
214
|
+
if ("vector" in plan.near) queryVector = plan.near.vector;
|
|
215
|
+
else if ("serverText" in plan.near) {
|
|
216
|
+
const [v] = await this.encode([plan.near.serverText], "query");
|
|
217
|
+
queryVector = v;
|
|
218
|
+
} else if ("id" in plan.near) {
|
|
219
|
+
try {
|
|
220
|
+
const res = await client.get({
|
|
221
|
+
index: plan.collection,
|
|
222
|
+
id: plan.near.id
|
|
223
|
+
});
|
|
224
|
+
queryVector = this.#body(res)?._source?.vec;
|
|
225
|
+
} catch {
|
|
226
|
+
queryVector = void 0;
|
|
227
|
+
}
|
|
228
|
+
if (!queryVector) throw new require_batteries_vector_exceptions.E_VECTOR_STORE_SEARCH_FAILED(["Referenced id not found: " + plan.near.id]);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const filter = translateElasticsearchFilter(plan.filter);
|
|
232
|
+
const size = plan.topK;
|
|
233
|
+
const from = plan.offset ?? 0;
|
|
234
|
+
try {
|
|
235
|
+
let res;
|
|
236
|
+
if (queryVector) {
|
|
237
|
+
const knn = {
|
|
238
|
+
field: "vec",
|
|
239
|
+
query_vector: queryVector,
|
|
240
|
+
k: size + from,
|
|
241
|
+
num_candidates: Math.max((size + from) * 10, 100)
|
|
242
|
+
};
|
|
243
|
+
if (filter) knn.filter = filter;
|
|
244
|
+
res = await client.search({
|
|
245
|
+
index: plan.collection,
|
|
246
|
+
knn,
|
|
247
|
+
size,
|
|
248
|
+
from,
|
|
249
|
+
_source: true
|
|
250
|
+
});
|
|
251
|
+
} else res = await client.search({
|
|
252
|
+
index: plan.collection,
|
|
253
|
+
size,
|
|
254
|
+
from,
|
|
255
|
+
query: filter ?? { match_all: {} }
|
|
256
|
+
});
|
|
257
|
+
return (this.#body(res)?.hits?.hits ?? []).map((hit) => this.#project(hit, plan, metric, !!queryVector));
|
|
258
|
+
} catch (err) {
|
|
259
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_SEARCH_FAILED([String(err)]);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
#project(hit, plan, metric, isKnn) {
|
|
263
|
+
const proj = plan.projection;
|
|
264
|
+
const src = hit._source ?? {};
|
|
265
|
+
const out = {};
|
|
266
|
+
if (proj.id) out.id = hit._id;
|
|
267
|
+
if (proj.vector && src.vec) out.vector = src.vec;
|
|
268
|
+
if (proj.document) out.document = src.document;
|
|
269
|
+
if (proj.metadata) out.metadata = src.metadata ?? {};
|
|
270
|
+
if (isKnn && typeof hit._score === "number") out.score = require_batteries_vector_helpers.normalizeScore(hit._score, metric, "similarity");
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
273
|
+
async executeDelete(plan) {
|
|
274
|
+
const client = await this.#ensure();
|
|
275
|
+
try {
|
|
276
|
+
if (plan.ids && plan.ids.length > 0) {
|
|
277
|
+
const operations = plan.ids.map((id) => ({ delete: {
|
|
278
|
+
_index: plan.collection,
|
|
279
|
+
_id: id
|
|
280
|
+
} }));
|
|
281
|
+
await client.bulk({
|
|
282
|
+
operations,
|
|
283
|
+
refresh: true
|
|
284
|
+
});
|
|
285
|
+
} else if (plan.filter) {
|
|
286
|
+
const filter = translateElasticsearchFilter(plan.filter);
|
|
287
|
+
await client.deleteByQuery({
|
|
288
|
+
index: plan.collection,
|
|
289
|
+
refresh: true,
|
|
290
|
+
query: filter ?? { match_all: {} }
|
|
291
|
+
});
|
|
292
|
+
} else await client.deleteByQuery({
|
|
293
|
+
index: plan.collection,
|
|
294
|
+
refresh: true,
|
|
295
|
+
query: { match_all: {} }
|
|
296
|
+
});
|
|
297
|
+
} catch (err) {
|
|
298
|
+
throw new require_batteries_vector_exceptions.E_VECTOR_STORE_DELETE_FAILED([String(err)]);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
//#endregion
|
|
303
|
+
exports.ElasticsearchVectorStore = ElasticsearchVectorStore;
|
|
304
|
+
exports.translateElasticsearchFilter = translateElasticsearchFilter;
|
|
305
|
+
|
|
306
|
+
//# sourceMappingURL=elasticsearch.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elasticsearch.cjs","names":["#opts","#client","#ensure","#dims","#body","#project"],"sources":["../../../src/batteries/vector/elasticsearch/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/elasticsearch\n *\n * Elasticsearch 8 adapter — each collection is an index with a `dense_vector` field; KNN uses ES8's\n * top-level `knn` search clause with an optional `filter`; the neutral filter tree compiles to bool/term/range\n * over `metadata.*`. Distinct from the opensearch adapter (which speaks OpenSearch's `knn_vector`/`query.knn` dialect).\n */\n\nimport { normalizeScore } from '../helpers'\nimport { BaseVectorStore } from '../contract'\nimport { validateRecords } from '../validation'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport { isFilterCondition, isRawFilter, isFilterGroup } from '../filters'\nimport {\n E_VECTOR_STORE_DRIVER_UNAVAILABLE,\n E_VECTOR_STORE_CONNECTION_FAILED,\n E_VECTOR_STORE_COLLECTION_FAILED,\n E_VECTOR_STORE_UPSERT_FAILED,\n E_VECTOR_STORE_SEARCH_FAILED,\n E_VECTOR_STORE_DELETE_FAILED,\n E_VECTOR_STORE_DIMENSION_MISMATCH,\n E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR,\n} from '../exceptions'\nimport type { VectorFilter } from '../filters'\nimport type { SearchPlan, UpsertPlan, DeletePlan, CollectionSpec } from '../plan'\nimport type {\n VectorMatch,\n VectorStoreCapabilities,\n BaseVectorStoreOptions,\n VectorMetadata,\n DistanceMetric,\n} from '../types'\n\nexport interface ElasticsearchVectorStoreOptions extends BaseVectorStoreOptions {\n connection?: {\n node?: string // default 'http://localhost:9200'\n auth?: { username: string; password: string } | { apiKey: string }\n client?: unknown // BYO @elastic/elasticsearch Client; overrides node\n }\n}\n\nconst getElasticsearchClient = async () => {\n try {\n const mod = await import('@elastic/elasticsearch')\n return mod.Client\n } catch {\n throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['@elastic/elasticsearch'])\n }\n}\n\n// Elasticsearch similarity per metric.\nconst similarity = (metric: DistanceMetric): string =>\n metric === 'cosine' ? 'cosine' : metric === 'dot' ? 'dot_product' : 'l2_norm'\n\n/**\n * Compile the neutral filter tree to an Elasticsearch bool-query clause over `metadata.*`.\n * String values use the `.keyword` sub-field for exact match; numbers use range/term.\n */\nexport const translateElasticsearchFilter = (\n filter?: VectorFilter\n): Record<string, unknown> | undefined => {\n if (!filter) return undefined\n if (isRawFilter(filter)) {\n if (filter.$dialect === 'elasticsearch' || filter.$dialect === 'opensearch') {\n return filter.$raw as Record<string, unknown>\n }\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['elasticsearch', String(filter.$dialect)])\n }\n if (isFilterCondition(filter)) {\n const { field, op, value } = filter\n const f = `metadata.${field}`\n const kw = `metadata.${field}.keyword`\n const term = (v: unknown) =>\n typeof v === 'number' || typeof v === 'boolean' ? { term: { [f]: v } } : { term: { [kw]: v } }\n switch (op) {\n case 'eq':\n return term(value)\n case 'ne':\n return { bool: { must_not: [term(value)] } }\n case 'gt':\n return { range: { [f]: { gt: value } } }\n case 'gte':\n return { range: { [f]: { gte: value } } }\n case 'lt':\n return { range: { [f]: { lt: value } } }\n case 'lte':\n return { range: { [f]: { lte: value } } }\n case 'in': {\n const arr = Array.isArray(value) ? value : [value]\n const allNum = arr.every((v) => typeof v === 'number' || typeof v === 'boolean')\n return { terms: { [allNum ? f : kw]: arr } }\n }\n case 'nin': {\n const arr = Array.isArray(value) ? value : [value]\n const allNum = arr.every((v) => typeof v === 'number' || typeof v === 'boolean')\n return { bool: { must_not: [{ terms: { [allNum ? f : kw]: arr } }] } }\n }\n case 'exists':\n return { exists: { field: f } }\n default:\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['elasticsearch', op])\n }\n }\n if (isFilterGroup(filter)) {\n const { and, or, not } = filter\n if (and) {\n const must = and.map(translateElasticsearchFilter).filter(Boolean)\n return { bool: { must } }\n }\n if (or) {\n const should = or.map(translateElasticsearchFilter).filter(Boolean)\n return { bool: { should, minimum_should_match: 1 } }\n }\n if (not) {\n const inner = translateElasticsearchFilter(not)\n return inner ? { bool: { must_not: [inner] } } : undefined\n }\n }\n return undefined\n}\n\nexport class ElasticsearchVectorStore extends BaseVectorStore {\n readonly capabilities: VectorStoreCapabilities = {\n transactions: false,\n namedVectors: false,\n rename: false,\n rawSql: false,\n builtInEncoding: false,\n // Made strongly consistent by refreshing the index after every write (refresh: true /\n // explicit _refresh), so a write is visible to the next search. The option is a no-op.\n consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n }\n\n #client: any | null = null\n #dims: Map<string, number> = new Map()\n\n get #opts(): ElasticsearchVectorStoreOptions {\n return this.options as ElasticsearchVectorStoreOptions\n }\n\n static isAvailable(): boolean {\n return typeof process !== 'undefined'\n }\n isAvailable(): boolean {\n return typeof process !== 'undefined'\n }\n\n async connect(): Promise<void> {\n if (this.#client) return\n const c = this.#opts.connection || {}\n if (c.client) {\n this.#client = c.client\n return\n }\n const Client = await getElasticsearchClient()\n try {\n this.#client = new Client({ node: c.node ?? 'http://localhost:9200', auth: c.auth })\n } catch (err) {\n throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n }\n }\n\n async close(): Promise<void> {\n if (\n this.#client &&\n typeof this.#client.close === 'function' &&\n !this.#opts.connection?.client\n ) {\n await this.#client.close()\n }\n this.#client = null\n }\n\n async #ensure(): Promise<any> {\n if (!this.#client) await this.connect()\n return this.#client!\n }\n\n // Unwrap the {body}/direct response shape across client versions.\n #body(res: any): any {\n return res && res.body !== undefined ? res.body : res\n }\n\n async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n const client = await this.#ensure()\n this.#dims.set(spec.collection, spec.vector.dimensions)\n if (ifNotExists && (await this.hasCollection(spec.collection))) return\n try {\n await client.indices.create({\n index: spec.collection,\n mappings: {\n properties: {\n vec: {\n type: 'dense_vector',\n dims: spec.vector.dimensions,\n index: true,\n similarity: similarity(spec.vector.metric),\n },\n document: { type: 'text' },\n metadata: { type: 'object', enabled: true },\n },\n },\n })\n } catch (err) {\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', String(err)])\n }\n }\n\n async dropCollection(collection: string, ifExists: boolean): Promise<void> {\n const client = await this.#ensure()\n if (ifExists && !(await this.hasCollection(collection))) return\n try {\n await client.indices.delete({ index: collection })\n this.#dims.delete(collection)\n } catch (err) {\n const msg = String(err)\n if (ifExists && msg.includes('index_not_found')) return\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['dropCollection', msg])\n }\n }\n\n async hasCollection(collection: string): Promise<boolean> {\n const client = await this.#ensure()\n try {\n const res = await client.indices.exists({ index: collection })\n const body = this.#body(res)\n return body === true || body === 200 || res?.statusCode === 200\n } catch {\n return false\n }\n }\n\n async renameCollection(_from: string, _to: string): Promise<void> {\n throw new E_VECTOR_STORE_UNSUPPORTED_OPERATION(['renameCollection', 'elasticsearch'])\n }\n\n async executeUpsert(plan: UpsertPlan): Promise<void> {\n if (plan.records.length === 0) return\n validateRecords(plan.records)\n const client = await this.#ensure()\n const expected = this.#opts.dimensions ?? this.#dims.get(plan.collection)\n try {\n const operations: any[] = []\n for (const r of plan.records) {\n let vector = r.vector\n if (!vector && r.document) {\n const [v] = await this.encode([r.document], 'document')\n vector = v\n }\n if (!vector) {\n throw new E_VECTOR_STORE_UPSERT_FAILED(['Record missing vector and document'])\n }\n if (expected !== undefined && vector.length !== expected) {\n throw new E_VECTOR_STORE_DIMENSION_MISMATCH([expected, vector.length])\n }\n operations.push({ index: { _index: plan.collection, _id: r.id } })\n operations.push({ vec: vector, document: r.document ?? '', metadata: r.metadata ?? {} })\n }\n await client.bulk({ operations, refresh: true })\n } catch (err) {\n if (\n isInstanceOf(err, 'E_VECTOR_STORE_DIMENSION_MISMATCH', E_VECTOR_STORE_DIMENSION_MISMATCH) ||\n isInstanceOf(err, 'E_VECTOR_STORE_UPSERT_FAILED', E_VECTOR_STORE_UPSERT_FAILED)\n ) {\n throw err\n }\n throw new E_VECTOR_STORE_UPSERT_FAILED([String(err)])\n }\n }\n\n async executeSearch(plan: SearchPlan): Promise<VectorMatch[]> {\n const client = await this.#ensure()\n const metric = this.#opts.metric ?? 'cosine'\n let queryVector: number[] | undefined\n if (plan.near) {\n if ('vector' in plan.near) {\n queryVector = plan.near.vector\n } else if ('serverText' in plan.near) {\n const [v] = await this.encode([plan.near.serverText], 'query')\n queryVector = v\n } else if ('id' in plan.near) {\n try {\n const res = await client.get({ index: plan.collection, id: plan.near.id })\n queryVector = this.#body(res)?._source?.vec as number[]\n } catch {\n queryVector = undefined\n }\n if (!queryVector) {\n throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n }\n }\n }\n\n const filter = translateElasticsearchFilter(plan.filter)\n const size = plan.topK\n const from = plan.offset ?? 0\n try {\n let res: any\n if (queryVector) {\n const knn: any = {\n field: 'vec',\n query_vector: queryVector,\n k: size + from,\n num_candidates: Math.max((size + from) * 10, 100),\n }\n if (filter) knn.filter = filter\n res = await client.search({ index: plan.collection, knn, size, from, _source: true })\n } else {\n res = await client.search({\n index: plan.collection,\n size,\n from,\n query: filter ?? { match_all: {} },\n })\n }\n const hits = this.#body(res)?.hits?.hits ?? []\n return hits.map((hit: any) => this.#project(hit, plan, metric, !!queryVector))\n } catch (err) {\n throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n }\n }\n\n #project(hit: any, plan: SearchPlan, metric: string, isKnn: boolean): VectorMatch {\n const proj = plan.projection\n const src = hit._source ?? {}\n const out: VectorMatch = {}\n if (proj.id) out.id = hit._id as string\n if (proj.vector && src.vec) out.vector = src.vec as number[]\n if (proj.document) out.document = src.document as string | undefined\n if (proj.metadata) out.metadata = (src.metadata ?? {}) as VectorMetadata\n if (isKnn && typeof hit._score === 'number') {\n // Elasticsearch cosine _score is already (sim+1)/2 ∈ [0,1]; normalize defensively to [0,1].\n out.score = normalizeScore(hit._score, metric as DistanceMetric, 'similarity')\n }\n return out\n }\n\n async executeDelete(plan: DeletePlan): Promise<void> {\n const client = await this.#ensure()\n try {\n if (plan.ids && plan.ids.length > 0) {\n const operations = plan.ids.map((id) => ({ delete: { _index: plan.collection, _id: id } }))\n await client.bulk({ operations, refresh: true })\n } else if (plan.filter) {\n const filter = translateElasticsearchFilter(plan.filter)\n await client.deleteByQuery({\n index: plan.collection,\n refresh: true,\n query: filter ?? { match_all: {} },\n })\n } else {\n await client.deleteByQuery({\n index: plan.collection,\n refresh: true,\n query: { match_all: {} },\n })\n }\n } catch (err) {\n throw new E_VECTOR_STORE_DELETE_FAILED([String(err)])\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { s as isInstanceOf } from "../../tool_registry-D1pSSlsd.mjs";
|
|
2
|
+
import "../../guards.mjs";
|
|
3
|
+
import { isFilterCondition, isFilterGroup, isRawFilter } from "./filters.mjs";
|
|
4
|
+
import { normalizeScore } from "./helpers.mjs";
|
|
5
|
+
import { E_VECTOR_STORE_COLLECTION_FAILED, E_VECTOR_STORE_CONNECTION_FAILED, E_VECTOR_STORE_DELETE_FAILED, E_VECTOR_STORE_DIMENSION_MISMATCH, E_VECTOR_STORE_DRIVER_UNAVAILABLE, E_VECTOR_STORE_SEARCH_FAILED, E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR, E_VECTOR_STORE_UNSUPPORTED_OPERATION, E_VECTOR_STORE_UPSERT_FAILED } from "./exceptions.mjs";
|
|
6
|
+
import { BaseVectorStore } from "./contract.mjs";
|
|
7
|
+
import { validateRecords } from "./validation.mjs";
|
|
8
|
+
//#region src/batteries/vector/elasticsearch/index.ts
|
|
9
|
+
/**
|
|
10
|
+
* @module @nhtio/adk/batteries/vector/elasticsearch
|
|
11
|
+
*
|
|
12
|
+
* Elasticsearch 8 adapter — each collection is an index with a `dense_vector` field; KNN uses ES8's
|
|
13
|
+
* top-level `knn` search clause with an optional `filter`; the neutral filter tree compiles to bool/term/range
|
|
14
|
+
* over `metadata.*`. Distinct from the opensearch adapter (which speaks OpenSearch's `knn_vector`/`query.knn` dialect).
|
|
15
|
+
*/
|
|
16
|
+
var getElasticsearchClient = async () => {
|
|
17
|
+
try {
|
|
18
|
+
return (await import("@elastic/elasticsearch")).Client;
|
|
19
|
+
} catch {
|
|
20
|
+
throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(["@elastic/elasticsearch"]);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var similarity = (metric) => metric === "cosine" ? "cosine" : metric === "dot" ? "dot_product" : "l2_norm";
|
|
24
|
+
/**
|
|
25
|
+
* Compile the neutral filter tree to an Elasticsearch bool-query clause over `metadata.*`.
|
|
26
|
+
* String values use the `.keyword` sub-field for exact match; numbers use range/term.
|
|
27
|
+
*/
|
|
28
|
+
var translateElasticsearchFilter = (filter) => {
|
|
29
|
+
if (!filter) return void 0;
|
|
30
|
+
if (isRawFilter(filter)) {
|
|
31
|
+
if (filter.$dialect === "elasticsearch" || filter.$dialect === "opensearch") return filter.$raw;
|
|
32
|
+
throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(["elasticsearch", String(filter.$dialect)]);
|
|
33
|
+
}
|
|
34
|
+
if (isFilterCondition(filter)) {
|
|
35
|
+
const { field, op, value } = filter;
|
|
36
|
+
const f = `metadata.${field}`;
|
|
37
|
+
const kw = `metadata.${field}.keyword`;
|
|
38
|
+
const term = (v) => typeof v === "number" || typeof v === "boolean" ? { term: { [f]: v } } : { term: { [kw]: v } };
|
|
39
|
+
switch (op) {
|
|
40
|
+
case "eq": return term(value);
|
|
41
|
+
case "ne": return { bool: { must_not: [term(value)] } };
|
|
42
|
+
case "gt": return { range: { [f]: { gt: value } } };
|
|
43
|
+
case "gte": return { range: { [f]: { gte: value } } };
|
|
44
|
+
case "lt": return { range: { [f]: { lt: value } } };
|
|
45
|
+
case "lte": return { range: { [f]: { lte: value } } };
|
|
46
|
+
case "in": {
|
|
47
|
+
const arr = Array.isArray(value) ? value : [value];
|
|
48
|
+
return { terms: { [arr.every((v) => typeof v === "number" || typeof v === "boolean") ? f : kw]: arr } };
|
|
49
|
+
}
|
|
50
|
+
case "nin": {
|
|
51
|
+
const arr = Array.isArray(value) ? value : [value];
|
|
52
|
+
return { bool: { must_not: [{ terms: { [arr.every((v) => typeof v === "number" || typeof v === "boolean") ? f : kw]: arr } }] } };
|
|
53
|
+
}
|
|
54
|
+
case "exists": return { exists: { field: f } };
|
|
55
|
+
default: throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(["elasticsearch", op]);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (isFilterGroup(filter)) {
|
|
59
|
+
const { and, or, not } = filter;
|
|
60
|
+
if (and) return { bool: { must: and.map(translateElasticsearchFilter).filter(Boolean) } };
|
|
61
|
+
if (or) return { bool: {
|
|
62
|
+
should: or.map(translateElasticsearchFilter).filter(Boolean),
|
|
63
|
+
minimum_should_match: 1
|
|
64
|
+
} };
|
|
65
|
+
if (not) {
|
|
66
|
+
const inner = translateElasticsearchFilter(not);
|
|
67
|
+
return inner ? { bool: { must_not: [inner] } } : void 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var ElasticsearchVectorStore = class extends BaseVectorStore {
|
|
72
|
+
capabilities = {
|
|
73
|
+
transactions: false,
|
|
74
|
+
namedVectors: false,
|
|
75
|
+
rename: false,
|
|
76
|
+
rawSql: false,
|
|
77
|
+
builtInEncoding: false,
|
|
78
|
+
consistency: {
|
|
79
|
+
configurable: false,
|
|
80
|
+
default: "strong",
|
|
81
|
+
modes: ["strong"]
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
#client = null;
|
|
85
|
+
#dims = /* @__PURE__ */ new Map();
|
|
86
|
+
get #opts() {
|
|
87
|
+
return this.options;
|
|
88
|
+
}
|
|
89
|
+
static isAvailable() {
|
|
90
|
+
return typeof process !== "undefined";
|
|
91
|
+
}
|
|
92
|
+
isAvailable() {
|
|
93
|
+
return typeof process !== "undefined";
|
|
94
|
+
}
|
|
95
|
+
async connect() {
|
|
96
|
+
if (this.#client) return;
|
|
97
|
+
const c = this.#opts.connection || {};
|
|
98
|
+
if (c.client) {
|
|
99
|
+
this.#client = c.client;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const Client = await getElasticsearchClient();
|
|
103
|
+
try {
|
|
104
|
+
this.#client = new Client({
|
|
105
|
+
node: c.node ?? "http://localhost:9200",
|
|
106
|
+
auth: c.auth
|
|
107
|
+
});
|
|
108
|
+
} catch (err) {
|
|
109
|
+
throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async close() {
|
|
113
|
+
if (this.#client && typeof this.#client.close === "function" && !this.#opts.connection?.client) await this.#client.close();
|
|
114
|
+
this.#client = null;
|
|
115
|
+
}
|
|
116
|
+
async #ensure() {
|
|
117
|
+
if (!this.#client) await this.connect();
|
|
118
|
+
return this.#client;
|
|
119
|
+
}
|
|
120
|
+
#body(res) {
|
|
121
|
+
return res && res.body !== void 0 ? res.body : res;
|
|
122
|
+
}
|
|
123
|
+
async createCollection(spec, ifNotExists) {
|
|
124
|
+
const client = await this.#ensure();
|
|
125
|
+
this.#dims.set(spec.collection, spec.vector.dimensions);
|
|
126
|
+
if (ifNotExists && await this.hasCollection(spec.collection)) return;
|
|
127
|
+
try {
|
|
128
|
+
await client.indices.create({
|
|
129
|
+
index: spec.collection,
|
|
130
|
+
mappings: { properties: {
|
|
131
|
+
vec: {
|
|
132
|
+
type: "dense_vector",
|
|
133
|
+
dims: spec.vector.dimensions,
|
|
134
|
+
index: true,
|
|
135
|
+
similarity: similarity(spec.vector.metric)
|
|
136
|
+
},
|
|
137
|
+
document: { type: "text" },
|
|
138
|
+
metadata: {
|
|
139
|
+
type: "object",
|
|
140
|
+
enabled: true
|
|
141
|
+
}
|
|
142
|
+
} }
|
|
143
|
+
});
|
|
144
|
+
} catch (err) {
|
|
145
|
+
throw new E_VECTOR_STORE_COLLECTION_FAILED(["createCollection", String(err)]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async dropCollection(collection, ifExists) {
|
|
149
|
+
const client = await this.#ensure();
|
|
150
|
+
if (ifExists && !await this.hasCollection(collection)) return;
|
|
151
|
+
try {
|
|
152
|
+
await client.indices.delete({ index: collection });
|
|
153
|
+
this.#dims.delete(collection);
|
|
154
|
+
} catch (err) {
|
|
155
|
+
const msg = String(err);
|
|
156
|
+
if (ifExists && msg.includes("index_not_found")) return;
|
|
157
|
+
throw new E_VECTOR_STORE_COLLECTION_FAILED(["dropCollection", msg]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async hasCollection(collection) {
|
|
161
|
+
const client = await this.#ensure();
|
|
162
|
+
try {
|
|
163
|
+
const res = await client.indices.exists({ index: collection });
|
|
164
|
+
const body = this.#body(res);
|
|
165
|
+
return body === true || body === 200 || res?.statusCode === 200;
|
|
166
|
+
} catch {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async renameCollection(_from, _to) {
|
|
171
|
+
throw new E_VECTOR_STORE_UNSUPPORTED_OPERATION(["renameCollection", "elasticsearch"]);
|
|
172
|
+
}
|
|
173
|
+
async executeUpsert(plan) {
|
|
174
|
+
if (plan.records.length === 0) return;
|
|
175
|
+
validateRecords(plan.records);
|
|
176
|
+
const client = await this.#ensure();
|
|
177
|
+
const expected = this.#opts.dimensions ?? this.#dims.get(plan.collection);
|
|
178
|
+
try {
|
|
179
|
+
const operations = [];
|
|
180
|
+
for (const r of plan.records) {
|
|
181
|
+
let vector = r.vector;
|
|
182
|
+
if (!vector && r.document) {
|
|
183
|
+
const [v] = await this.encode([r.document], "document");
|
|
184
|
+
vector = v;
|
|
185
|
+
}
|
|
186
|
+
if (!vector) throw new E_VECTOR_STORE_UPSERT_FAILED(["Record missing vector and document"]);
|
|
187
|
+
if (expected !== void 0 && vector.length !== expected) throw new E_VECTOR_STORE_DIMENSION_MISMATCH([expected, vector.length]);
|
|
188
|
+
operations.push({ index: {
|
|
189
|
+
_index: plan.collection,
|
|
190
|
+
_id: r.id
|
|
191
|
+
} });
|
|
192
|
+
operations.push({
|
|
193
|
+
vec: vector,
|
|
194
|
+
document: r.document ?? "",
|
|
195
|
+
metadata: r.metadata ?? {}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
await client.bulk({
|
|
199
|
+
operations,
|
|
200
|
+
refresh: true
|
|
201
|
+
});
|
|
202
|
+
} catch (err) {
|
|
203
|
+
if (isInstanceOf(err, "E_VECTOR_STORE_DIMENSION_MISMATCH", E_VECTOR_STORE_DIMENSION_MISMATCH) || isInstanceOf(err, "E_VECTOR_STORE_UPSERT_FAILED", E_VECTOR_STORE_UPSERT_FAILED)) throw err;
|
|
204
|
+
throw new E_VECTOR_STORE_UPSERT_FAILED([String(err)]);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async executeSearch(plan) {
|
|
208
|
+
const client = await this.#ensure();
|
|
209
|
+
const metric = this.#opts.metric ?? "cosine";
|
|
210
|
+
let queryVector;
|
|
211
|
+
if (plan.near) {
|
|
212
|
+
if ("vector" in plan.near) queryVector = plan.near.vector;
|
|
213
|
+
else if ("serverText" in plan.near) {
|
|
214
|
+
const [v] = await this.encode([plan.near.serverText], "query");
|
|
215
|
+
queryVector = v;
|
|
216
|
+
} else if ("id" in plan.near) {
|
|
217
|
+
try {
|
|
218
|
+
const res = await client.get({
|
|
219
|
+
index: plan.collection,
|
|
220
|
+
id: plan.near.id
|
|
221
|
+
});
|
|
222
|
+
queryVector = this.#body(res)?._source?.vec;
|
|
223
|
+
} catch {
|
|
224
|
+
queryVector = void 0;
|
|
225
|
+
}
|
|
226
|
+
if (!queryVector) throw new E_VECTOR_STORE_SEARCH_FAILED(["Referenced id not found: " + plan.near.id]);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const filter = translateElasticsearchFilter(plan.filter);
|
|
230
|
+
const size = plan.topK;
|
|
231
|
+
const from = plan.offset ?? 0;
|
|
232
|
+
try {
|
|
233
|
+
let res;
|
|
234
|
+
if (queryVector) {
|
|
235
|
+
const knn = {
|
|
236
|
+
field: "vec",
|
|
237
|
+
query_vector: queryVector,
|
|
238
|
+
k: size + from,
|
|
239
|
+
num_candidates: Math.max((size + from) * 10, 100)
|
|
240
|
+
};
|
|
241
|
+
if (filter) knn.filter = filter;
|
|
242
|
+
res = await client.search({
|
|
243
|
+
index: plan.collection,
|
|
244
|
+
knn,
|
|
245
|
+
size,
|
|
246
|
+
from,
|
|
247
|
+
_source: true
|
|
248
|
+
});
|
|
249
|
+
} else res = await client.search({
|
|
250
|
+
index: plan.collection,
|
|
251
|
+
size,
|
|
252
|
+
from,
|
|
253
|
+
query: filter ?? { match_all: {} }
|
|
254
|
+
});
|
|
255
|
+
return (this.#body(res)?.hits?.hits ?? []).map((hit) => this.#project(hit, plan, metric, !!queryVector));
|
|
256
|
+
} catch (err) {
|
|
257
|
+
throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)]);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
#project(hit, plan, metric, isKnn) {
|
|
261
|
+
const proj = plan.projection;
|
|
262
|
+
const src = hit._source ?? {};
|
|
263
|
+
const out = {};
|
|
264
|
+
if (proj.id) out.id = hit._id;
|
|
265
|
+
if (proj.vector && src.vec) out.vector = src.vec;
|
|
266
|
+
if (proj.document) out.document = src.document;
|
|
267
|
+
if (proj.metadata) out.metadata = src.metadata ?? {};
|
|
268
|
+
if (isKnn && typeof hit._score === "number") out.score = normalizeScore(hit._score, metric, "similarity");
|
|
269
|
+
return out;
|
|
270
|
+
}
|
|
271
|
+
async executeDelete(plan) {
|
|
272
|
+
const client = await this.#ensure();
|
|
273
|
+
try {
|
|
274
|
+
if (plan.ids && plan.ids.length > 0) {
|
|
275
|
+
const operations = plan.ids.map((id) => ({ delete: {
|
|
276
|
+
_index: plan.collection,
|
|
277
|
+
_id: id
|
|
278
|
+
} }));
|
|
279
|
+
await client.bulk({
|
|
280
|
+
operations,
|
|
281
|
+
refresh: true
|
|
282
|
+
});
|
|
283
|
+
} else if (plan.filter) {
|
|
284
|
+
const filter = translateElasticsearchFilter(plan.filter);
|
|
285
|
+
await client.deleteByQuery({
|
|
286
|
+
index: plan.collection,
|
|
287
|
+
refresh: true,
|
|
288
|
+
query: filter ?? { match_all: {} }
|
|
289
|
+
});
|
|
290
|
+
} else await client.deleteByQuery({
|
|
291
|
+
index: plan.collection,
|
|
292
|
+
refresh: true,
|
|
293
|
+
query: { match_all: {} }
|
|
294
|
+
});
|
|
295
|
+
} catch (err) {
|
|
296
|
+
throw new E_VECTOR_STORE_DELETE_FAILED([String(err)]);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
//#endregion
|
|
301
|
+
export { ElasticsearchVectorStore, translateElasticsearchFilter };
|
|
302
|
+
|
|
303
|
+
//# sourceMappingURL=elasticsearch.mjs.map
|