@nhtio/adk 1.20260607.2 → 1.20260609.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/CHANGELOG.md +230 -0
- package/batteries/embeddings/openai/adapter.cjs +1 -1
- package/batteries/embeddings/openai/adapter.mjs +1 -1
- package/batteries/embeddings/openai/exceptions.cjs +1 -1
- package/batteries/embeddings/openai/exceptions.mjs +1 -1
- package/batteries/embeddings/openai/types.d.ts +7 -0
- package/batteries/embeddings/webllm/adapter.cjs +1 -1
- package/batteries/embeddings/webllm/adapter.mjs +1 -1
- package/batteries/embeddings/webllm/exceptions.cjs +1 -1
- package/batteries/embeddings/webllm/exceptions.mjs +1 -1
- package/batteries/llm/chat_common/helpers.d.ts +165 -0
- package/batteries/llm/chat_common/types.d.ts +309 -0
- package/batteries/llm/index.d.ts +5 -0
- package/batteries/llm/ollama/adapter.cjs +736 -0
- package/batteries/llm/ollama/adapter.cjs.map +1 -0
- package/batteries/llm/ollama/adapter.d.ts +64 -0
- package/batteries/llm/ollama/adapter.mjs +734 -0
- package/batteries/llm/ollama/adapter.mjs.map +1 -0
- package/batteries/llm/ollama/exceptions.cjs +105 -0
- package/batteries/llm/ollama/exceptions.cjs.map +1 -0
- package/batteries/llm/ollama/exceptions.d.ts +112 -0
- package/batteries/llm/ollama/exceptions.mjs +96 -0
- package/batteries/llm/ollama/exceptions.mjs.map +1 -0
- package/batteries/llm/ollama/helpers.cjs +487 -0
- package/batteries/llm/ollama/helpers.cjs.map +1 -0
- package/batteries/llm/ollama/helpers.d.ts +158 -0
- package/batteries/llm/ollama/helpers.mjs +450 -0
- package/batteries/llm/ollama/helpers.mjs.map +1 -0
- package/batteries/llm/ollama/index.d.ts +29 -0
- package/batteries/llm/ollama/types.cjs +2 -0
- package/batteries/llm/ollama/types.d.ts +334 -0
- package/batteries/llm/ollama/types.mjs +0 -0
- package/batteries/llm/ollama/validation.cjs +130 -0
- package/batteries/llm/ollama/validation.cjs.map +1 -0
- package/batteries/llm/ollama/validation.d.ts +31 -0
- package/batteries/llm/ollama/validation.mjs +127 -0
- package/batteries/llm/ollama/validation.mjs.map +1 -0
- package/batteries/llm/ollama.cjs +54 -0
- package/batteries/llm/ollama.mjs +6 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs +36 -19
- package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/adapter.mjs +23 -6
- package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/exceptions.cjs +1 -1
- package/batteries/llm/openai_chat_completions/exceptions.mjs +1 -1
- package/batteries/llm/openai_chat_completions/helpers.cjs +80 -320
- package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/helpers.d.ts +68 -144
- package/batteries/llm/openai_chat_completions/helpers.mjs +40 -280
- package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/types.d.ts +273 -181
- 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/openai_chat_completions.cjs +29 -28
- package/batteries/llm/openai_chat_completions.mjs +2 -1
- package/batteries/llm/webllm_chat_completions/adapter.cjs +38 -19
- package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.d.ts +18 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs +25 -6
- package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/exceptions.cjs +1 -1
- package/batteries/llm/webllm_chat_completions/exceptions.mjs +1 -1
- package/batteries/llm/webllm_chat_completions/helpers.cjs +29 -28
- package/batteries/llm/webllm_chat_completions/helpers.mjs +2 -1
- package/batteries/llm/webllm_chat_completions/types.d.ts +21 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs +13 -1
- package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/validation.d.ts +12 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs +13 -1
- package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions.cjs +29 -28
- package/batteries/llm/webllm_chat_completions.mjs +2 -1
- package/batteries/llm.cjs +44 -28
- package/batteries/llm.mjs +9 -4
- package/batteries/storage/flydrive.cjs +1 -1
- package/batteries/storage/flydrive.mjs +1 -1
- package/batteries/storage/in_memory/index.d.ts +1 -1
- package/batteries/storage/in_memory.cjs +2 -2
- package/batteries/storage/in_memory.cjs.map +1 -1
- package/batteries/storage/in_memory.mjs +2 -2
- package/batteries/storage/in_memory.mjs.map +1 -1
- package/batteries/storage/opfs/index.d.ts +19 -0
- package/batteries/storage/opfs.cjs +1 -1
- package/batteries/storage/opfs.cjs.map +1 -1
- package/batteries/storage/opfs.mjs +1 -1
- package/batteries/storage/opfs.mjs.map +1 -1
- package/batteries/tools/_shared/index.d.ts +121 -0
- package/batteries/tools/_shared.cjs +157 -0
- package/batteries/tools/_shared.cjs.map +1 -0
- package/batteries/tools/_shared.mjs +149 -0
- package/batteries/tools/_shared.mjs.map +1 -0
- package/batteries/tools/color.cjs +3 -2
- package/batteries/tools/color.cjs.map +1 -1
- package/batteries/tools/color.mjs +3 -2
- package/batteries/tools/color.mjs.map +1 -1
- package/batteries/tools/comparison.cjs +4 -3
- package/batteries/tools/comparison.cjs.map +1 -1
- package/batteries/tools/comparison.mjs +4 -3
- package/batteries/tools/comparison.mjs.map +1 -1
- package/batteries/tools/data_structure.cjs +30 -10
- package/batteries/tools/data_structure.cjs.map +1 -1
- package/batteries/tools/data_structure.mjs +30 -10
- package/batteries/tools/data_structure.mjs.map +1 -1
- package/batteries/tools/datetime_extended.cjs +5 -10
- package/batteries/tools/datetime_extended.cjs.map +1 -1
- package/batteries/tools/datetime_extended.mjs +5 -10
- package/batteries/tools/datetime_extended.mjs.map +1 -1
- package/batteries/tools/datetime_math.cjs +2 -2
- package/batteries/tools/datetime_math.mjs +2 -2
- package/batteries/tools/encoding.cjs +13 -4
- package/batteries/tools/encoding.cjs.map +1 -1
- package/batteries/tools/encoding.mjs +13 -4
- package/batteries/tools/encoding.mjs.map +1 -1
- package/batteries/tools/formatting.cjs +4 -4
- package/batteries/tools/formatting.cjs.map +1 -1
- package/batteries/tools/formatting.mjs +4 -4
- package/batteries/tools/formatting.mjs.map +1 -1
- package/batteries/tools/geo_basics.cjs +2 -2
- package/batteries/tools/geo_basics.mjs +2 -2
- package/batteries/tools/index.d.ts +3 -0
- package/batteries/tools/math.cjs +10 -8
- package/batteries/tools/math.cjs.map +1 -1
- package/batteries/tools/math.mjs +10 -8
- 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 +9 -5
- package/batteries/tools/parsing.cjs.map +1 -1
- package/batteries/tools/parsing.mjs +9 -5
- package/batteries/tools/parsing.mjs.map +1 -1
- package/batteries/tools/retrievables.cjs +4 -4
- package/batteries/tools/retrievables.mjs +4 -4
- package/batteries/tools/scrapper/exceptions.d.ts +21 -0
- package/batteries/tools/scrapper/index.d.ts +172 -0
- package/batteries/tools/scrapper/shared.d.ts +139 -0
- package/batteries/tools/scrapper.cjs +8 -0
- package/batteries/tools/scrapper.mjs +2 -0
- package/batteries/tools/searxng/exceptions.d.ts +21 -0
- package/batteries/tools/searxng/index.d.ts +177 -0
- package/batteries/tools/searxng.cjs +6 -0
- package/batteries/tools/searxng.mjs +2 -0
- package/batteries/tools/standing_instructions.cjs +4 -4
- package/batteries/tools/standing_instructions.mjs +4 -4
- package/batteries/tools/statistics.cjs +54 -43
- package/batteries/tools/statistics.cjs.map +1 -1
- package/batteries/tools/statistics.mjs +54 -43
- package/batteries/tools/statistics.mjs.map +1 -1
- package/batteries/tools/string_processing.cjs +5 -5
- package/batteries/tools/string_processing.cjs.map +1 -1
- package/batteries/tools/string_processing.mjs +5 -5
- package/batteries/tools/string_processing.mjs.map +1 -1
- package/batteries/tools/structured_data.cjs +8 -13
- package/batteries/tools/structured_data.cjs.map +1 -1
- package/batteries/tools/structured_data.mjs +8 -13
- package/batteries/tools/structured_data.mjs.map +1 -1
- 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 +10 -8
- package/batteries/tools/unit_conversion.cjs.map +1 -1
- package/batteries/tools/unit_conversion.mjs +10 -8
- package/batteries/tools/unit_conversion.mjs.map +1 -1
- package/batteries/tools/web_retrieval/index.d.ts +186 -0
- package/batteries/tools/web_retrieval.cjs +206 -0
- package/batteries/tools/web_retrieval.cjs.map +1 -0
- package/batteries/tools/web_retrieval.mjs +201 -0
- package/batteries/tools/web_retrieval.mjs.map +1 -0
- package/batteries/tools.cjs +15 -0
- package/batteries/tools.mjs +4 -1
- package/batteries/vector/arangodb/index.d.ts +2 -0
- package/batteries/vector/arangodb.cjs +2 -1
- package/batteries/vector/arangodb.cjs.map +1 -1
- package/batteries/vector/arangodb.mjs +2 -1
- package/batteries/vector/arangodb.mjs.map +1 -1
- package/batteries/vector/builder.cjs +31 -0
- package/batteries/vector/builder.cjs.map +1 -1
- package/batteries/vector/builder.d.ts +58 -0
- package/batteries/vector/builder.mjs +31 -0
- package/batteries/vector/builder.mjs.map +1 -1
- package/batteries/vector/chroma/index.d.ts +4 -0
- package/batteries/vector/chroma.cjs +3 -0
- package/batteries/vector/chroma.cjs.map +1 -1
- package/batteries/vector/chroma.mjs +3 -0
- package/batteries/vector/chroma.mjs.map +1 -1
- package/batteries/vector/clickhouse/index.d.ts +2 -0
- package/batteries/vector/clickhouse.cjs +2 -1
- package/batteries/vector/clickhouse.cjs.map +1 -1
- package/batteries/vector/clickhouse.mjs +2 -1
- package/batteries/vector/clickhouse.mjs.map +1 -1
- package/batteries/vector/cloudflare/index.d.ts +2 -0
- package/batteries/vector/cloudflare.cjs +2 -1
- package/batteries/vector/cloudflare.cjs.map +1 -1
- package/batteries/vector/cloudflare.mjs +2 -1
- package/batteries/vector/cloudflare.mjs.map +1 -1
- package/batteries/vector/conformance/index.d.ts +22 -0
- package/batteries/vector/conformance.cjs +22 -0
- package/batteries/vector/conformance.cjs.map +1 -1
- package/batteries/vector/conformance.mjs +22 -0
- package/batteries/vector/conformance.mjs.map +1 -1
- package/batteries/vector/contract.cjs +22 -0
- package/batteries/vector/contract.cjs.map +1 -1
- package/batteries/vector/contract.d.ts +51 -0
- package/batteries/vector/contract.mjs +22 -0
- package/batteries/vector/contract.mjs.map +1 -1
- package/batteries/vector/couchbase/index.d.ts +2 -0
- package/batteries/vector/couchbase.cjs +2 -1
- package/batteries/vector/couchbase.cjs.map +1 -1
- package/batteries/vector/couchbase.mjs +2 -1
- package/batteries/vector/couchbase.mjs.map +1 -1
- package/batteries/vector/duckdb/index.d.ts +2 -0
- package/batteries/vector/duckdb.cjs +2 -1
- package/batteries/vector/duckdb.cjs.map +1 -1
- package/batteries/vector/duckdb.mjs +2 -1
- package/batteries/vector/duckdb.mjs.map +1 -1
- package/batteries/vector/elasticsearch/index.d.ts +2 -0
- package/batteries/vector/elasticsearch.cjs +2 -1
- package/batteries/vector/elasticsearch.cjs.map +1 -1
- package/batteries/vector/elasticsearch.mjs +2 -1
- package/batteries/vector/elasticsearch.mjs.map +1 -1
- package/batteries/vector/exceptions.cjs +1 -1
- package/batteries/vector/exceptions.mjs +1 -1
- package/batteries/vector/factory.cjs +6 -0
- package/batteries/vector/factory.cjs.map +1 -1
- package/batteries/vector/factory.d.ts +14 -0
- package/batteries/vector/factory.mjs +6 -0
- package/batteries/vector/factory.mjs.map +1 -1
- package/batteries/vector/filters.cjs +22 -1
- package/batteries/vector/filters.cjs.map +1 -1
- package/batteries/vector/filters.d.ts +38 -0
- package/batteries/vector/filters.mjs +22 -1
- package/batteries/vector/filters.mjs.map +1 -1
- package/batteries/vector/helpers.cjs +13 -0
- package/batteries/vector/helpers.cjs.map +1 -1
- package/batteries/vector/helpers.d.ts +14 -0
- package/batteries/vector/helpers.mjs +13 -0
- package/batteries/vector/helpers.mjs.map +1 -1
- package/batteries/vector/hnswlib/index.d.ts +2 -0
- package/batteries/vector/hnswlib.cjs +2 -1
- package/batteries/vector/hnswlib.cjs.map +1 -1
- package/batteries/vector/hnswlib.mjs +2 -1
- package/batteries/vector/hnswlib.mjs.map +1 -1
- package/batteries/vector/in_memory/index.d.ts +1 -0
- package/batteries/vector/in_memory.cjs +1 -0
- package/batteries/vector/in_memory.cjs.map +1 -1
- package/batteries/vector/in_memory.mjs +1 -0
- package/batteries/vector/in_memory.mjs.map +1 -1
- package/batteries/vector/lancedb/index.d.ts +2 -0
- package/batteries/vector/lancedb.cjs +2 -1
- package/batteries/vector/lancedb.cjs.map +1 -1
- package/batteries/vector/lancedb.mjs +2 -1
- package/batteries/vector/lancedb.mjs.map +1 -1
- package/batteries/vector/mariadb/index.d.ts +2 -0
- package/batteries/vector/mariadb.cjs +2 -1
- package/batteries/vector/mariadb.cjs.map +1 -1
- package/batteries/vector/mariadb.mjs +2 -1
- package/batteries/vector/mariadb.mjs.map +1 -1
- package/batteries/vector/meilisearch/index.d.ts +2 -0
- package/batteries/vector/meilisearch.cjs +2 -1
- package/batteries/vector/meilisearch.cjs.map +1 -1
- package/batteries/vector/meilisearch.mjs +2 -1
- package/batteries/vector/meilisearch.mjs.map +1 -1
- package/batteries/vector/migrate.cjs +18 -1
- package/batteries/vector/migrate.cjs.map +1 -1
- package/batteries/vector/migrate.d.ts +31 -0
- package/batteries/vector/migrate.mjs +18 -1
- package/batteries/vector/migrate.mjs.map +1 -1
- package/batteries/vector/milvus/index.d.ts +5 -0
- package/batteries/vector/milvus.cjs +4 -0
- package/batteries/vector/milvus.cjs.map +1 -1
- package/batteries/vector/milvus.mjs +4 -0
- package/batteries/vector/milvus.mjs.map +1 -1
- package/batteries/vector/mongodb/index.d.ts +2 -0
- package/batteries/vector/mongodb.cjs +2 -1
- package/batteries/vector/mongodb.cjs.map +1 -1
- package/batteries/vector/mongodb.mjs +2 -1
- package/batteries/vector/mongodb.mjs.map +1 -1
- package/batteries/vector/neo4j/index.d.ts +2 -0
- package/batteries/vector/neo4j.cjs +2 -1
- package/batteries/vector/neo4j.cjs.map +1 -1
- package/batteries/vector/neo4j.mjs +2 -1
- package/batteries/vector/neo4j.mjs.map +1 -1
- package/batteries/vector/opensearch/index.d.ts +2 -0
- package/batteries/vector/opensearch.cjs +2 -1
- package/batteries/vector/opensearch.cjs.map +1 -1
- package/batteries/vector/opensearch.mjs +2 -1
- package/batteries/vector/opensearch.mjs.map +1 -1
- package/batteries/vector/oracle23ai/index.d.ts +2 -0
- package/batteries/vector/oracle23ai.cjs +2 -1
- package/batteries/vector/oracle23ai.cjs.map +1 -1
- package/batteries/vector/oracle23ai.mjs +2 -1
- package/batteries/vector/oracle23ai.mjs.map +1 -1
- package/batteries/vector/orama/index.d.ts +1 -0
- package/batteries/vector/orama.cjs +1 -0
- package/batteries/vector/orama.cjs.map +1 -1
- package/batteries/vector/orama.mjs +1 -0
- package/batteries/vector/orama.mjs.map +1 -1
- package/batteries/vector/pgvector/index.d.ts +9 -2
- package/batteries/vector/pgvector.cjs +4 -0
- package/batteries/vector/pgvector.cjs.map +1 -1
- package/batteries/vector/pgvector.mjs +4 -0
- package/batteries/vector/pgvector.mjs.map +1 -1
- package/batteries/vector/pinecone/index.d.ts +5 -0
- package/batteries/vector/pinecone.cjs +3 -1
- package/batteries/vector/pinecone.cjs.map +1 -1
- package/batteries/vector/pinecone.mjs +3 -1
- package/batteries/vector/pinecone.mjs.map +1 -1
- package/batteries/vector/plan.d.ts +27 -0
- package/batteries/vector/qdrant/index.d.ts +5 -0
- package/batteries/vector/qdrant.cjs +4 -0
- package/batteries/vector/qdrant.cjs.map +1 -1
- package/batteries/vector/qdrant.mjs +4 -0
- package/batteries/vector/qdrant.mjs.map +1 -1
- package/batteries/vector/redis/index.d.ts +2 -0
- package/batteries/vector/redis.cjs +2 -1
- package/batteries/vector/redis.cjs.map +1 -1
- package/batteries/vector/redis.mjs +2 -1
- package/batteries/vector/redis.mjs.map +1 -1
- package/batteries/vector/retrievable.cjs +9 -1
- package/batteries/vector/retrievable.cjs.map +1 -1
- package/batteries/vector/retrievable.mjs +9 -1
- package/batteries/vector/retrievable.mjs.map +1 -1
- package/batteries/vector/retrievable_glue.d.ts +21 -0
- package/batteries/vector/s3vectors/index.d.ts +2 -0
- package/batteries/vector/s3vectors.cjs +2 -1
- package/batteries/vector/s3vectors.cjs.map +1 -1
- package/batteries/vector/s3vectors.mjs +2 -1
- package/batteries/vector/s3vectors.mjs.map +1 -1
- package/batteries/vector/schema.cjs +28 -0
- package/batteries/vector/schema.cjs.map +1 -1
- package/batteries/vector/schema.d.ts +39 -0
- package/batteries/vector/schema.mjs +28 -0
- package/batteries/vector/schema.mjs.map +1 -1
- package/batteries/vector/solr/index.d.ts +2 -0
- package/batteries/vector/solr.cjs +2 -1
- package/batteries/vector/solr.cjs.map +1 -1
- package/batteries/vector/solr.mjs +2 -1
- package/batteries/vector/solr.mjs.map +1 -1
- package/batteries/vector/sqlite_vec/index.d.ts +6 -3
- package/batteries/vector/sqlite_vec.cjs +2 -0
- package/batteries/vector/sqlite_vec.cjs.map +1 -1
- package/batteries/vector/sqlite_vec.mjs +2 -0
- package/batteries/vector/sqlite_vec.mjs.map +1 -1
- package/batteries/vector/surrealdb/index.d.ts +2 -0
- package/batteries/vector/surrealdb.cjs +2 -1
- package/batteries/vector/surrealdb.cjs.map +1 -1
- package/batteries/vector/surrealdb.mjs +2 -1
- package/batteries/vector/surrealdb.mjs.map +1 -1
- package/batteries/vector/types.d.ts +27 -0
- package/batteries/vector/typesense/index.d.ts +2 -0
- package/batteries/vector/typesense.cjs +2 -1
- package/batteries/vector/typesense.cjs.map +1 -1
- package/batteries/vector/typesense.mjs +2 -1
- package/batteries/vector/typesense.mjs.map +1 -1
- package/batteries/vector/validation.cjs +14 -0
- package/batteries/vector/validation.cjs.map +1 -1
- package/batteries/vector/validation.d.ts +14 -0
- package/batteries/vector/validation.mjs +14 -0
- package/batteries/vector/validation.mjs.map +1 -1
- package/batteries/vector/vector_store_constructor.cjs +1 -1
- package/batteries/vector/vector_store_constructor.cjs.map +1 -1
- package/batteries/vector/vector_store_constructor.d.ts +1 -1
- package/batteries/vector/vector_store_constructor.mjs +1 -1
- package/batteries/vector/vector_store_constructor.mjs.map +1 -1
- package/batteries/vector/vespa/index.d.ts +2 -0
- package/batteries/vector/vespa.cjs +2 -1
- package/batteries/vector/vespa.cjs.map +1 -1
- package/batteries/vector/vespa.mjs +2 -1
- package/batteries/vector/vespa.mjs.map +1 -1
- package/batteries/vector/weaviate/index.d.ts +2 -0
- package/batteries/vector/weaviate.cjs +2 -1
- package/batteries/vector/weaviate.cjs.map +1 -1
- package/batteries/vector/weaviate.mjs +2 -1
- package/batteries/vector/weaviate.mjs.map +1 -1
- package/batteries.cjs +58 -28
- package/batteries.mjs +12 -5
- package/{common-BT0nfCi9.mjs → common-DYDUi99O.mjs} +9 -9
- package/common-DYDUi99O.mjs.map +1 -0
- package/{common-Cj8TaQ9U.js → common-DZl3ADJs.js} +9 -9
- package/common-DZl3ADJs.js.map +1 -0
- package/common.cjs +7 -7
- package/common.mjs +7 -7
- package/{dispatch_runner-DPcS7Y_M.mjs → dispatch_runner--ZhdDWRZ.mjs} +27 -5
- package/{dispatch_runner-DPcS7Y_M.mjs.map → dispatch_runner--ZhdDWRZ.mjs.map} +1 -1
- package/{dispatch_runner-BHBNupqp.js → dispatch_runner-nHDKkxye.js} +27 -5
- package/{dispatch_runner-BHBNupqp.js.map → dispatch_runner-nHDKkxye.js.map} +1 -1
- package/dispatch_runner.cjs +1 -1
- package/dispatch_runner.d.ts +1 -1
- package/dispatch_runner.mjs +1 -1
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs.map +1 -1
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.d.ts +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.mjs +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.mjs.map +1 -1
- package/eslint/rules/no_model_in_tool_handler.cjs +1 -0
- package/eslint/rules/no_model_in_tool_handler.cjs.map +1 -1
- package/eslint/rules/no_model_in_tool_handler.d.ts +1 -0
- package/eslint/rules/no_model_in_tool_handler.mjs +1 -0
- package/eslint/rules/no_model_in_tool_handler.mjs.map +1 -1
- package/eslint/rules/require_validator_any_required.cjs +1 -0
- package/eslint/rules/require_validator_any_required.cjs.map +1 -1
- package/eslint/rules/require_validator_any_required.d.ts +1 -0
- package/eslint/rules/require_validator_any_required.mjs +1 -0
- package/eslint/rules/require_validator_any_required.mjs.map +1 -1
- package/eslint/rules/thought_payload_requires_replay_tag.cjs +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.cjs.map +1 -1
- package/eslint/rules/thought_payload_requires_replay_tag.d.ts +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.mjs +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.mjs.map +1 -1
- package/eslint/rules/token_encoding_requires_context_window.cjs +1 -0
- package/eslint/rules/token_encoding_requires_context_window.cjs.map +1 -1
- package/eslint/rules/token_encoding_requires_context_window.d.ts +1 -0
- package/eslint/rules/token_encoding_requires_context_window.mjs +1 -0
- package/eslint/rules/token_encoding_requires_context_window.mjs.map +1 -1
- package/eslint/rules.cjs +1 -1
- package/eslint/rules.mjs +1 -1
- package/eslint.cjs +2 -2
- package/eslint.mjs +2 -2
- package/{exceptions-BeWH2FwP.mjs → exceptions-BDhN0Xzr.mjs} +3 -2
- package/exceptions-BDhN0Xzr.mjs.map +1 -0
- package/{exceptions-CitH5wZI.js → exceptions-BRXrUKiW.js} +3 -2
- package/exceptions-BRXrUKiW.js.map +1 -0
- package/exceptions.cjs +2 -2
- package/exceptions.mjs +2 -2
- package/factories.cjs +1 -1
- package/factories.mjs +1 -1
- package/forge.cjs +4 -4
- package/forge.d.ts +1 -1
- package/forge.mjs +4 -4
- package/guards.cjs +9 -9
- package/guards.mjs +9 -9
- package/helpers-DSTFxTiC.js +497 -0
- package/helpers-DSTFxTiC.js.map +1 -0
- package/helpers-xhrQbMAG.mjs +306 -0
- package/helpers-xhrQbMAG.mjs.map +1 -0
- package/index.cjs +12 -12
- package/index.mjs +12 -12
- package/lib/classes/base_exception.d.ts +1 -0
- package/lib/classes/media.d.ts +10 -0
- package/lib/classes/retrievable.d.ts +1 -1
- package/lib/classes/spooled_json_artifact.d.ts +1 -1
- package/lib/classes/spooled_markdown_artifact.d.ts +1 -0
- package/lib/classes/tokenizable.d.ts +3 -0
- package/lib/classes/tool.d.ts +8 -0
- package/lib/classes/turn_gate.d.ts +6 -0
- package/lib/dispatch_runner.d.ts +4 -32
- package/lib/helpers/bignum.cjs +82 -0
- package/lib/helpers/bignum.cjs.map +1 -0
- package/lib/helpers/bignum.d.ts +52 -0
- package/lib/helpers/bignum.mjs +74 -0
- package/lib/helpers/bignum.mjs.map +1 -0
- package/lib/turn_runner.d.ts +1 -1
- package/lib/types/dispatch_runner.d.ts +83 -0
- package/lib/utils/exceptions.d.ts +1 -1
- package/lib/utils/retry.cjs.map +1 -1
- package/lib/utils/retry.d.ts +2 -0
- package/lib/utils/retry.mjs.map +1 -1
- package/mcp/adk-docs-corpus.json +1 -1
- package/package.json +259 -204
- package/{runtime-j92CNi5z.mjs → runtime-Bz5zA8wc.mjs} +2 -2
- package/{runtime-j92CNi5z.mjs.map → runtime-Bz5zA8wc.mjs.map} +1 -1
- package/{runtime-MFFcJrRv.js → runtime-DslE1aBw.js} +2 -2
- package/{runtime-MFFcJrRv.js.map → runtime-DslE1aBw.js.map} +1 -1
- package/scrapper-BHM1mCde.mjs +432 -0
- package/scrapper-BHM1mCde.mjs.map +1 -0
- package/scrapper-BeweWurk.js +462 -0
- package/scrapper-BeweWurk.js.map +1 -0
- package/searxng-BJFulNcK.mjs +247 -0
- package/searxng-BJFulNcK.mjs.map +1 -0
- package/searxng-B_D--V5q.js +265 -0
- package/searxng-B_D--V5q.js.map +1 -0
- package/skills/adk-assembly/SKILL.md +2 -2
- package/{spooled_artifact-CHoZgWwI.mjs → spooled_artifact-7eePq7JA.mjs} +5 -5
- package/{spooled_artifact-CHoZgWwI.mjs.map → spooled_artifact-7eePq7JA.mjs.map} +1 -1
- package/{spooled_artifact-BTq6Nzfy.js → spooled_artifact-DX8LLyUX.js} +5 -5
- package/{spooled_artifact-BTq6Nzfy.js.map → spooled_artifact-DX8LLyUX.js.map} +1 -1
- package/spooled_artifact.cjs +2 -2
- package/spooled_artifact.mjs +2 -2
- package/{spooled_markdown_artifact-CALSDxIx.js → spooled_markdown_artifact-ClX72lek.js} +4 -4
- package/spooled_markdown_artifact-ClX72lek.js.map +1 -0
- package/{spooled_markdown_artifact-Ci5UL7l4.mjs → spooled_markdown_artifact-wkrBF3oX.mjs} +4 -4
- package/spooled_markdown_artifact-wkrBF3oX.mjs.map +1 -0
- package/{thought-D34QQZZ9.mjs → thought-B_vxAiKU.mjs} +5 -5
- package/{thought-D34QQZZ9.mjs.map → thought-B_vxAiKU.mjs.map} +1 -1
- package/{thought-BbwhJ1wb.js → thought-DLwpF7MI.js} +5 -5
- package/{thought-BbwhJ1wb.js.map → thought-DLwpF7MI.js.map} +1 -1
- package/{tool-CVyZkFC7.js → tool-D5WGVIcI.js} +4 -4
- package/{tool-CVyZkFC7.js.map → tool-D5WGVIcI.js.map} +1 -1
- package/{tool-CMhaDRNd.mjs → tool-wMYMVl60.mjs} +4 -4
- package/{tool-CMhaDRNd.mjs.map → tool-wMYMVl60.mjs.map} +1 -1
- package/{tool_call-CV5qVNlb.mjs → tool_call-B4-_-vjG.mjs} +5 -5
- package/tool_call-B4-_-vjG.mjs.map +1 -0
- package/{tool_call-Db68hB7y.js → tool_call-DixVlW40.js} +5 -5
- package/tool_call-DixVlW40.js.map +1 -0
- package/{tool_registry-D1pSSlsd.mjs → tool_registry-791Vrjtf.mjs} +4 -3
- package/tool_registry-791Vrjtf.mjs.map +1 -0
- package/{tool_registry-DYUYqXvo.js → tool_registry-CKJPze3j.js} +4 -3
- package/tool_registry-CKJPze3j.js.map +1 -0
- package/{turn_runner-DqWHNP80.js → turn_runner-HXImLGIn.js} +7 -7
- package/turn_runner-HXImLGIn.js.map +1 -0
- package/{turn_runner-fg1Wc3dK.mjs → turn_runner-ZyYO-Kti.mjs} +7 -7
- package/turn_runner-ZyYO-Kti.mjs.map +1 -0
- package/turn_runner.cjs +1 -1
- package/turn_runner.mjs +1 -1
- package/types.d.ts +1 -1
- package/common-BT0nfCi9.mjs.map +0 -1
- package/common-Cj8TaQ9U.js.map +0 -1
- package/exceptions-BeWH2FwP.mjs.map +0 -1
- package/exceptions-CitH5wZI.js.map +0 -1
- package/spooled_markdown_artifact-CALSDxIx.js.map +0 -1
- package/spooled_markdown_artifact-Ci5UL7l4.mjs.map +0 -1
- package/tool_call-CV5qVNlb.mjs.map +0 -1
- package/tool_call-Db68hB7y.js.map +0 -1
- package/tool_registry-D1pSSlsd.mjs.map +0 -1
- package/tool_registry-DYUYqXvo.js.map +0 -1
- package/turn_runner-DqWHNP80.js.map +0 -1
- package/turn_runner-fg1Wc3dK.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.cjs","names":["#opts","#client","#ensure","#fields","#materialize","#parseSearchReply","#project","#decode"],"sources":["../../../src/batteries/vector/redis/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/redis\n *\n * One adapter for the whole Redis/Valkey family. The vector engine is RediSearch\n * (`FT.CREATE` / `FT.SEARCH` with a `VECTOR` field over a HASH keyspace); records are\n * stored as Redis hashes keyed `${collection}:${id}`, with the vector packed as a\n * little-endian Float32 buffer. Metadata scalars are stored as TAG/NUMERIC fields so the\n * neutral filter tree compiles to RediSearch query syntax.\n *\n * Works against `redis/redis-stack-server` (bundles RediSearch) and any Redis/Valkey with\n * the RediSearch module loaded.\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_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_FILTER_OPERATOR,\n E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n E_VECTOR_STORE_CONNECTION_FAILED,\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 RedisVectorStoreOptions extends BaseVectorStoreOptions {\n connection?: { url?: string; username?: string; password?: string }\n}\n\nconst getRedisClient = async () => {\n try {\n const mod = await import('redis')\n return mod.createClient\n } catch {\n throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['redis'])\n }\n}\n\n// RediSearch index name + key prefix derived from the logical collection.\nconst indexName = (collection: string): string => `idx:${collection}`\nconst keyPrefix = (collection: string): string => `${collection}:`\nconst keyFor = (collection: string, id: string): string => `${collection}:${id}`\n\n// Pack a number[] into a little-endian Float32 Buffer (RediSearch FLOAT32 vector blob).\nconst packVector = (vector: number[]): Buffer => {\n const buf = Buffer.allocUnsafe(vector.length * 4)\n for (let i = 0; i < vector.length; i++) buf.writeFloatLE(vector[i], i * 4)\n return buf\n}\n\nconst unpackVector = (buf: Buffer): number[] => {\n const out: number[] = []\n for (let i = 0; i < buf.length; i += 4) out.push(buf.readFloatLE(i))\n return out\n}\n\n// RediSearch distance metric for the index. Cosine + L2 are native; 'dot' maps to IP.\nconst metricToRedis = (metric: DistanceMetric): string =>\n metric === 'euclidean' ? 'L2' : metric === 'dot' ? 'IP' : 'COSINE'\n\n// Escape a value for a RediSearch TAG filter (`@field:{value}`). Special chars must be escaped.\nconst escapeTag = (value: string): string =>\n value.replace(/[,.<>{}[\\]\"':;!@#$%^&*()\\-+=~|/\\\\ ]/g, '\\\\$&')\n\n/**\n * Compile the neutral filter tree to a RediSearch query fragment. TAG fields hold string /\n * boolean metadata; NUMERIC fields hold numbers. Returns a fragment to AND with the KNN\n * clause (or to use alone for a filter-scan). Throws on operators RediSearch can't express.\n */\nexport const translateRedisFilter = (filter?: VectorFilter): string => {\n if (!filter) return '*'\n if (isRawFilter(filter)) {\n if (filter.$dialect === 'redis' && typeof filter.$raw === 'string') {\n return filter.$raw\n }\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['redis', String(filter.$dialect)])\n }\n if (isFilterCondition(filter)) {\n const { field, op, value } = filter\n const tag = (v: unknown): string => `@${field}:{${escapeTag(String(v))}}`\n const num = (lo: string, hi: string): string => `@${field}:[${lo} ${hi}]`\n switch (op) {\n case 'eq':\n return typeof value === 'number' ? num(String(value), String(value)) : tag(value)\n case 'ne':\n return typeof value === 'number'\n ? `-${num(String(value), String(value))}`\n : `-${tag(value)}`\n case 'gt':\n return num(`(${String(value)}`, '+inf')\n case 'gte':\n return num(String(value), '+inf')\n case 'lt':\n return num('-inf', `(${String(value)}`)\n case 'lte':\n return num('-inf', String(value))\n case 'in': {\n if (!Array.isArray(value) || value.length === 0) return '@__never:{__never}'\n return `@${field}:{${value.map((v) => escapeTag(String(v))).join('|')}}`\n }\n case 'nin': {\n if (!Array.isArray(value) || value.length === 0) return '*'\n return `-@${field}:{${value.map((v) => escapeTag(String(v))).join('|')}}`\n }\n case 'exists':\n return `@${field}:*`\n default:\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['redis', op])\n }\n }\n if (isFilterGroup(filter)) {\n const { and, or, not } = filter\n if (and) {\n const parts = and.map(translateRedisFilter).filter((p) => p !== '*')\n return parts.length === 0 ? '*' : `(${parts.join(' ')})`\n }\n if (or) {\n const parts = or.map(translateRedisFilter).filter((p) => p !== '*')\n return parts.length === 0 ? '*' : `(${parts.join(' | ')})`\n }\n if (not) {\n const inner = translateRedisFilter(not)\n return inner === '*' ? '*' : `-${inner}`\n }\n return '*'\n }\n return '*'\n}\n\nexport class RedisVectorStore extends BaseVectorStore {\n readonly capabilities: VectorStoreCapabilities = {\n transactions: false,\n namedVectors: false,\n rename: false,\n rawSql: false,\n builtInEncoding: false,\n // RediSearch indexes synchronously on HSET; a write is visible on resolve. No-op option.\n consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n }\n #client: any | null = null\n // Per-collection declared metadata fields, so FT.CREATE can declare TAG/NUMERIC schema.\n #fields: Map<string, CollectionSpec['fields']> = new Map()\n\n get #opts(): RedisVectorStoreOptions {\n return this.options as RedisVectorStoreOptions\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 createClient = await getRedisClient()\n const c = this.#opts.connection || {}\n try {\n this.#client = createClient({\n url: c.url ?? 'redis://localhost:6379',\n username: c.username,\n password: c.password,\n })\n await this.#client.connect()\n } catch (err) {\n throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n }\n }\n\n async close(): Promise<void> {\n if (this.#client) {\n try {\n await this.#client.quit()\n } catch {\n // ignore quit errors on teardown\n }\n this.#client = null\n }\n }\n\n async #ensure(): Promise<any> {\n if (!this.#client) await this.connect()\n return this.#client!\n }\n\n async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n const client = await this.#ensure()\n this.#fields.set(spec.collection, spec.fields)\n if (ifNotExists && (await this.hasCollection(spec.collection))) return\n const dim = spec.vector.dimensions\n const distance = metricToRedis(spec.vector.metric)\n // Build the FT.CREATE schema: the vector field + a TAG/NUMERIC field per declared payload\n // column. Declared fields are advisory; undeclared metadata is still stored on the hash\n // (just not independently filterable).\n const schema: string[] = [\n '__vector',\n 'VECTOR',\n 'FLAT',\n '6',\n 'TYPE',\n 'FLOAT32',\n 'DIM',\n String(dim),\n 'DISTANCE_METRIC',\n distance,\n ]\n for (const f of spec.fields) {\n schema.push(f.name)\n schema.push(f.type === 'integer' || f.type === 'number' ? 'NUMERIC' : 'TAG')\n }\n try {\n await client.sendCommand([\n 'FT.CREATE',\n indexName(spec.collection),\n 'ON',\n 'HASH',\n 'PREFIX',\n '1',\n keyPrefix(spec.collection),\n 'SCHEMA',\n ...schema,\n ])\n } catch (err) {\n const msg = String(err)\n if (msg.includes('Index already exists')) return\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', msg])\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 // DD drops the indexed documents too.\n await client.sendCommand(['FT.DROPINDEX', indexName(collection), 'DD'])\n } catch (err) {\n const msg = String(err)\n if (ifExists && msg.includes('Unknown')) 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 await client.sendCommand(['FT.INFO', indexName(collection)])\n return true\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', 'redis'])\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\n try {\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 // Hash fields: the vector blob, the document, and each metadata scalar (stringified\n // for TAG, numeric kept as-is). __id/__document are reserved internal fields.\n const blob = packVector(vector)\n const entries: Record<string, string | Buffer> = {\n // Raw FLOAT32 blob for RediSearch to index on...\n __vector: blob,\n // ...plus a base64 copy so the vector survives a plain (string) hGetAll read-back\n // (node-redis v6's buffer-mode read API is version-fragile; base64 is portable).\n __vecb64: blob.toString('base64'),\n __id: r.id,\n }\n if (r.document !== undefined) entries.__document = r.document\n if (r.metadata) {\n for (const [k, v] of Object.entries(r.metadata)) {\n if (v === null || v === undefined) continue\n entries[k] = typeof v === 'object' ? JSON.stringify(v) : String(v)\n }\n }\n await client.hSet(keyFor(plan.collection, r.id), entries)\n }\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 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 const raw = await client.hGetAll(keyFor(plan.collection, plan.near.id))\n const b64 = raw?.__vecb64\n if (!b64) {\n throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n }\n queryVector = unpackVector(Buffer.from(String(b64), 'base64'))\n }\n }\n\n try {\n if (queryVector) {\n const filterFrag = translateRedisFilter(plan.filter)\n const k = plan.topK + (plan.offset ?? 0)\n const query = `(${filterFrag})=>[KNN ${k} @__vector $BLOB AS __score]`\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n query,\n 'PARAMS',\n '2',\n 'BLOB',\n packVector(queryVector),\n 'SORTBY',\n '__score',\n 'DIALECT',\n '2',\n 'LIMIT',\n String(plan.offset ?? 0),\n String(plan.topK),\n 'RETURN',\n '1',\n '__score',\n ])\n return await this.#materialize(client, reply, plan, metric, true)\n } else {\n // Filter-scan: FT.SEARCH with the filter fragment, no KNN.\n const filterFrag = translateRedisFilter(plan.filter)\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n filterFrag,\n 'DIALECT',\n '2',\n 'LIMIT',\n String(plan.offset ?? 0),\n String(plan.topK),\n 'NOCONTENT',\n ])\n return await this.#materialize(client, reply, plan, metric, false)\n }\n } catch (err) {\n throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n }\n }\n\n // Parse a node-redis v6 FT.SEARCH reply (structured object OR legacy flat array) into\n // [{ key, score? }] pairs. Score is read from extra_attributes.__score on KNN searches.\n #parseSearchReply(reply: any): Array<{ key: string; score?: number }> {\n // node-redis v6 returns { total_results, results: [{ id, extra_attributes }] }\n if (reply && typeof reply === 'object' && Array.isArray(reply.results)) {\n return reply.results.map((r: any) => ({\n key: String(r.id),\n score:\n r.extra_attributes && r.extra_attributes.__score !== undefined\n ? Number(r.extra_attributes.__score)\n : undefined,\n }))\n }\n // Legacy flat array reply: [total, key, key, ...]\n if (Array.isArray(reply)) {\n return reply.filter((_: unknown, i: number) => i > 0).map((k: any) => ({ key: String(k) }))\n }\n return []\n }\n\n // Parse the FT.SEARCH reply for keys (+ KNN score), then re-fetch each hash as buffers to\n // project. Re-fetching keeps the vector blob intact (RediSearch's per-field reply mangles it).\n async #materialize(\n client: any,\n reply: any,\n plan: SearchPlan,\n metric: string,\n isKnn: boolean\n ): Promise<VectorMatch[]> {\n const hits = this.#parseSearchReply(reply)\n const out: VectorMatch[] = []\n for (const hit of hits) {\n const raw = await client.hGetAll(hit.key)\n if (!raw) continue\n out.push(this.#project(raw, plan, metric, isKnn, hit.score))\n }\n return out\n }\n\n #decode(buf: unknown): string | undefined {\n if (buf === undefined || buf === null) return undefined\n return Buffer.isBuffer(buf) ? buf.toString('utf8') : String(buf)\n }\n\n #project(\n raw: Record<string, unknown>,\n plan: SearchPlan,\n metric: string,\n isKnn: boolean,\n rawScore?: number\n ): VectorMatch {\n const proj = plan.projection\n const out: VectorMatch = {}\n if (proj.id) out.id = this.#decode(raw.__id)\n if (proj.vector && raw.__vecb64) {\n out.vector = unpackVector(Buffer.from(String(this.#decode(raw.__vecb64)), 'base64'))\n }\n if (proj.document) out.document = this.#decode(raw.__document)\n if (proj.metadata) {\n const meta: VectorMetadata = {}\n const reserved = new Set(['__vector', '__vecb64', '__id', '__document', '__score'])\n for (const [k, v] of Object.entries(raw)) {\n if (reserved.has(k)) continue\n meta[k] = this.#decode(v) as string\n }\n out.metadata = meta\n }\n if (isKnn && rawScore !== undefined) {\n // RediSearch returns the raw distance for the metric; normalize to [0,1] higher-is-better.\n out.score = normalizeScore(rawScore, metric as DistanceMetric, 'distance')\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 await client.del(plan.ids.map((id) => keyFor(plan.collection, id)))\n } else if (plan.filter) {\n // Resolve ids via a filter-scan, then delete the hashes.\n const filterFrag = translateRedisFilter(plan.filter)\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n filterFrag,\n 'DIALECT',\n '2',\n 'LIMIT',\n '0',\n '10000',\n 'NOCONTENT',\n ])\n const keys = this.#parseSearchReply(reply).map((h) => h.key)\n if (keys.length > 0) await client.del(keys)\n } else {\n // Delete-all: drop every hash under the prefix via the index.\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n '*',\n 'DIALECT',\n '2',\n 'LIMIT',\n '0',\n '10000',\n 'NOCONTENT',\n ])\n const keys = this.#parseSearchReply(reply).map((h) => h.key)\n if (keys.length > 0) await client.del(keys)\n }\n } catch (err) {\n throw new E_VECTOR_STORE_DELETE_FAILED([String(err)])\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"redis.cjs","names":["#opts","#client","#ensure","#fields","#materialize","#parseSearchReply","#project","#decode"],"sources":["../../../src/batteries/vector/redis/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/redis\n *\n * One adapter for the whole Redis/Valkey family. The vector engine is RediSearch\n * (`FT.CREATE` / `FT.SEARCH` with a `VECTOR` field over a HASH keyspace); records are\n * stored as Redis hashes keyed `${collection}:${id}`, with the vector packed as a\n * little-endian Float32 buffer. Metadata scalars are stored as TAG/NUMERIC fields so the\n * neutral filter tree compiles to RediSearch query syntax.\n *\n * Works against `redis/redis-stack-server` (bundles RediSearch) and any Redis/Valkey with\n * the RediSearch module loaded.\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_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_FILTER_OPERATOR,\n E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n E_VECTOR_STORE_CONNECTION_FAILED,\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 RedisVectorStoreOptions extends BaseVectorStoreOptions {\n /** Connection and authentication parameters for the backend. */\n connection?: { url?: string; username?: string; password?: string }\n}\n\nconst getRedisClient = async () => {\n try {\n const mod = await import('redis')\n return mod.createClient\n } catch {\n throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['redis'])\n }\n}\n\n// RediSearch index name + key prefix derived from the logical collection.\nconst indexName = (collection: string): string => `idx:${collection}`\nconst keyPrefix = (collection: string): string => `${collection}:`\nconst keyFor = (collection: string, id: string): string => `${collection}:${id}`\n\n// Pack a number[] into a little-endian Float32 Buffer (RediSearch FLOAT32 vector blob).\nconst packVector = (vector: number[]): Buffer => {\n const buf = Buffer.allocUnsafe(vector.length * 4)\n for (let i = 0; i < vector.length; i++) buf.writeFloatLE(vector[i], i * 4)\n return buf\n}\n\nconst unpackVector = (buf: Buffer): number[] => {\n const out: number[] = []\n for (let i = 0; i < buf.length; i += 4) out.push(buf.readFloatLE(i))\n return out\n}\n\n// RediSearch distance metric for the index. Cosine + L2 are native; 'dot' maps to IP.\nconst metricToRedis = (metric: DistanceMetric): string =>\n metric === 'euclidean' ? 'L2' : metric === 'dot' ? 'IP' : 'COSINE'\n\n// Escape a value for a RediSearch TAG filter (`@field:{value}`). Special chars must be escaped.\nconst escapeTag = (value: string): string =>\n value.replace(/[,.<>{}[\\]\"':;!@#$%^&*()\\-+=~|/\\\\ ]/g, '\\\\$&')\n\n/**\n * Compile the neutral filter tree to a RediSearch query fragment. TAG fields hold string /\n * boolean metadata; NUMERIC fields hold numbers. Returns a fragment to AND with the KNN\n * clause (or to use alone for a filter-scan). Throws on operators RediSearch can't express.\n */\nexport const translateRedisFilter = (filter?: VectorFilter): string => {\n if (!filter) return '*'\n if (isRawFilter(filter)) {\n if (filter.$dialect === 'redis' && typeof filter.$raw === 'string') {\n return filter.$raw\n }\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['redis', String(filter.$dialect)])\n }\n if (isFilterCondition(filter)) {\n const { field, op, value } = filter\n const tag = (v: unknown): string => `@${field}:{${escapeTag(String(v))}}`\n const num = (lo: string, hi: string): string => `@${field}:[${lo} ${hi}]`\n switch (op) {\n case 'eq':\n return typeof value === 'number' ? num(String(value), String(value)) : tag(value)\n case 'ne':\n return typeof value === 'number'\n ? `-${num(String(value), String(value))}`\n : `-${tag(value)}`\n case 'gt':\n return num(`(${String(value)}`, '+inf')\n case 'gte':\n return num(String(value), '+inf')\n case 'lt':\n return num('-inf', `(${String(value)}`)\n case 'lte':\n return num('-inf', String(value))\n case 'in': {\n if (!Array.isArray(value) || value.length === 0) return '@__never:{__never}'\n return `@${field}:{${value.map((v) => escapeTag(String(v))).join('|')}}`\n }\n case 'nin': {\n if (!Array.isArray(value) || value.length === 0) return '*'\n return `-@${field}:{${value.map((v) => escapeTag(String(v))).join('|')}}`\n }\n case 'exists':\n return `@${field}:*`\n default:\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['redis', op])\n }\n }\n if (isFilterGroup(filter)) {\n const { and, or, not } = filter\n if (and) {\n const parts = and.map(translateRedisFilter).filter((p) => p !== '*')\n return parts.length === 0 ? '*' : `(${parts.join(' ')})`\n }\n if (or) {\n const parts = or.map(translateRedisFilter).filter((p) => p !== '*')\n return parts.length === 0 ? '*' : `(${parts.join(' | ')})`\n }\n if (not) {\n const inner = translateRedisFilter(not)\n return inner === '*' ? '*' : `-${inner}`\n }\n return '*'\n }\n return '*'\n}\n\nexport class RedisVectorStore extends BaseVectorStore {\n readonly capabilities: VectorStoreCapabilities = {\n transactions: false,\n namedVectors: false,\n rename: false,\n rawSql: false,\n builtInEncoding: false,\n // RediSearch indexes synchronously on HSET; a write is visible on resolve. No-op option.\n consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n }\n #client: any | null = null\n // Per-collection declared metadata fields, so FT.CREATE can declare TAG/NUMERIC schema.\n #fields: Map<string, CollectionSpec['fields']> = new Map()\n\n get #opts(): RedisVectorStoreOptions {\n return this.options as RedisVectorStoreOptions\n }\n\n /** Static availability probe: whether this adapter's runtime driver can load in the current environment. */\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 createClient = await getRedisClient()\n const c = this.#opts.connection || {}\n try {\n this.#client = createClient({\n url: c.url ?? 'redis://localhost:6379',\n username: c.username,\n password: c.password,\n })\n await this.#client.connect()\n } catch (err) {\n throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n }\n }\n\n async close(): Promise<void> {\n if (this.#client) {\n try {\n await this.#client.quit()\n } catch {\n // ignore quit errors on teardown\n }\n this.#client = null\n }\n }\n\n async #ensure(): Promise<any> {\n if (!this.#client) await this.connect()\n return this.#client!\n }\n\n async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n const client = await this.#ensure()\n this.#fields.set(spec.collection, spec.fields)\n if (ifNotExists && (await this.hasCollection(spec.collection))) return\n const dim = spec.vector.dimensions\n const distance = metricToRedis(spec.vector.metric)\n // Build the FT.CREATE schema: the vector field + a TAG/NUMERIC field per declared payload\n // column. Declared fields are advisory; undeclared metadata is still stored on the hash\n // (just not independently filterable).\n const schema: string[] = [\n '__vector',\n 'VECTOR',\n 'FLAT',\n '6',\n 'TYPE',\n 'FLOAT32',\n 'DIM',\n String(dim),\n 'DISTANCE_METRIC',\n distance,\n ]\n for (const f of spec.fields) {\n schema.push(f.name)\n schema.push(f.type === 'integer' || f.type === 'number' ? 'NUMERIC' : 'TAG')\n }\n try {\n await client.sendCommand([\n 'FT.CREATE',\n indexName(spec.collection),\n 'ON',\n 'HASH',\n 'PREFIX',\n '1',\n keyPrefix(spec.collection),\n 'SCHEMA',\n ...schema,\n ])\n } catch (err) {\n const msg = String(err)\n if (msg.includes('Index already exists')) return\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', msg])\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 // DD drops the indexed documents too.\n await client.sendCommand(['FT.DROPINDEX', indexName(collection), 'DD'])\n } catch (err) {\n const msg = String(err)\n if (ifExists && msg.includes('Unknown')) 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 await client.sendCommand(['FT.INFO', indexName(collection)])\n return true\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', 'redis'])\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\n try {\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 // Hash fields: the vector blob, the document, and each metadata scalar (stringified\n // for TAG, numeric kept as-is). __id/__document are reserved internal fields.\n const blob = packVector(vector)\n const entries: Record<string, string | Buffer> = {\n // Raw FLOAT32 blob for RediSearch to index on...\n __vector: blob,\n // ...plus a base64 copy so the vector survives a plain (string) hGetAll read-back\n // (node-redis v6's buffer-mode read API is version-fragile; base64 is portable).\n __vecb64: blob.toString('base64'),\n __id: r.id,\n }\n if (r.document !== undefined) entries.__document = r.document\n if (r.metadata) {\n for (const [k, v] of Object.entries(r.metadata)) {\n if (v === null || v === undefined) continue\n entries[k] = typeof v === 'object' ? JSON.stringify(v) : String(v)\n }\n }\n await client.hSet(keyFor(plan.collection, r.id), entries)\n }\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 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 const raw = await client.hGetAll(keyFor(plan.collection, plan.near.id))\n const b64 = raw?.__vecb64\n if (!b64) {\n throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n }\n queryVector = unpackVector(Buffer.from(String(b64), 'base64'))\n }\n }\n\n try {\n if (queryVector) {\n const filterFrag = translateRedisFilter(plan.filter)\n const k = plan.topK + (plan.offset ?? 0)\n const query = `(${filterFrag})=>[KNN ${k} @__vector $BLOB AS __score]`\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n query,\n 'PARAMS',\n '2',\n 'BLOB',\n packVector(queryVector),\n 'SORTBY',\n '__score',\n 'DIALECT',\n '2',\n 'LIMIT',\n String(plan.offset ?? 0),\n String(plan.topK),\n 'RETURN',\n '1',\n '__score',\n ])\n return await this.#materialize(client, reply, plan, metric, true)\n } else {\n // Filter-scan: FT.SEARCH with the filter fragment, no KNN.\n const filterFrag = translateRedisFilter(plan.filter)\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n filterFrag,\n 'DIALECT',\n '2',\n 'LIMIT',\n String(plan.offset ?? 0),\n String(plan.topK),\n 'NOCONTENT',\n ])\n return await this.#materialize(client, reply, plan, metric, false)\n }\n } catch (err) {\n throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n }\n }\n\n // Parse a node-redis v6 FT.SEARCH reply (structured object OR legacy flat array) into\n // [{ key, score? }] pairs. Score is read from extra_attributes.__score on KNN searches.\n #parseSearchReply(reply: any): Array<{ key: string; score?: number }> {\n // node-redis v6 returns { total_results, results: [{ id, extra_attributes }] }\n if (reply && typeof reply === 'object' && Array.isArray(reply.results)) {\n return reply.results.map((r: any) => ({\n key: String(r.id),\n score:\n r.extra_attributes && r.extra_attributes.__score !== undefined\n ? Number(r.extra_attributes.__score)\n : undefined,\n }))\n }\n // Legacy flat array reply: [total, key, key, ...]\n if (Array.isArray(reply)) {\n return reply.filter((_: unknown, i: number) => i > 0).map((k: any) => ({ key: String(k) }))\n }\n return []\n }\n\n // Parse the FT.SEARCH reply for keys (+ KNN score), then re-fetch each hash as buffers to\n // project. Re-fetching keeps the vector blob intact (RediSearch's per-field reply mangles it).\n async #materialize(\n client: any,\n reply: any,\n plan: SearchPlan,\n metric: string,\n isKnn: boolean\n ): Promise<VectorMatch[]> {\n const hits = this.#parseSearchReply(reply)\n const out: VectorMatch[] = []\n for (const hit of hits) {\n const raw = await client.hGetAll(hit.key)\n if (!raw) continue\n out.push(this.#project(raw, plan, metric, isKnn, hit.score))\n }\n return out\n }\n\n #decode(buf: unknown): string | undefined {\n if (buf === undefined || buf === null) return undefined\n return Buffer.isBuffer(buf) ? buf.toString('utf8') : String(buf)\n }\n\n #project(\n raw: Record<string, unknown>,\n plan: SearchPlan,\n metric: string,\n isKnn: boolean,\n rawScore?: number\n ): VectorMatch {\n const proj = plan.projection\n const out: VectorMatch = {}\n if (proj.id) out.id = this.#decode(raw.__id)\n if (proj.vector && raw.__vecb64) {\n out.vector = unpackVector(Buffer.from(String(this.#decode(raw.__vecb64)), 'base64'))\n }\n if (proj.document) out.document = this.#decode(raw.__document)\n if (proj.metadata) {\n const meta: VectorMetadata = {}\n const reserved = new Set(['__vector', '__vecb64', '__id', '__document', '__score'])\n for (const [k, v] of Object.entries(raw)) {\n if (reserved.has(k)) continue\n meta[k] = this.#decode(v) as string\n }\n out.metadata = meta\n }\n if (isKnn && rawScore !== undefined) {\n // RediSearch returns the raw distance for the metric; normalize to [0,1] higher-is-better.\n out.score = normalizeScore(rawScore, metric as DistanceMetric, 'distance')\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 await client.del(plan.ids.map((id) => keyFor(plan.collection, id)))\n } else if (plan.filter) {\n // Resolve ids via a filter-scan, then delete the hashes.\n const filterFrag = translateRedisFilter(plan.filter)\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n filterFrag,\n 'DIALECT',\n '2',\n 'LIMIT',\n '0',\n '10000',\n 'NOCONTENT',\n ])\n const keys = this.#parseSearchReply(reply).map((h) => h.key)\n if (keys.length > 0) await client.del(keys)\n } else {\n // Delete-all: drop every hash under the prefix via the index.\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n '*',\n 'DIALECT',\n '2',\n 'LIMIT',\n '0',\n '10000',\n 'NOCONTENT',\n ])\n const keys = this.#parseSearchReply(reply).map((h) => h.key)\n if (keys.length > 0) await client.del(keys)\n }\n } catch (err) {\n throw new E_VECTOR_STORE_DELETE_FAILED([String(err)])\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as isInstanceOf } from "../../tool_registry-
|
|
1
|
+
import { s as isInstanceOf } from "../../tool_registry-791Vrjtf.mjs";
|
|
2
2
|
import "../../guards.mjs";
|
|
3
3
|
import { isFilterCondition, isFilterGroup, isRawFilter } from "./filters.mjs";
|
|
4
4
|
import { normalizeScore } from "./helpers.mjs";
|
|
@@ -108,6 +108,7 @@ var RedisVectorStore = class extends BaseVectorStore {
|
|
|
108
108
|
get #opts() {
|
|
109
109
|
return this.options;
|
|
110
110
|
}
|
|
111
|
+
/** Static availability probe: whether this adapter's runtime driver can load in the current environment. */
|
|
111
112
|
static isAvailable() {
|
|
112
113
|
return typeof process !== "undefined";
|
|
113
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.mjs","names":["#opts","#client","#ensure","#fields","#materialize","#parseSearchReply","#project","#decode"],"sources":["../../../src/batteries/vector/redis/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/redis\n *\n * One adapter for the whole Redis/Valkey family. The vector engine is RediSearch\n * (`FT.CREATE` / `FT.SEARCH` with a `VECTOR` field over a HASH keyspace); records are\n * stored as Redis hashes keyed `${collection}:${id}`, with the vector packed as a\n * little-endian Float32 buffer. Metadata scalars are stored as TAG/NUMERIC fields so the\n * neutral filter tree compiles to RediSearch query syntax.\n *\n * Works against `redis/redis-stack-server` (bundles RediSearch) and any Redis/Valkey with\n * the RediSearch module loaded.\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_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_FILTER_OPERATOR,\n E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n E_VECTOR_STORE_CONNECTION_FAILED,\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 RedisVectorStoreOptions extends BaseVectorStoreOptions {\n connection?: { url?: string; username?: string; password?: string }\n}\n\nconst getRedisClient = async () => {\n try {\n const mod = await import('redis')\n return mod.createClient\n } catch {\n throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['redis'])\n }\n}\n\n// RediSearch index name + key prefix derived from the logical collection.\nconst indexName = (collection: string): string => `idx:${collection}`\nconst keyPrefix = (collection: string): string => `${collection}:`\nconst keyFor = (collection: string, id: string): string => `${collection}:${id}`\n\n// Pack a number[] into a little-endian Float32 Buffer (RediSearch FLOAT32 vector blob).\nconst packVector = (vector: number[]): Buffer => {\n const buf = Buffer.allocUnsafe(vector.length * 4)\n for (let i = 0; i < vector.length; i++) buf.writeFloatLE(vector[i], i * 4)\n return buf\n}\n\nconst unpackVector = (buf: Buffer): number[] => {\n const out: number[] = []\n for (let i = 0; i < buf.length; i += 4) out.push(buf.readFloatLE(i))\n return out\n}\n\n// RediSearch distance metric for the index. Cosine + L2 are native; 'dot' maps to IP.\nconst metricToRedis = (metric: DistanceMetric): string =>\n metric === 'euclidean' ? 'L2' : metric === 'dot' ? 'IP' : 'COSINE'\n\n// Escape a value for a RediSearch TAG filter (`@field:{value}`). Special chars must be escaped.\nconst escapeTag = (value: string): string =>\n value.replace(/[,.<>{}[\\]\"':;!@#$%^&*()\\-+=~|/\\\\ ]/g, '\\\\$&')\n\n/**\n * Compile the neutral filter tree to a RediSearch query fragment. TAG fields hold string /\n * boolean metadata; NUMERIC fields hold numbers. Returns a fragment to AND with the KNN\n * clause (or to use alone for a filter-scan). Throws on operators RediSearch can't express.\n */\nexport const translateRedisFilter = (filter?: VectorFilter): string => {\n if (!filter) return '*'\n if (isRawFilter(filter)) {\n if (filter.$dialect === 'redis' && typeof filter.$raw === 'string') {\n return filter.$raw\n }\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['redis', String(filter.$dialect)])\n }\n if (isFilterCondition(filter)) {\n const { field, op, value } = filter\n const tag = (v: unknown): string => `@${field}:{${escapeTag(String(v))}}`\n const num = (lo: string, hi: string): string => `@${field}:[${lo} ${hi}]`\n switch (op) {\n case 'eq':\n return typeof value === 'number' ? num(String(value), String(value)) : tag(value)\n case 'ne':\n return typeof value === 'number'\n ? `-${num(String(value), String(value))}`\n : `-${tag(value)}`\n case 'gt':\n return num(`(${String(value)}`, '+inf')\n case 'gte':\n return num(String(value), '+inf')\n case 'lt':\n return num('-inf', `(${String(value)}`)\n case 'lte':\n return num('-inf', String(value))\n case 'in': {\n if (!Array.isArray(value) || value.length === 0) return '@__never:{__never}'\n return `@${field}:{${value.map((v) => escapeTag(String(v))).join('|')}}`\n }\n case 'nin': {\n if (!Array.isArray(value) || value.length === 0) return '*'\n return `-@${field}:{${value.map((v) => escapeTag(String(v))).join('|')}}`\n }\n case 'exists':\n return `@${field}:*`\n default:\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['redis', op])\n }\n }\n if (isFilterGroup(filter)) {\n const { and, or, not } = filter\n if (and) {\n const parts = and.map(translateRedisFilter).filter((p) => p !== '*')\n return parts.length === 0 ? '*' : `(${parts.join(' ')})`\n }\n if (or) {\n const parts = or.map(translateRedisFilter).filter((p) => p !== '*')\n return parts.length === 0 ? '*' : `(${parts.join(' | ')})`\n }\n if (not) {\n const inner = translateRedisFilter(not)\n return inner === '*' ? '*' : `-${inner}`\n }\n return '*'\n }\n return '*'\n}\n\nexport class RedisVectorStore extends BaseVectorStore {\n readonly capabilities: VectorStoreCapabilities = {\n transactions: false,\n namedVectors: false,\n rename: false,\n rawSql: false,\n builtInEncoding: false,\n // RediSearch indexes synchronously on HSET; a write is visible on resolve. No-op option.\n consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n }\n #client: any | null = null\n // Per-collection declared metadata fields, so FT.CREATE can declare TAG/NUMERIC schema.\n #fields: Map<string, CollectionSpec['fields']> = new Map()\n\n get #opts(): RedisVectorStoreOptions {\n return this.options as RedisVectorStoreOptions\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 createClient = await getRedisClient()\n const c = this.#opts.connection || {}\n try {\n this.#client = createClient({\n url: c.url ?? 'redis://localhost:6379',\n username: c.username,\n password: c.password,\n })\n await this.#client.connect()\n } catch (err) {\n throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n }\n }\n\n async close(): Promise<void> {\n if (this.#client) {\n try {\n await this.#client.quit()\n } catch {\n // ignore quit errors on teardown\n }\n this.#client = null\n }\n }\n\n async #ensure(): Promise<any> {\n if (!this.#client) await this.connect()\n return this.#client!\n }\n\n async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n const client = await this.#ensure()\n this.#fields.set(spec.collection, spec.fields)\n if (ifNotExists && (await this.hasCollection(spec.collection))) return\n const dim = spec.vector.dimensions\n const distance = metricToRedis(spec.vector.metric)\n // Build the FT.CREATE schema: the vector field + a TAG/NUMERIC field per declared payload\n // column. Declared fields are advisory; undeclared metadata is still stored on the hash\n // (just not independently filterable).\n const schema: string[] = [\n '__vector',\n 'VECTOR',\n 'FLAT',\n '6',\n 'TYPE',\n 'FLOAT32',\n 'DIM',\n String(dim),\n 'DISTANCE_METRIC',\n distance,\n ]\n for (const f of spec.fields) {\n schema.push(f.name)\n schema.push(f.type === 'integer' || f.type === 'number' ? 'NUMERIC' : 'TAG')\n }\n try {\n await client.sendCommand([\n 'FT.CREATE',\n indexName(spec.collection),\n 'ON',\n 'HASH',\n 'PREFIX',\n '1',\n keyPrefix(spec.collection),\n 'SCHEMA',\n ...schema,\n ])\n } catch (err) {\n const msg = String(err)\n if (msg.includes('Index already exists')) return\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', msg])\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 // DD drops the indexed documents too.\n await client.sendCommand(['FT.DROPINDEX', indexName(collection), 'DD'])\n } catch (err) {\n const msg = String(err)\n if (ifExists && msg.includes('Unknown')) 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 await client.sendCommand(['FT.INFO', indexName(collection)])\n return true\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', 'redis'])\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\n try {\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 // Hash fields: the vector blob, the document, and each metadata scalar (stringified\n // for TAG, numeric kept as-is). __id/__document are reserved internal fields.\n const blob = packVector(vector)\n const entries: Record<string, string | Buffer> = {\n // Raw FLOAT32 blob for RediSearch to index on...\n __vector: blob,\n // ...plus a base64 copy so the vector survives a plain (string) hGetAll read-back\n // (node-redis v6's buffer-mode read API is version-fragile; base64 is portable).\n __vecb64: blob.toString('base64'),\n __id: r.id,\n }\n if (r.document !== undefined) entries.__document = r.document\n if (r.metadata) {\n for (const [k, v] of Object.entries(r.metadata)) {\n if (v === null || v === undefined) continue\n entries[k] = typeof v === 'object' ? JSON.stringify(v) : String(v)\n }\n }\n await client.hSet(keyFor(plan.collection, r.id), entries)\n }\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 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 const raw = await client.hGetAll(keyFor(plan.collection, plan.near.id))\n const b64 = raw?.__vecb64\n if (!b64) {\n throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n }\n queryVector = unpackVector(Buffer.from(String(b64), 'base64'))\n }\n }\n\n try {\n if (queryVector) {\n const filterFrag = translateRedisFilter(plan.filter)\n const k = plan.topK + (plan.offset ?? 0)\n const query = `(${filterFrag})=>[KNN ${k} @__vector $BLOB AS __score]`\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n query,\n 'PARAMS',\n '2',\n 'BLOB',\n packVector(queryVector),\n 'SORTBY',\n '__score',\n 'DIALECT',\n '2',\n 'LIMIT',\n String(plan.offset ?? 0),\n String(plan.topK),\n 'RETURN',\n '1',\n '__score',\n ])\n return await this.#materialize(client, reply, plan, metric, true)\n } else {\n // Filter-scan: FT.SEARCH with the filter fragment, no KNN.\n const filterFrag = translateRedisFilter(plan.filter)\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n filterFrag,\n 'DIALECT',\n '2',\n 'LIMIT',\n String(plan.offset ?? 0),\n String(plan.topK),\n 'NOCONTENT',\n ])\n return await this.#materialize(client, reply, plan, metric, false)\n }\n } catch (err) {\n throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n }\n }\n\n // Parse a node-redis v6 FT.SEARCH reply (structured object OR legacy flat array) into\n // [{ key, score? }] pairs. Score is read from extra_attributes.__score on KNN searches.\n #parseSearchReply(reply: any): Array<{ key: string; score?: number }> {\n // node-redis v6 returns { total_results, results: [{ id, extra_attributes }] }\n if (reply && typeof reply === 'object' && Array.isArray(reply.results)) {\n return reply.results.map((r: any) => ({\n key: String(r.id),\n score:\n r.extra_attributes && r.extra_attributes.__score !== undefined\n ? Number(r.extra_attributes.__score)\n : undefined,\n }))\n }\n // Legacy flat array reply: [total, key, key, ...]\n if (Array.isArray(reply)) {\n return reply.filter((_: unknown, i: number) => i > 0).map((k: any) => ({ key: String(k) }))\n }\n return []\n }\n\n // Parse the FT.SEARCH reply for keys (+ KNN score), then re-fetch each hash as buffers to\n // project. Re-fetching keeps the vector blob intact (RediSearch's per-field reply mangles it).\n async #materialize(\n client: any,\n reply: any,\n plan: SearchPlan,\n metric: string,\n isKnn: boolean\n ): Promise<VectorMatch[]> {\n const hits = this.#parseSearchReply(reply)\n const out: VectorMatch[] = []\n for (const hit of hits) {\n const raw = await client.hGetAll(hit.key)\n if (!raw) continue\n out.push(this.#project(raw, plan, metric, isKnn, hit.score))\n }\n return out\n }\n\n #decode(buf: unknown): string | undefined {\n if (buf === undefined || buf === null) return undefined\n return Buffer.isBuffer(buf) ? buf.toString('utf8') : String(buf)\n }\n\n #project(\n raw: Record<string, unknown>,\n plan: SearchPlan,\n metric: string,\n isKnn: boolean,\n rawScore?: number\n ): VectorMatch {\n const proj = plan.projection\n const out: VectorMatch = {}\n if (proj.id) out.id = this.#decode(raw.__id)\n if (proj.vector && raw.__vecb64) {\n out.vector = unpackVector(Buffer.from(String(this.#decode(raw.__vecb64)), 'base64'))\n }\n if (proj.document) out.document = this.#decode(raw.__document)\n if (proj.metadata) {\n const meta: VectorMetadata = {}\n const reserved = new Set(['__vector', '__vecb64', '__id', '__document', '__score'])\n for (const [k, v] of Object.entries(raw)) {\n if (reserved.has(k)) continue\n meta[k] = this.#decode(v) as string\n }\n out.metadata = meta\n }\n if (isKnn && rawScore !== undefined) {\n // RediSearch returns the raw distance for the metric; normalize to [0,1] higher-is-better.\n out.score = normalizeScore(rawScore, metric as DistanceMetric, 'distance')\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 await client.del(plan.ids.map((id) => keyFor(plan.collection, id)))\n } else if (plan.filter) {\n // Resolve ids via a filter-scan, then delete the hashes.\n const filterFrag = translateRedisFilter(plan.filter)\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n filterFrag,\n 'DIALECT',\n '2',\n 'LIMIT',\n '0',\n '10000',\n 'NOCONTENT',\n ])\n const keys = this.#parseSearchReply(reply).map((h) => h.key)\n if (keys.length > 0) await client.del(keys)\n } else {\n // Delete-all: drop every hash under the prefix via the index.\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n '*',\n 'DIALECT',\n '2',\n 'LIMIT',\n '0',\n '10000',\n 'NOCONTENT',\n ])\n const keys = this.#parseSearchReply(reply).map((h) => h.key)\n if (keys.length > 0) await client.del(keys)\n }\n } catch (err) {\n throw new E_VECTOR_STORE_DELETE_FAILED([String(err)])\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"redis.mjs","names":["#opts","#client","#ensure","#fields","#materialize","#parseSearchReply","#project","#decode"],"sources":["../../../src/batteries/vector/redis/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/redis\n *\n * One adapter for the whole Redis/Valkey family. The vector engine is RediSearch\n * (`FT.CREATE` / `FT.SEARCH` with a `VECTOR` field over a HASH keyspace); records are\n * stored as Redis hashes keyed `${collection}:${id}`, with the vector packed as a\n * little-endian Float32 buffer. Metadata scalars are stored as TAG/NUMERIC fields so the\n * neutral filter tree compiles to RediSearch query syntax.\n *\n * Works against `redis/redis-stack-server` (bundles RediSearch) and any Redis/Valkey with\n * the RediSearch module loaded.\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_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_FILTER_OPERATOR,\n E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n E_VECTOR_STORE_CONNECTION_FAILED,\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 RedisVectorStoreOptions extends BaseVectorStoreOptions {\n /** Connection and authentication parameters for the backend. */\n connection?: { url?: string; username?: string; password?: string }\n}\n\nconst getRedisClient = async () => {\n try {\n const mod = await import('redis')\n return mod.createClient\n } catch {\n throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['redis'])\n }\n}\n\n// RediSearch index name + key prefix derived from the logical collection.\nconst indexName = (collection: string): string => `idx:${collection}`\nconst keyPrefix = (collection: string): string => `${collection}:`\nconst keyFor = (collection: string, id: string): string => `${collection}:${id}`\n\n// Pack a number[] into a little-endian Float32 Buffer (RediSearch FLOAT32 vector blob).\nconst packVector = (vector: number[]): Buffer => {\n const buf = Buffer.allocUnsafe(vector.length * 4)\n for (let i = 0; i < vector.length; i++) buf.writeFloatLE(vector[i], i * 4)\n return buf\n}\n\nconst unpackVector = (buf: Buffer): number[] => {\n const out: number[] = []\n for (let i = 0; i < buf.length; i += 4) out.push(buf.readFloatLE(i))\n return out\n}\n\n// RediSearch distance metric for the index. Cosine + L2 are native; 'dot' maps to IP.\nconst metricToRedis = (metric: DistanceMetric): string =>\n metric === 'euclidean' ? 'L2' : metric === 'dot' ? 'IP' : 'COSINE'\n\n// Escape a value for a RediSearch TAG filter (`@field:{value}`). Special chars must be escaped.\nconst escapeTag = (value: string): string =>\n value.replace(/[,.<>{}[\\]\"':;!@#$%^&*()\\-+=~|/\\\\ ]/g, '\\\\$&')\n\n/**\n * Compile the neutral filter tree to a RediSearch query fragment. TAG fields hold string /\n * boolean metadata; NUMERIC fields hold numbers. Returns a fragment to AND with the KNN\n * clause (or to use alone for a filter-scan). Throws on operators RediSearch can't express.\n */\nexport const translateRedisFilter = (filter?: VectorFilter): string => {\n if (!filter) return '*'\n if (isRawFilter(filter)) {\n if (filter.$dialect === 'redis' && typeof filter.$raw === 'string') {\n return filter.$raw\n }\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['redis', String(filter.$dialect)])\n }\n if (isFilterCondition(filter)) {\n const { field, op, value } = filter\n const tag = (v: unknown): string => `@${field}:{${escapeTag(String(v))}}`\n const num = (lo: string, hi: string): string => `@${field}:[${lo} ${hi}]`\n switch (op) {\n case 'eq':\n return typeof value === 'number' ? num(String(value), String(value)) : tag(value)\n case 'ne':\n return typeof value === 'number'\n ? `-${num(String(value), String(value))}`\n : `-${tag(value)}`\n case 'gt':\n return num(`(${String(value)}`, '+inf')\n case 'gte':\n return num(String(value), '+inf')\n case 'lt':\n return num('-inf', `(${String(value)}`)\n case 'lte':\n return num('-inf', String(value))\n case 'in': {\n if (!Array.isArray(value) || value.length === 0) return '@__never:{__never}'\n return `@${field}:{${value.map((v) => escapeTag(String(v))).join('|')}}`\n }\n case 'nin': {\n if (!Array.isArray(value) || value.length === 0) return '*'\n return `-@${field}:{${value.map((v) => escapeTag(String(v))).join('|')}}`\n }\n case 'exists':\n return `@${field}:*`\n default:\n throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['redis', op])\n }\n }\n if (isFilterGroup(filter)) {\n const { and, or, not } = filter\n if (and) {\n const parts = and.map(translateRedisFilter).filter((p) => p !== '*')\n return parts.length === 0 ? '*' : `(${parts.join(' ')})`\n }\n if (or) {\n const parts = or.map(translateRedisFilter).filter((p) => p !== '*')\n return parts.length === 0 ? '*' : `(${parts.join(' | ')})`\n }\n if (not) {\n const inner = translateRedisFilter(not)\n return inner === '*' ? '*' : `-${inner}`\n }\n return '*'\n }\n return '*'\n}\n\nexport class RedisVectorStore extends BaseVectorStore {\n readonly capabilities: VectorStoreCapabilities = {\n transactions: false,\n namedVectors: false,\n rename: false,\n rawSql: false,\n builtInEncoding: false,\n // RediSearch indexes synchronously on HSET; a write is visible on resolve. No-op option.\n consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n }\n #client: any | null = null\n // Per-collection declared metadata fields, so FT.CREATE can declare TAG/NUMERIC schema.\n #fields: Map<string, CollectionSpec['fields']> = new Map()\n\n get #opts(): RedisVectorStoreOptions {\n return this.options as RedisVectorStoreOptions\n }\n\n /** Static availability probe: whether this adapter's runtime driver can load in the current environment. */\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 createClient = await getRedisClient()\n const c = this.#opts.connection || {}\n try {\n this.#client = createClient({\n url: c.url ?? 'redis://localhost:6379',\n username: c.username,\n password: c.password,\n })\n await this.#client.connect()\n } catch (err) {\n throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n }\n }\n\n async close(): Promise<void> {\n if (this.#client) {\n try {\n await this.#client.quit()\n } catch {\n // ignore quit errors on teardown\n }\n this.#client = null\n }\n }\n\n async #ensure(): Promise<any> {\n if (!this.#client) await this.connect()\n return this.#client!\n }\n\n async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n const client = await this.#ensure()\n this.#fields.set(spec.collection, spec.fields)\n if (ifNotExists && (await this.hasCollection(spec.collection))) return\n const dim = spec.vector.dimensions\n const distance = metricToRedis(spec.vector.metric)\n // Build the FT.CREATE schema: the vector field + a TAG/NUMERIC field per declared payload\n // column. Declared fields are advisory; undeclared metadata is still stored on the hash\n // (just not independently filterable).\n const schema: string[] = [\n '__vector',\n 'VECTOR',\n 'FLAT',\n '6',\n 'TYPE',\n 'FLOAT32',\n 'DIM',\n String(dim),\n 'DISTANCE_METRIC',\n distance,\n ]\n for (const f of spec.fields) {\n schema.push(f.name)\n schema.push(f.type === 'integer' || f.type === 'number' ? 'NUMERIC' : 'TAG')\n }\n try {\n await client.sendCommand([\n 'FT.CREATE',\n indexName(spec.collection),\n 'ON',\n 'HASH',\n 'PREFIX',\n '1',\n keyPrefix(spec.collection),\n 'SCHEMA',\n ...schema,\n ])\n } catch (err) {\n const msg = String(err)\n if (msg.includes('Index already exists')) return\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', msg])\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 // DD drops the indexed documents too.\n await client.sendCommand(['FT.DROPINDEX', indexName(collection), 'DD'])\n } catch (err) {\n const msg = String(err)\n if (ifExists && msg.includes('Unknown')) 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 await client.sendCommand(['FT.INFO', indexName(collection)])\n return true\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', 'redis'])\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\n try {\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 // Hash fields: the vector blob, the document, and each metadata scalar (stringified\n // for TAG, numeric kept as-is). __id/__document are reserved internal fields.\n const blob = packVector(vector)\n const entries: Record<string, string | Buffer> = {\n // Raw FLOAT32 blob for RediSearch to index on...\n __vector: blob,\n // ...plus a base64 copy so the vector survives a plain (string) hGetAll read-back\n // (node-redis v6's buffer-mode read API is version-fragile; base64 is portable).\n __vecb64: blob.toString('base64'),\n __id: r.id,\n }\n if (r.document !== undefined) entries.__document = r.document\n if (r.metadata) {\n for (const [k, v] of Object.entries(r.metadata)) {\n if (v === null || v === undefined) continue\n entries[k] = typeof v === 'object' ? JSON.stringify(v) : String(v)\n }\n }\n await client.hSet(keyFor(plan.collection, r.id), entries)\n }\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 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 const raw = await client.hGetAll(keyFor(plan.collection, plan.near.id))\n const b64 = raw?.__vecb64\n if (!b64) {\n throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n }\n queryVector = unpackVector(Buffer.from(String(b64), 'base64'))\n }\n }\n\n try {\n if (queryVector) {\n const filterFrag = translateRedisFilter(plan.filter)\n const k = plan.topK + (plan.offset ?? 0)\n const query = `(${filterFrag})=>[KNN ${k} @__vector $BLOB AS __score]`\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n query,\n 'PARAMS',\n '2',\n 'BLOB',\n packVector(queryVector),\n 'SORTBY',\n '__score',\n 'DIALECT',\n '2',\n 'LIMIT',\n String(plan.offset ?? 0),\n String(plan.topK),\n 'RETURN',\n '1',\n '__score',\n ])\n return await this.#materialize(client, reply, plan, metric, true)\n } else {\n // Filter-scan: FT.SEARCH with the filter fragment, no KNN.\n const filterFrag = translateRedisFilter(plan.filter)\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n filterFrag,\n 'DIALECT',\n '2',\n 'LIMIT',\n String(plan.offset ?? 0),\n String(plan.topK),\n 'NOCONTENT',\n ])\n return await this.#materialize(client, reply, plan, metric, false)\n }\n } catch (err) {\n throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n }\n }\n\n // Parse a node-redis v6 FT.SEARCH reply (structured object OR legacy flat array) into\n // [{ key, score? }] pairs. Score is read from extra_attributes.__score on KNN searches.\n #parseSearchReply(reply: any): Array<{ key: string; score?: number }> {\n // node-redis v6 returns { total_results, results: [{ id, extra_attributes }] }\n if (reply && typeof reply === 'object' && Array.isArray(reply.results)) {\n return reply.results.map((r: any) => ({\n key: String(r.id),\n score:\n r.extra_attributes && r.extra_attributes.__score !== undefined\n ? Number(r.extra_attributes.__score)\n : undefined,\n }))\n }\n // Legacy flat array reply: [total, key, key, ...]\n if (Array.isArray(reply)) {\n return reply.filter((_: unknown, i: number) => i > 0).map((k: any) => ({ key: String(k) }))\n }\n return []\n }\n\n // Parse the FT.SEARCH reply for keys (+ KNN score), then re-fetch each hash as buffers to\n // project. Re-fetching keeps the vector blob intact (RediSearch's per-field reply mangles it).\n async #materialize(\n client: any,\n reply: any,\n plan: SearchPlan,\n metric: string,\n isKnn: boolean\n ): Promise<VectorMatch[]> {\n const hits = this.#parseSearchReply(reply)\n const out: VectorMatch[] = []\n for (const hit of hits) {\n const raw = await client.hGetAll(hit.key)\n if (!raw) continue\n out.push(this.#project(raw, plan, metric, isKnn, hit.score))\n }\n return out\n }\n\n #decode(buf: unknown): string | undefined {\n if (buf === undefined || buf === null) return undefined\n return Buffer.isBuffer(buf) ? buf.toString('utf8') : String(buf)\n }\n\n #project(\n raw: Record<string, unknown>,\n plan: SearchPlan,\n metric: string,\n isKnn: boolean,\n rawScore?: number\n ): VectorMatch {\n const proj = plan.projection\n const out: VectorMatch = {}\n if (proj.id) out.id = this.#decode(raw.__id)\n if (proj.vector && raw.__vecb64) {\n out.vector = unpackVector(Buffer.from(String(this.#decode(raw.__vecb64)), 'base64'))\n }\n if (proj.document) out.document = this.#decode(raw.__document)\n if (proj.metadata) {\n const meta: VectorMetadata = {}\n const reserved = new Set(['__vector', '__vecb64', '__id', '__document', '__score'])\n for (const [k, v] of Object.entries(raw)) {\n if (reserved.has(k)) continue\n meta[k] = this.#decode(v) as string\n }\n out.metadata = meta\n }\n if (isKnn && rawScore !== undefined) {\n // RediSearch returns the raw distance for the metric; normalize to [0,1] higher-is-better.\n out.score = normalizeScore(rawScore, metric as DistanceMetric, 'distance')\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 await client.del(plan.ids.map((id) => keyFor(plan.collection, id)))\n } else if (plan.filter) {\n // Resolve ids via a filter-scan, then delete the hashes.\n const filterFrag = translateRedisFilter(plan.filter)\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n filterFrag,\n 'DIALECT',\n '2',\n 'LIMIT',\n '0',\n '10000',\n 'NOCONTENT',\n ])\n const keys = this.#parseSearchReply(reply).map((h) => h.key)\n if (keys.length > 0) await client.del(keys)\n } else {\n // Delete-all: drop every hash under the prefix via the index.\n const reply: any = await client.sendCommand([\n 'FT.SEARCH',\n indexName(plan.collection),\n '*',\n 'DIALECT',\n '2',\n 'LIMIT',\n '0',\n '10000',\n 'NOCONTENT',\n ])\n const keys = this.#parseSearchReply(reply).map((h) => h.key)\n if (keys.length > 0) await client.del(keys)\n }\n } catch (err) {\n throw new E_VECTOR_STORE_DELETE_FAILED([String(err)])\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Ble4zEEl.js");
|
|
3
|
-
const require_common = require("../../common-
|
|
3
|
+
const require_common = require("../../common-DZl3ADJs.js");
|
|
4
4
|
require("../../index.cjs");
|
|
5
5
|
//#region src/batteries/vector/retrievable_glue.ts
|
|
6
6
|
/**
|
|
7
7
|
* @module @nhtio/adk/batteries/vector/retrievable
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* Build the retrievable-lifecycle callbacks (fetch/store/mutate/delete) that bridge a callable
|
|
11
|
+
* vector store to the ADK's retrievable subsystem, applying the supplied query derivation,
|
|
12
|
+
* match-to-retrievable mapping, and trust-tier assignment.
|
|
13
|
+
*
|
|
14
|
+
* @param opts - The store, collection, and behaviour overrides.
|
|
15
|
+
* @returns The four wired {@link VectorRetrievableCallbacks}.
|
|
16
|
+
*/
|
|
9
17
|
var createVectorRetrievableCallbacks = (opts) => {
|
|
10
18
|
const topK = opts.topK ?? 5;
|
|
11
19
|
const tierFor = (m) => typeof opts.trustTier === "function" ? opts.trustTier(m) : opts.trustTier;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retrievable.cjs","names":[],"sources":["../../../src/batteries/vector/retrievable_glue.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/retrievable\n */\n\nimport { Retrievable } from '@nhtio/adk'\nimport type { VectorFilter } from './filters'\nimport type { CallableVectorStore } from './contract'\nimport type { VectorMatch, VectorMetadata } from './types'\nimport type { RawRetrievable, RetrievableTrustTier } from '@nhtio/adk/common'\nimport type {\n TurnContext,\n RetrievableRetrievalFn,\n RetrievableStoreFn,\n RetrievableMutateFn,\n RetrievableDeleteFn,\n} from '@nhtio/adk'\n\nexport interface VectorRetrievableGlueOptions {\n store: CallableVectorStore\n collection: string\n trustTier: RetrievableTrustTier | ((m: VectorMatch) => RetrievableTrustTier)\n topK?: number\n filter?: VectorFilter\n deriveQuery?: (\n ctx: TurnContext\n ) => string | number[] | undefined | Promise<string | number[] | undefined>\n toRetrievable?: (m: VectorMatch) => Omit<RawRetrievable, 'trustTier'>\n}\n\nexport interface VectorRetrievableCallbacks {\n fetchRetrievablesCallback: RetrievableRetrievalFn\n storeRetrievableCallback: RetrievableStoreFn\n mutateRetrievableCallback: RetrievableMutateFn\n deleteRetrievableCallback: RetrievableDeleteFn\n}\n\nexport const createVectorRetrievableCallbacks = (\n opts: VectorRetrievableGlueOptions\n): VectorRetrievableCallbacks => {\n const topK = opts.topK ?? 5\n const tierFor = (m: VectorMatch): RetrievableTrustTier =>\n typeof opts.trustTier === 'function' ? opts.trustTier(m) : opts.trustTier\n\n // default deriveQuery: last user message text, else undefined\n const deriveQuery =\n opts.deriveQuery ??\n (async (ctx: TurnContext) => {\n const msgs = await ctx.fetchMessages()\n for (let i = msgs.length - 1; i >= 0; i--) {\n if (msgs[i].role === 'user') return msgs[i].content?.toString() ?? ''\n }\n return undefined\n })\n\n // default mapping VectorMatch -> RawRetrievable (minus trustTier)\n const toRetrievable =\n opts.toRetrievable ??\n ((m: VectorMatch): Omit<RawRetrievable, 'trustTier'> => {\n const md = (m.metadata ?? {}) as Record<string, unknown>\n const now = new Date()\n return {\n id: m.id ?? String(md.id ?? ''),\n content: m.document ?? String(md.content ?? ''),\n source: typeof md.source === 'string' ? md.source : undefined,\n kind: typeof md.kind === 'string' ? md.kind : undefined,\n score: typeof m.score === 'number' ? m.score : undefined,\n createdAt: (md.createdAt as any) ?? now,\n updatedAt: (md.updatedAt as any) ?? now,\n }\n })\n\n const fetchRetrievablesCallback: RetrievableRetrievalFn = async (ctx) => {\n const q = await deriveQuery(ctx)\n if (q === undefined) return []\n let b = opts.store(opts.collection)\n b = Array.isArray(q) ? b.nearVector(q) : b.nearText(q)\n if (opts.filter) b = b.whereRaw(opts.filter as any)\n const matches = await b.select('id', 'document', 'metadata').limit(topK)\n return matches.map((m) => new Retrievable({ ...toRetrievable(m), trustTier: tierFor(m) }))\n }\n\n const storeRetrievableCallback: RetrievableStoreFn = async (_ctx, r) => {\n const content = await r.contentString()\n const metadata: VectorMetadata = {\n trustTier: r.trustTier,\n createdAt: r.createdAt?.toISO?.() ?? String(r.createdAt),\n updatedAt: r.updatedAt?.toISO?.() ?? String(r.updatedAt),\n }\n if (r.source !== undefined) metadata.source = r.source\n if (r.kind !== undefined) metadata.kind = r.kind\n await opts.store(opts.collection).upsert([{ id: r.id, document: content, metadata }])\n }\n const mutateRetrievableCallback: RetrievableMutateFn = storeRetrievableCallback // upsert == replace\n const deleteRetrievableCallback: RetrievableDeleteFn = async (_ctx, id) => {\n await opts.store(opts.collection).whereIn('id', [id]).delete()\n }\n\n return {\n fetchRetrievablesCallback,\n storeRetrievableCallback,\n mutateRetrievableCallback,\n deleteRetrievableCallback,\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"retrievable.cjs","names":[],"sources":["../../../src/batteries/vector/retrievable_glue.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/retrievable\n */\n\nimport { Retrievable } from '@nhtio/adk'\nimport type { VectorFilter } from './filters'\nimport type { CallableVectorStore } from './contract'\nimport type { VectorMatch, VectorMetadata } from './types'\nimport type { RawRetrievable, RetrievableTrustTier } from '@nhtio/adk/common'\nimport type {\n TurnContext,\n RetrievableRetrievalFn,\n RetrievableStoreFn,\n RetrievableMutateFn,\n RetrievableDeleteFn,\n} from '@nhtio/adk'\n\n/** Configuration for wiring a vector store to the ADK's retrievable lifecycle callbacks. */\nexport interface VectorRetrievableGlueOptions {\n /** The callable vector store the callbacks query and write to. */\n store: CallableVectorStore\n /** Collection the retrievables live in. */\n collection: string\n /** Trust tier for fetched matches — a fixed tier, or a per-match function. */\n trustTier: RetrievableTrustTier | ((m: VectorMatch) => RetrievableTrustTier)\n /** Maximum number of retrievables to fetch per turn (default 5). */\n topK?: number\n /** Optional filter applied to every retrieval query. */\n filter?: VectorFilter\n /** Derives the retrieval query from the turn context; defaults to the last user message. */\n deriveQuery?: (\n ctx: TurnContext\n ) => string | number[] | undefined | Promise<string | number[] | undefined>\n /** Maps a {@link VectorMatch} to a raw retrievable (trust tier applied separately). */\n toRetrievable?: (m: VectorMatch) => Omit<RawRetrievable, 'trustTier'>\n}\n\n/** The four retrievable-lifecycle callbacks produced by {@link createVectorRetrievableCallbacks}. */\nexport interface VectorRetrievableCallbacks {\n /** Fetches retrievables relevant to the current turn. */\n fetchRetrievablesCallback: RetrievableRetrievalFn\n /** Persists a new retrievable into the store. */\n storeRetrievableCallback: RetrievableStoreFn\n /** Replaces an existing retrievable (upsert). */\n mutateRetrievableCallback: RetrievableMutateFn\n /** Deletes a retrievable by id. */\n deleteRetrievableCallback: RetrievableDeleteFn\n}\n\n/**\n * Build the retrievable-lifecycle callbacks (fetch/store/mutate/delete) that bridge a callable\n * vector store to the ADK's retrievable subsystem, applying the supplied query derivation,\n * match-to-retrievable mapping, and trust-tier assignment.\n *\n * @param opts - The store, collection, and behaviour overrides.\n * @returns The four wired {@link VectorRetrievableCallbacks}.\n */\nexport const createVectorRetrievableCallbacks = (\n opts: VectorRetrievableGlueOptions\n): VectorRetrievableCallbacks => {\n const topK = opts.topK ?? 5\n const tierFor = (m: VectorMatch): RetrievableTrustTier =>\n typeof opts.trustTier === 'function' ? opts.trustTier(m) : opts.trustTier\n\n // default deriveQuery: last user message text, else undefined\n const deriveQuery =\n opts.deriveQuery ??\n (async (ctx: TurnContext) => {\n const msgs = await ctx.fetchMessages()\n for (let i = msgs.length - 1; i >= 0; i--) {\n if (msgs[i].role === 'user') return msgs[i].content?.toString() ?? ''\n }\n return undefined\n })\n\n // default mapping VectorMatch -> RawRetrievable (minus trustTier)\n const toRetrievable =\n opts.toRetrievable ??\n ((m: VectorMatch): Omit<RawRetrievable, 'trustTier'> => {\n const md = (m.metadata ?? {}) as Record<string, unknown>\n const now = new Date()\n return {\n id: m.id ?? String(md.id ?? ''),\n content: m.document ?? String(md.content ?? ''),\n source: typeof md.source === 'string' ? md.source : undefined,\n kind: typeof md.kind === 'string' ? md.kind : undefined,\n score: typeof m.score === 'number' ? m.score : undefined,\n createdAt: (md.createdAt as any) ?? now,\n updatedAt: (md.updatedAt as any) ?? now,\n }\n })\n\n const fetchRetrievablesCallback: RetrievableRetrievalFn = async (ctx) => {\n const q = await deriveQuery(ctx)\n if (q === undefined) return []\n let b = opts.store(opts.collection)\n b = Array.isArray(q) ? b.nearVector(q) : b.nearText(q)\n if (opts.filter) b = b.whereRaw(opts.filter as any)\n const matches = await b.select('id', 'document', 'metadata').limit(topK)\n return matches.map((m) => new Retrievable({ ...toRetrievable(m), trustTier: tierFor(m) }))\n }\n\n const storeRetrievableCallback: RetrievableStoreFn = async (_ctx, r) => {\n const content = await r.contentString()\n const metadata: VectorMetadata = {\n trustTier: r.trustTier,\n createdAt: r.createdAt?.toISO?.() ?? String(r.createdAt),\n updatedAt: r.updatedAt?.toISO?.() ?? String(r.updatedAt),\n }\n if (r.source !== undefined) metadata.source = r.source\n if (r.kind !== undefined) metadata.kind = r.kind\n await opts.store(opts.collection).upsert([{ id: r.id, document: content, metadata }])\n }\n const mutateRetrievableCallback: RetrievableMutateFn = storeRetrievableCallback // upsert == replace\n const deleteRetrievableCallback: RetrievableDeleteFn = async (_ctx, id) => {\n await opts.store(opts.collection).whereIn('id', [id]).delete()\n }\n\n return {\n fetchRetrievablesCallback,\n storeRetrievableCallback,\n mutateRetrievableCallback,\n deleteRetrievableCallback,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAyDA,IAAa,oCACX,SAC+B;CAC/B,MAAM,OAAO,KAAK,QAAQ;CAC1B,MAAM,WAAW,MACf,OAAO,KAAK,cAAc,aAAa,KAAK,UAAU,CAAC,IAAI,KAAK;CAGlE,MAAM,cACJ,KAAK,gBACJ,OAAO,QAAqB;EAC3B,MAAM,OAAO,MAAM,IAAI,cAAc;EACrC,KAAK,IAAI,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,KACpC,IAAI,KAAK,GAAG,SAAS,QAAQ,OAAO,KAAK,GAAG,SAAS,SAAS,KAAK;CAGvE;CAGF,MAAM,gBACJ,KAAK,mBACH,MAAsD;EACtD,MAAM,KAAM,EAAE,YAAY,CAAC;EAC3B,MAAM,sBAAM,IAAI,KAAK;EACrB,OAAO;GACL,IAAI,EAAE,MAAM,OAAO,GAAG,MAAM,EAAE;GAC9B,SAAS,EAAE,YAAY,OAAO,GAAG,WAAW,EAAE;GAC9C,QAAQ,OAAO,GAAG,WAAW,WAAW,GAAG,SAAS,KAAA;GACpD,MAAM,OAAO,GAAG,SAAS,WAAW,GAAG,OAAO,KAAA;GAC9C,OAAO,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ,KAAA;GAC/C,WAAY,GAAG,aAAqB;GACpC,WAAY,GAAG,aAAqB;EACtC;CACF;CAEF,MAAM,4BAAoD,OAAO,QAAQ;EACvE,MAAM,IAAI,MAAM,YAAY,GAAG;EAC/B,IAAI,MAAM,KAAA,GAAW,OAAO,CAAC;EAC7B,IAAI,IAAI,KAAK,MAAM,KAAK,UAAU;EAClC,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC;EACrD,IAAI,KAAK,QAAQ,IAAI,EAAE,SAAS,KAAK,MAAa;EAElD,QAAO,MADe,EAAE,OAAO,MAAM,YAAY,UAAU,EAAE,MAAM,IAAI,GACxD,KAAK,MAAM,IAAI,eAAA,YAAY;GAAE,GAAG,cAAc,CAAC;GAAG,WAAW,QAAQ,CAAC;EAAE,CAAC,CAAC;CAC3F;CAEA,MAAM,2BAA+C,OAAO,MAAM,MAAM;EACtE,MAAM,UAAU,MAAM,EAAE,cAAc;EACtC,MAAM,WAA2B;GAC/B,WAAW,EAAE;GACb,WAAW,EAAE,WAAW,QAAQ,KAAK,OAAO,EAAE,SAAS;GACvD,WAAW,EAAE,WAAW,QAAQ,KAAK,OAAO,EAAE,SAAS;EACzD;EACA,IAAI,EAAE,WAAW,KAAA,GAAW,SAAS,SAAS,EAAE;EAChD,IAAI,EAAE,SAAS,KAAA,GAAW,SAAS,OAAO,EAAE;EAC5C,MAAM,KAAK,MAAM,KAAK,UAAU,EAAE,OAAO,CAAC;GAAE,IAAI,EAAE;GAAI,UAAU;GAAS;EAAS,CAAC,CAAC;CACtF;CACA,MAAM,4BAAiD;CACvD,MAAM,4BAAiD,OAAO,MAAM,OAAO;EACzE,MAAM,KAAK,MAAM,KAAK,UAAU,EAAE,QAAQ,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO;CAC/D;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { o as Retrievable } from "../../common-
|
|
1
|
+
import { o as Retrievable } from "../../common-DYDUi99O.mjs";
|
|
2
2
|
import "../../index.mjs";
|
|
3
3
|
//#region src/batteries/vector/retrievable_glue.ts
|
|
4
4
|
/**
|
|
5
5
|
* @module @nhtio/adk/batteries/vector/retrievable
|
|
6
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* Build the retrievable-lifecycle callbacks (fetch/store/mutate/delete) that bridge a callable
|
|
9
|
+
* vector store to the ADK's retrievable subsystem, applying the supplied query derivation,
|
|
10
|
+
* match-to-retrievable mapping, and trust-tier assignment.
|
|
11
|
+
*
|
|
12
|
+
* @param opts - The store, collection, and behaviour overrides.
|
|
13
|
+
* @returns The four wired {@link VectorRetrievableCallbacks}.
|
|
14
|
+
*/
|
|
7
15
|
var createVectorRetrievableCallbacks = (opts) => {
|
|
8
16
|
const topK = opts.topK ?? 5;
|
|
9
17
|
const tierFor = (m) => typeof opts.trustTier === "function" ? opts.trustTier(m) : opts.trustTier;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retrievable.mjs","names":[],"sources":["../../../src/batteries/vector/retrievable_glue.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/retrievable\n */\n\nimport { Retrievable } from '@nhtio/adk'\nimport type { VectorFilter } from './filters'\nimport type { CallableVectorStore } from './contract'\nimport type { VectorMatch, VectorMetadata } from './types'\nimport type { RawRetrievable, RetrievableTrustTier } from '@nhtio/adk/common'\nimport type {\n TurnContext,\n RetrievableRetrievalFn,\n RetrievableStoreFn,\n RetrievableMutateFn,\n RetrievableDeleteFn,\n} from '@nhtio/adk'\n\nexport interface VectorRetrievableGlueOptions {\n store: CallableVectorStore\n collection: string\n trustTier: RetrievableTrustTier | ((m: VectorMatch) => RetrievableTrustTier)\n topK?: number\n filter?: VectorFilter\n deriveQuery?: (\n ctx: TurnContext\n ) => string | number[] | undefined | Promise<string | number[] | undefined>\n toRetrievable?: (m: VectorMatch) => Omit<RawRetrievable, 'trustTier'>\n}\n\nexport interface VectorRetrievableCallbacks {\n fetchRetrievablesCallback: RetrievableRetrievalFn\n storeRetrievableCallback: RetrievableStoreFn\n mutateRetrievableCallback: RetrievableMutateFn\n deleteRetrievableCallback: RetrievableDeleteFn\n}\n\nexport const createVectorRetrievableCallbacks = (\n opts: VectorRetrievableGlueOptions\n): VectorRetrievableCallbacks => {\n const topK = opts.topK ?? 5\n const tierFor = (m: VectorMatch): RetrievableTrustTier =>\n typeof opts.trustTier === 'function' ? opts.trustTier(m) : opts.trustTier\n\n // default deriveQuery: last user message text, else undefined\n const deriveQuery =\n opts.deriveQuery ??\n (async (ctx: TurnContext) => {\n const msgs = await ctx.fetchMessages()\n for (let i = msgs.length - 1; i >= 0; i--) {\n if (msgs[i].role === 'user') return msgs[i].content?.toString() ?? ''\n }\n return undefined\n })\n\n // default mapping VectorMatch -> RawRetrievable (minus trustTier)\n const toRetrievable =\n opts.toRetrievable ??\n ((m: VectorMatch): Omit<RawRetrievable, 'trustTier'> => {\n const md = (m.metadata ?? {}) as Record<string, unknown>\n const now = new Date()\n return {\n id: m.id ?? String(md.id ?? ''),\n content: m.document ?? String(md.content ?? ''),\n source: typeof md.source === 'string' ? md.source : undefined,\n kind: typeof md.kind === 'string' ? md.kind : undefined,\n score: typeof m.score === 'number' ? m.score : undefined,\n createdAt: (md.createdAt as any) ?? now,\n updatedAt: (md.updatedAt as any) ?? now,\n }\n })\n\n const fetchRetrievablesCallback: RetrievableRetrievalFn = async (ctx) => {\n const q = await deriveQuery(ctx)\n if (q === undefined) return []\n let b = opts.store(opts.collection)\n b = Array.isArray(q) ? b.nearVector(q) : b.nearText(q)\n if (opts.filter) b = b.whereRaw(opts.filter as any)\n const matches = await b.select('id', 'document', 'metadata').limit(topK)\n return matches.map((m) => new Retrievable({ ...toRetrievable(m), trustTier: tierFor(m) }))\n }\n\n const storeRetrievableCallback: RetrievableStoreFn = async (_ctx, r) => {\n const content = await r.contentString()\n const metadata: VectorMetadata = {\n trustTier: r.trustTier,\n createdAt: r.createdAt?.toISO?.() ?? String(r.createdAt),\n updatedAt: r.updatedAt?.toISO?.() ?? String(r.updatedAt),\n }\n if (r.source !== undefined) metadata.source = r.source\n if (r.kind !== undefined) metadata.kind = r.kind\n await opts.store(opts.collection).upsert([{ id: r.id, document: content, metadata }])\n }\n const mutateRetrievableCallback: RetrievableMutateFn = storeRetrievableCallback // upsert == replace\n const deleteRetrievableCallback: RetrievableDeleteFn = async (_ctx, id) => {\n await opts.store(opts.collection).whereIn('id', [id]).delete()\n }\n\n return {\n fetchRetrievablesCallback,\n storeRetrievableCallback,\n mutateRetrievableCallback,\n deleteRetrievableCallback,\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"retrievable.mjs","names":[],"sources":["../../../src/batteries/vector/retrievable_glue.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/retrievable\n */\n\nimport { Retrievable } from '@nhtio/adk'\nimport type { VectorFilter } from './filters'\nimport type { CallableVectorStore } from './contract'\nimport type { VectorMatch, VectorMetadata } from './types'\nimport type { RawRetrievable, RetrievableTrustTier } from '@nhtio/adk/common'\nimport type {\n TurnContext,\n RetrievableRetrievalFn,\n RetrievableStoreFn,\n RetrievableMutateFn,\n RetrievableDeleteFn,\n} from '@nhtio/adk'\n\n/** Configuration for wiring a vector store to the ADK's retrievable lifecycle callbacks. */\nexport interface VectorRetrievableGlueOptions {\n /** The callable vector store the callbacks query and write to. */\n store: CallableVectorStore\n /** Collection the retrievables live in. */\n collection: string\n /** Trust tier for fetched matches — a fixed tier, or a per-match function. */\n trustTier: RetrievableTrustTier | ((m: VectorMatch) => RetrievableTrustTier)\n /** Maximum number of retrievables to fetch per turn (default 5). */\n topK?: number\n /** Optional filter applied to every retrieval query. */\n filter?: VectorFilter\n /** Derives the retrieval query from the turn context; defaults to the last user message. */\n deriveQuery?: (\n ctx: TurnContext\n ) => string | number[] | undefined | Promise<string | number[] | undefined>\n /** Maps a {@link VectorMatch} to a raw retrievable (trust tier applied separately). */\n toRetrievable?: (m: VectorMatch) => Omit<RawRetrievable, 'trustTier'>\n}\n\n/** The four retrievable-lifecycle callbacks produced by {@link createVectorRetrievableCallbacks}. */\nexport interface VectorRetrievableCallbacks {\n /** Fetches retrievables relevant to the current turn. */\n fetchRetrievablesCallback: RetrievableRetrievalFn\n /** Persists a new retrievable into the store. */\n storeRetrievableCallback: RetrievableStoreFn\n /** Replaces an existing retrievable (upsert). */\n mutateRetrievableCallback: RetrievableMutateFn\n /** Deletes a retrievable by id. */\n deleteRetrievableCallback: RetrievableDeleteFn\n}\n\n/**\n * Build the retrievable-lifecycle callbacks (fetch/store/mutate/delete) that bridge a callable\n * vector store to the ADK's retrievable subsystem, applying the supplied query derivation,\n * match-to-retrievable mapping, and trust-tier assignment.\n *\n * @param opts - The store, collection, and behaviour overrides.\n * @returns The four wired {@link VectorRetrievableCallbacks}.\n */\nexport const createVectorRetrievableCallbacks = (\n opts: VectorRetrievableGlueOptions\n): VectorRetrievableCallbacks => {\n const topK = opts.topK ?? 5\n const tierFor = (m: VectorMatch): RetrievableTrustTier =>\n typeof opts.trustTier === 'function' ? opts.trustTier(m) : opts.trustTier\n\n // default deriveQuery: last user message text, else undefined\n const deriveQuery =\n opts.deriveQuery ??\n (async (ctx: TurnContext) => {\n const msgs = await ctx.fetchMessages()\n for (let i = msgs.length - 1; i >= 0; i--) {\n if (msgs[i].role === 'user') return msgs[i].content?.toString() ?? ''\n }\n return undefined\n })\n\n // default mapping VectorMatch -> RawRetrievable (minus trustTier)\n const toRetrievable =\n opts.toRetrievable ??\n ((m: VectorMatch): Omit<RawRetrievable, 'trustTier'> => {\n const md = (m.metadata ?? {}) as Record<string, unknown>\n const now = new Date()\n return {\n id: m.id ?? String(md.id ?? ''),\n content: m.document ?? String(md.content ?? ''),\n source: typeof md.source === 'string' ? md.source : undefined,\n kind: typeof md.kind === 'string' ? md.kind : undefined,\n score: typeof m.score === 'number' ? m.score : undefined,\n createdAt: (md.createdAt as any) ?? now,\n updatedAt: (md.updatedAt as any) ?? now,\n }\n })\n\n const fetchRetrievablesCallback: RetrievableRetrievalFn = async (ctx) => {\n const q = await deriveQuery(ctx)\n if (q === undefined) return []\n let b = opts.store(opts.collection)\n b = Array.isArray(q) ? b.nearVector(q) : b.nearText(q)\n if (opts.filter) b = b.whereRaw(opts.filter as any)\n const matches = await b.select('id', 'document', 'metadata').limit(topK)\n return matches.map((m) => new Retrievable({ ...toRetrievable(m), trustTier: tierFor(m) }))\n }\n\n const storeRetrievableCallback: RetrievableStoreFn = async (_ctx, r) => {\n const content = await r.contentString()\n const metadata: VectorMetadata = {\n trustTier: r.trustTier,\n createdAt: r.createdAt?.toISO?.() ?? String(r.createdAt),\n updatedAt: r.updatedAt?.toISO?.() ?? String(r.updatedAt),\n }\n if (r.source !== undefined) metadata.source = r.source\n if (r.kind !== undefined) metadata.kind = r.kind\n await opts.store(opts.collection).upsert([{ id: r.id, document: content, metadata }])\n }\n const mutateRetrievableCallback: RetrievableMutateFn = storeRetrievableCallback // upsert == replace\n const deleteRetrievableCallback: RetrievableDeleteFn = async (_ctx, id) => {\n await opts.store(opts.collection).whereIn('id', [id]).delete()\n }\n\n return {\n fetchRetrievablesCallback,\n storeRetrievableCallback,\n mutateRetrievableCallback,\n deleteRetrievableCallback,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAyDA,IAAa,oCACX,SAC+B;CAC/B,MAAM,OAAO,KAAK,QAAQ;CAC1B,MAAM,WAAW,MACf,OAAO,KAAK,cAAc,aAAa,KAAK,UAAU,CAAC,IAAI,KAAK;CAGlE,MAAM,cACJ,KAAK,gBACJ,OAAO,QAAqB;EAC3B,MAAM,OAAO,MAAM,IAAI,cAAc;EACrC,KAAK,IAAI,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,KACpC,IAAI,KAAK,GAAG,SAAS,QAAQ,OAAO,KAAK,GAAG,SAAS,SAAS,KAAK;CAGvE;CAGF,MAAM,gBACJ,KAAK,mBACH,MAAsD;EACtD,MAAM,KAAM,EAAE,YAAY,CAAC;EAC3B,MAAM,sBAAM,IAAI,KAAK;EACrB,OAAO;GACL,IAAI,EAAE,MAAM,OAAO,GAAG,MAAM,EAAE;GAC9B,SAAS,EAAE,YAAY,OAAO,GAAG,WAAW,EAAE;GAC9C,QAAQ,OAAO,GAAG,WAAW,WAAW,GAAG,SAAS,KAAA;GACpD,MAAM,OAAO,GAAG,SAAS,WAAW,GAAG,OAAO,KAAA;GAC9C,OAAO,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ,KAAA;GAC/C,WAAY,GAAG,aAAqB;GACpC,WAAY,GAAG,aAAqB;EACtC;CACF;CAEF,MAAM,4BAAoD,OAAO,QAAQ;EACvE,MAAM,IAAI,MAAM,YAAY,GAAG;EAC/B,IAAI,MAAM,KAAA,GAAW,OAAO,CAAC;EAC7B,IAAI,IAAI,KAAK,MAAM,KAAK,UAAU;EAClC,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC;EACrD,IAAI,KAAK,QAAQ,IAAI,EAAE,SAAS,KAAK,MAAa;EAElD,QAAO,MADe,EAAE,OAAO,MAAM,YAAY,UAAU,EAAE,MAAM,IAAI,GACxD,KAAK,MAAM,IAAI,YAAY;GAAE,GAAG,cAAc,CAAC;GAAG,WAAW,QAAQ,CAAC;EAAE,CAAC,CAAC;CAC3F;CAEA,MAAM,2BAA+C,OAAO,MAAM,MAAM;EACtE,MAAM,UAAU,MAAM,EAAE,cAAc;EACtC,MAAM,WAA2B;GAC/B,WAAW,EAAE;GACb,WAAW,EAAE,WAAW,QAAQ,KAAK,OAAO,EAAE,SAAS;GACvD,WAAW,EAAE,WAAW,QAAQ,KAAK,OAAO,EAAE,SAAS;EACzD;EACA,IAAI,EAAE,WAAW,KAAA,GAAW,SAAS,SAAS,EAAE;EAChD,IAAI,EAAE,SAAS,KAAA,GAAW,SAAS,OAAO,EAAE;EAC5C,MAAM,KAAK,MAAM,KAAK,UAAU,EAAE,OAAO,CAAC;GAAE,IAAI,EAAE;GAAI,UAAU;GAAS;EAAS,CAAC,CAAC;CACtF;CACA,MAAM,4BAAiD;CACvD,MAAM,4BAAiD,OAAO,MAAM,OAAO;EACzE,MAAM,KAAK,MAAM,KAAK,UAAU,EAAE,QAAQ,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO;CAC/D;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -6,19 +6,40 @@ import type { CallableVectorStore } from "./contract";
|
|
|
6
6
|
import type { VectorMatch } from "./types";
|
|
7
7
|
import type { RawRetrievable, RetrievableTrustTier } from "../../common";
|
|
8
8
|
import type { TurnContext, RetrievableRetrievalFn, RetrievableStoreFn, RetrievableMutateFn, RetrievableDeleteFn } from "../../index";
|
|
9
|
+
/** Configuration for wiring a vector store to the ADK's retrievable lifecycle callbacks. */
|
|
9
10
|
export interface VectorRetrievableGlueOptions {
|
|
11
|
+
/** The callable vector store the callbacks query and write to. */
|
|
10
12
|
store: CallableVectorStore;
|
|
13
|
+
/** Collection the retrievables live in. */
|
|
11
14
|
collection: string;
|
|
15
|
+
/** Trust tier for fetched matches — a fixed tier, or a per-match function. */
|
|
12
16
|
trustTier: RetrievableTrustTier | ((m: VectorMatch) => RetrievableTrustTier);
|
|
17
|
+
/** Maximum number of retrievables to fetch per turn (default 5). */
|
|
13
18
|
topK?: number;
|
|
19
|
+
/** Optional filter applied to every retrieval query. */
|
|
14
20
|
filter?: VectorFilter;
|
|
21
|
+
/** Derives the retrieval query from the turn context; defaults to the last user message. */
|
|
15
22
|
deriveQuery?: (ctx: TurnContext) => string | number[] | undefined | Promise<string | number[] | undefined>;
|
|
23
|
+
/** Maps a {@link VectorMatch} to a raw retrievable (trust tier applied separately). */
|
|
16
24
|
toRetrievable?: (m: VectorMatch) => Omit<RawRetrievable, 'trustTier'>;
|
|
17
25
|
}
|
|
26
|
+
/** The four retrievable-lifecycle callbacks produced by {@link createVectorRetrievableCallbacks}. */
|
|
18
27
|
export interface VectorRetrievableCallbacks {
|
|
28
|
+
/** Fetches retrievables relevant to the current turn. */
|
|
19
29
|
fetchRetrievablesCallback: RetrievableRetrievalFn;
|
|
30
|
+
/** Persists a new retrievable into the store. */
|
|
20
31
|
storeRetrievableCallback: RetrievableStoreFn;
|
|
32
|
+
/** Replaces an existing retrievable (upsert). */
|
|
21
33
|
mutateRetrievableCallback: RetrievableMutateFn;
|
|
34
|
+
/** Deletes a retrievable by id. */
|
|
22
35
|
deleteRetrievableCallback: RetrievableDeleteFn;
|
|
23
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Build the retrievable-lifecycle callbacks (fetch/store/mutate/delete) that bridge a callable
|
|
39
|
+
* vector store to the ADK's retrievable subsystem, applying the supplied query derivation,
|
|
40
|
+
* match-to-retrievable mapping, and trust-tier assignment.
|
|
41
|
+
*
|
|
42
|
+
* @param opts - The store, collection, and behaviour overrides.
|
|
43
|
+
* @returns The four wired {@link VectorRetrievableCallbacks}.
|
|
44
|
+
*/
|
|
24
45
|
export declare const createVectorRetrievableCallbacks: (opts: VectorRetrievableGlueOptions) => VectorRetrievableCallbacks;
|
|
@@ -24,6 +24,7 @@ import { BaseVectorStore } from "../contract";
|
|
|
24
24
|
import type { SearchPlan, UpsertPlan, DeletePlan, CollectionSpec } from "../plan";
|
|
25
25
|
import type { VectorMatch, VectorStoreCapabilities, BaseVectorStoreOptions } from "../types";
|
|
26
26
|
export interface S3VectorsVectorStoreOptions extends BaseVectorStoreOptions {
|
|
27
|
+
/** Connection and authentication parameters for the backend. */
|
|
27
28
|
connection: {
|
|
28
29
|
bucket: string;
|
|
29
30
|
region?: string;
|
|
@@ -38,6 +39,7 @@ export interface S3VectorsVectorStoreOptions extends BaseVectorStoreOptions {
|
|
|
38
39
|
export declare class S3VectorsVectorStore extends BaseVectorStore {
|
|
39
40
|
#private;
|
|
40
41
|
readonly capabilities: VectorStoreCapabilities;
|
|
42
|
+
/** Static availability probe: whether this adapter's runtime driver can load in the current environment. */
|
|
41
43
|
static isAvailable(): boolean;
|
|
42
44
|
isAvailable(): boolean;
|
|
43
45
|
connect(): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Ble4zEEl.js");
|
|
3
|
-
const require_tool_registry = require("../../tool_registry-
|
|
3
|
+
const require_tool_registry = require("../../tool_registry-CKJPze3j.js");
|
|
4
4
|
require("../../guards.cjs");
|
|
5
5
|
const require_batteries_vector_filters = require("./filters.cjs");
|
|
6
6
|
const require_batteries_vector_helpers = require("./helpers.cjs");
|
|
@@ -122,6 +122,7 @@ var S3VectorsVectorStore = class extends require_batteries_vector_contract.BaseV
|
|
|
122
122
|
await new Promise((r) => setTimeout(r, 300));
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
+
/** Static availability probe: whether this adapter's runtime driver can load in the current environment. */
|
|
125
126
|
static isAvailable() {
|
|
126
127
|
return typeof process !== "undefined";
|
|
127
128
|
}
|