@nhtio/adk 1.20260607.2 → 1.20260609.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +185 -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/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 +1 -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/searxng/exceptions.d.ts +21 -0
- package/batteries/tools/searxng/index.d.ts +150 -0
- package/batteries/tools/searxng.cjs +5 -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.cjs +3 -0
- package/batteries/tools.mjs +2 -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 +46 -28
- package/batteries.mjs +10 -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.d.ts +1 -1
- 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.cjs +1 -1
- package/eslint.mjs +1 -1
- 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 +13 -13
- package/index.mjs +13 -13
- 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 +264 -224
- 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/searxng-Bkrwhwhw.js +269 -0
- package/searxng-Bkrwhwhw.js.map +1 -0
- package/searxng-CyA-nEu5.mjs +257 -0
- package/searxng-CyA-nEu5.mjs.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":"arangodb.mjs","names":["#opts","#db","#aql","#ensure","#dims","#indexed","#ensureVectorIndex","#parseMeta","#project"],"sources":["../../../src/batteries/vector/arangodb/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/arangodb\n *\n * ArangoDB adapter (experimental vector index, 3.12.4+). Each collection is an ArangoDB\n * document collection keyed by `_key`; a `vector` index on `vec` enables KNN via\n * `APPROX_NEAR_COSINE` / `APPROX_NEAR_L2`. Metadata is a JSON string attribute filtered with\n * the neutral filter tree's JS reference evaluator for exact cross-adapter parity.\n *\n * Driver: `arangojs` (pure JS). Requires the server started with\n * `--experimental-vector-index=true`. All values are passed as AQL bind parameters.\n */\n\nimport { evaluateFilter } from '../filters'\nimport { BaseVectorStore } from '../contract'\nimport { validateRecords } from '../validation'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport {\n E_VECTOR_STORE_DRIVER_UNAVAILABLE,\n E_VECTOR_STORE_CONNECTION_FAILED,\n E_VECTOR_STORE_COLLECTION_FAILED,\n E_VECTOR_STORE_UPSERT_FAILED,\n E_VECTOR_STORE_SEARCH_FAILED,\n E_VECTOR_STORE_DELETE_FAILED,\n E_VECTOR_STORE_DIMENSION_MISMATCH,\n E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n} from '../exceptions'\nimport type { SearchPlan, UpsertPlan, DeletePlan, CollectionSpec } from '../plan'\nimport type {\n VectorMatch,\n VectorStoreCapabilities,\n BaseVectorStoreOptions,\n VectorMetadata,\n} from '../types'\n\nexport interface ArangoDBVectorStoreOptions extends BaseVectorStoreOptions {\n connection: {\n url: string\n username?: string\n password?: string\n database?: string\n nLists?: number\n }\n}\n\nconst getArango = async () => {\n try {\n const mod = await import('arangojs')\n return mod\n } catch {\n throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['arangojs'])\n }\n}\n\nexport class ArangoDBVectorStore extends BaseVectorStore {\n readonly capabilities: VectorStoreCapabilities = {\n transactions: false,\n namedVectors: false,\n rename: false,\n rawSql: false,\n builtInEncoding: false,\n // Document writes are synchronous (visible on resolve). The option is a no-op.\n consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n }\n\n #db: any | null = null\n #aql: any | null = null\n #dims: Map<string, number> = new Map()\n // ArangoDB's IVF vector index can't be created on an empty collection (\"not ready\") and\n // needs nLists <= doc count. We therefore create the index lazily after the first upsert.\n #indexed: Set<string> = new Set()\n\n get #opts(): ArangoDBVectorStoreOptions {\n return this.options as ArangoDBVectorStoreOptions\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.#db) return\n const arango = await getArango()\n this.#aql = arango.aql\n const c = this.#opts.connection\n const dbName = c.database ?? 'vector'\n try {\n const auth = c.username ? { username: c.username, password: c.password ?? '' } : undefined\n const sys = new arango.Database({ url: c.url, auth })\n const exists = await sys.listDatabases().then((dbs: string[]) => dbs.includes(dbName))\n if (!exists) {\n await sys.createDatabase(dbName)\n }\n this.#db = new arango.Database({ url: c.url, databaseName: dbName, auth })\n } catch (err) {\n throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n }\n }\n\n async close(): Promise<void> {\n this.#db = null\n this.#aql = null\n }\n\n async #ensure(): Promise<any> {\n if (!this.#db) await this.connect()\n return this.#db!\n }\n\n async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n const db = await this.#ensure()\n this.#dims.set(spec.collection, spec.vector.dimensions)\n try {\n const col = db.collection(spec.collection)\n const exists = await col.exists()\n if (exists && !ifNotExists) {\n await col.drop()\n this.#indexed.delete(spec.collection)\n }\n if (!(await col.exists())) {\n await col.create()\n this.#indexed.delete(spec.collection)\n }\n // The vector index is created lazily on first upsert (see #ensureVectorIndex): ArangoDB\n // rejects creating it on an empty collection (\"vector index not ready\").\n } catch (err) {\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', String(err)])\n }\n }\n\n // Create the IVF vector index once the collection has data (idempotent per collection).\n async #ensureVectorIndex(collection: string): Promise<void> {\n if (this.#indexed.has(collection)) return\n const db = await this.#ensure()\n const col = db.collection(collection)\n const metric = this.#opts.metric ?? 'cosine'\n const dim = this.#dims.get(collection) ?? this.#opts.dimensions\n if (dim === undefined) return\n try {\n await col.ensureIndex({\n type: 'vector',\n fields: ['vec'],\n params: {\n metric: metric === 'euclidean' ? 'l2' : 'cosine',\n dimension: dim,\n nLists: this.#opts.connection.nLists ?? 1,\n },\n })\n this.#indexed.add(collection)\n } catch {\n // If it still isn't ready (too few docs), leave it; executeSearch falls back to a\n // brute-force AQL scan so correctness holds regardless of the index.\n }\n }\n\n async dropCollection(collection: string, ifExists: boolean): Promise<void> {\n const db = await this.#ensure()\n try {\n const col = db.collection(collection)\n if (await col.exists()) {\n await col.drop()\n } else if (!ifExists) {\n throw new Error('collection not found: ' + collection)\n }\n this.#dims.delete(collection)\n } catch (err) {\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['dropCollection', String(err)])\n }\n }\n\n async hasCollection(collection: string): Promise<boolean> {\n const db = await this.#ensure()\n try {\n return await db.collection(collection).exists()\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', 'arangodb'])\n }\n\n async executeUpsert(plan: UpsertPlan): Promise<void> {\n if (plan.records.length === 0) return\n validateRecords(plan.records)\n const db = await this.#ensure()\n const expected = this.#opts.dimensions ?? this.#dims.get(plan.collection)\n try {\n const col = db.collection(plan.collection)\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 const doc = {\n _key: r.id,\n vec: vector,\n document: r.document ?? '',\n metadata: r.metadata ? JSON.stringify(r.metadata) : '{}',\n }\n await col.save(doc, { overwriteMode: 'replace' })\n }\n // Now that the collection has data, ensure the IVF vector index exists.\n await this.#ensureVectorIndex(plan.collection)\n } catch (err) {\n if (\n isInstanceOf(err, 'E_VECTOR_STORE_DIMENSION_MISMATCH', E_VECTOR_STORE_DIMENSION_MISMATCH) ||\n isInstanceOf(err, 'E_VECTOR_STORE_UPSERT_FAILED', E_VECTOR_STORE_UPSERT_FAILED)\n ) {\n throw err\n }\n throw new E_VECTOR_STORE_UPSERT_FAILED([String(err)])\n }\n }\n\n async executeSearch(plan: SearchPlan): Promise<VectorMatch[]> {\n const db = await this.#ensure()\n const aql = this.#aql\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 col = db.collection(plan.collection)\n try {\n const doc = await col.document(plan.near.id)\n queryVector = doc.vec as number[]\n } catch {\n throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n }\n }\n }\n\n const offset = plan.offset ?? 0\n try {\n let rows: any[]\n if (queryVector) {\n // Use the exact AQL distance functions (COSINE_SIMILARITY / L2_DISTANCE) rather than the\n // APPROX_NEAR_* index functions: they need no index, are always correct, and avoid\n // ArangoDB's IVF \"not ready\" / nLists-vs-doc-count constraints. The IVF index is still\n // created lazily on upsert for production-scale ANN; here correctness comes first.\n const useL2 = metric === 'euclidean'\n const fn = useL2 ? 'L2_DISTANCE' : 'COSINE_SIMILARITY'\n const dir = useL2 ? 'ASC' : 'DESC'\n const k = plan.filter ? 100000 : plan.topK + offset\n const query =\n `FOR d IN @@col ` +\n `LET __score = ${fn}(d.vec, @qv) ` +\n `SORT __score ${dir} LIMIT @k ` +\n `RETURN { id: d._key, vec: d.vec, document: d.document, metadata: d.metadata, score: __score }`\n const cursor = await db.query(query, {\n '@col': plan.collection,\n 'qv': queryVector,\n k,\n })\n rows = await cursor.all()\n const filtered = plan.filter\n ? rows.filter((row) => evaluateFilter(plan.filter!, this.#parseMeta(row.metadata)))\n : rows\n return filtered\n .slice(offset, offset + plan.topK)\n .map((row) => this.#project(row, plan, true))\n } else {\n const cursor = await db.query(\n aql`FOR d IN ${db.collection(plan.collection)} RETURN { id: d._key, vec: d.vec, document: d.document, metadata: d.metadata }`\n )\n rows = await cursor.all()\n const filtered = plan.filter\n ? rows.filter((row) => evaluateFilter(plan.filter!, this.#parseMeta(row.metadata)))\n : rows\n return filtered\n .slice(offset, offset + plan.topK)\n .map((row) => this.#project(row, plan, false))\n }\n } catch (err) {\n throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n }\n }\n\n #parseMeta(val: unknown): VectorMetadata {\n if (typeof val === 'string') {\n try {\n return JSON.parse(val) as VectorMetadata\n } catch {\n return {}\n }\n }\n if (val && typeof val === 'object') return val as VectorMetadata\n return {}\n }\n\n #project(row: any, plan: SearchPlan, isKnn: boolean): VectorMatch {\n const proj = plan.projection\n const out: VectorMatch = {}\n if (proj.id) out.id = row.id as string\n if (proj.vector && Array.isArray(row.vec)) out.vector = (row.vec as number[]).map(Number)\n if (proj.document) out.document = (row.document ?? undefined) as string | undefined\n if (proj.metadata) out.metadata = this.#parseMeta(row.metadata)\n if (isKnn && row.score !== undefined && row.score !== null) {\n // APPROX_NEAR_COSINE returns cosine similarity in [0,1]; L2 returns a distance.\n const m = this.#opts.metric ?? 'cosine'\n out.score = m === 'euclidean' ? 1 / (1 + Number(row.score)) : Number(row.score)\n }\n return out\n }\n\n async executeDelete(plan: DeletePlan): Promise<void> {\n const db = await this.#ensure()\n const aql = this.#aql\n try {\n const col = db.collection(plan.collection)\n if (plan.ids && plan.ids.length > 0) {\n await col.removeAll(plan.ids).catch(async () => {\n for (const id of plan.ids!) await col.remove(id).catch(() => undefined)\n })\n } else if (plan.filter) {\n const cursor = await db.query(\n aql`FOR d IN ${col} RETURN { id: d._key, metadata: d.metadata }`\n )\n const rows = await cursor.all()\n const targets = rows\n .filter((row: any) => evaluateFilter(plan.filter!, this.#parseMeta(row.metadata)))\n .map((row: any) => row.id as string)\n if (targets.length > 0) {\n await col.removeAll(targets).catch(async () => {\n for (const id of targets) await col.remove(id).catch(() => undefined)\n })\n }\n } else {\n await col.truncate()\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":"arangodb.mjs","names":["#opts","#db","#aql","#ensure","#dims","#indexed","#ensureVectorIndex","#parseMeta","#project"],"sources":["../../../src/batteries/vector/arangodb/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/arangodb\n *\n * ArangoDB adapter (experimental vector index, 3.12.4+). Each collection is an ArangoDB\n * document collection keyed by `_key`; a `vector` index on `vec` enables KNN via\n * `APPROX_NEAR_COSINE` / `APPROX_NEAR_L2`. Metadata is a JSON string attribute filtered with\n * the neutral filter tree's JS reference evaluator for exact cross-adapter parity.\n *\n * Driver: `arangojs` (pure JS). Requires the server started with\n * `--experimental-vector-index=true`. All values are passed as AQL bind parameters.\n */\n\nimport { evaluateFilter } from '../filters'\nimport { BaseVectorStore } from '../contract'\nimport { validateRecords } from '../validation'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport {\n E_VECTOR_STORE_DRIVER_UNAVAILABLE,\n E_VECTOR_STORE_CONNECTION_FAILED,\n E_VECTOR_STORE_COLLECTION_FAILED,\n E_VECTOR_STORE_UPSERT_FAILED,\n E_VECTOR_STORE_SEARCH_FAILED,\n E_VECTOR_STORE_DELETE_FAILED,\n E_VECTOR_STORE_DIMENSION_MISMATCH,\n E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n} from '../exceptions'\nimport type { SearchPlan, UpsertPlan, DeletePlan, CollectionSpec } from '../plan'\nimport type {\n VectorMatch,\n VectorStoreCapabilities,\n BaseVectorStoreOptions,\n VectorMetadata,\n} from '../types'\n\nexport interface ArangoDBVectorStoreOptions extends BaseVectorStoreOptions {\n /** Connection and authentication parameters for the backend. */\n connection: {\n url: string\n username?: string\n password?: string\n database?: string\n nLists?: number\n }\n}\n\nconst getArango = async () => {\n try {\n const mod = await import('arangojs')\n return mod\n } catch {\n throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['arangojs'])\n }\n}\n\nexport class ArangoDBVectorStore extends BaseVectorStore {\n readonly capabilities: VectorStoreCapabilities = {\n transactions: false,\n namedVectors: false,\n rename: false,\n rawSql: false,\n builtInEncoding: false,\n // Document writes are synchronous (visible on resolve). The option is a no-op.\n consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n }\n\n #db: any | null = null\n #aql: any | null = null\n #dims: Map<string, number> = new Map()\n // ArangoDB's IVF vector index can't be created on an empty collection (\"not ready\") and\n // needs nLists <= doc count. We therefore create the index lazily after the first upsert.\n #indexed: Set<string> = new Set()\n\n get #opts(): ArangoDBVectorStoreOptions {\n return this.options as ArangoDBVectorStoreOptions\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.#db) return\n const arango = await getArango()\n this.#aql = arango.aql\n const c = this.#opts.connection\n const dbName = c.database ?? 'vector'\n try {\n const auth = c.username ? { username: c.username, password: c.password ?? '' } : undefined\n const sys = new arango.Database({ url: c.url, auth })\n const exists = await sys.listDatabases().then((dbs: string[]) => dbs.includes(dbName))\n if (!exists) {\n await sys.createDatabase(dbName)\n }\n this.#db = new arango.Database({ url: c.url, databaseName: dbName, auth })\n } catch (err) {\n throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n }\n }\n\n async close(): Promise<void> {\n this.#db = null\n this.#aql = null\n }\n\n async #ensure(): Promise<any> {\n if (!this.#db) await this.connect()\n return this.#db!\n }\n\n async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n const db = await this.#ensure()\n this.#dims.set(spec.collection, spec.vector.dimensions)\n try {\n const col = db.collection(spec.collection)\n const exists = await col.exists()\n if (exists && !ifNotExists) {\n await col.drop()\n this.#indexed.delete(spec.collection)\n }\n if (!(await col.exists())) {\n await col.create()\n this.#indexed.delete(spec.collection)\n }\n // The vector index is created lazily on first upsert (see #ensureVectorIndex): ArangoDB\n // rejects creating it on an empty collection (\"vector index not ready\").\n } catch (err) {\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', String(err)])\n }\n }\n\n // Create the IVF vector index once the collection has data (idempotent per collection).\n async #ensureVectorIndex(collection: string): Promise<void> {\n if (this.#indexed.has(collection)) return\n const db = await this.#ensure()\n const col = db.collection(collection)\n const metric = this.#opts.metric ?? 'cosine'\n const dim = this.#dims.get(collection) ?? this.#opts.dimensions\n if (dim === undefined) return\n try {\n await col.ensureIndex({\n type: 'vector',\n fields: ['vec'],\n params: {\n metric: metric === 'euclidean' ? 'l2' : 'cosine',\n dimension: dim,\n nLists: this.#opts.connection.nLists ?? 1,\n },\n })\n this.#indexed.add(collection)\n } catch {\n // If it still isn't ready (too few docs), leave it; executeSearch falls back to a\n // brute-force AQL scan so correctness holds regardless of the index.\n }\n }\n\n async dropCollection(collection: string, ifExists: boolean): Promise<void> {\n const db = await this.#ensure()\n try {\n const col = db.collection(collection)\n if (await col.exists()) {\n await col.drop()\n } else if (!ifExists) {\n throw new Error('collection not found: ' + collection)\n }\n this.#dims.delete(collection)\n } catch (err) {\n throw new E_VECTOR_STORE_COLLECTION_FAILED(['dropCollection', String(err)])\n }\n }\n\n async hasCollection(collection: string): Promise<boolean> {\n const db = await this.#ensure()\n try {\n return await db.collection(collection).exists()\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', 'arangodb'])\n }\n\n async executeUpsert(plan: UpsertPlan): Promise<void> {\n if (plan.records.length === 0) return\n validateRecords(plan.records)\n const db = await this.#ensure()\n const expected = this.#opts.dimensions ?? this.#dims.get(plan.collection)\n try {\n const col = db.collection(plan.collection)\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 const doc = {\n _key: r.id,\n vec: vector,\n document: r.document ?? '',\n metadata: r.metadata ? JSON.stringify(r.metadata) : '{}',\n }\n await col.save(doc, { overwriteMode: 'replace' })\n }\n // Now that the collection has data, ensure the IVF vector index exists.\n await this.#ensureVectorIndex(plan.collection)\n } catch (err) {\n if (\n isInstanceOf(err, 'E_VECTOR_STORE_DIMENSION_MISMATCH', E_VECTOR_STORE_DIMENSION_MISMATCH) ||\n isInstanceOf(err, 'E_VECTOR_STORE_UPSERT_FAILED', E_VECTOR_STORE_UPSERT_FAILED)\n ) {\n throw err\n }\n throw new E_VECTOR_STORE_UPSERT_FAILED([String(err)])\n }\n }\n\n async executeSearch(plan: SearchPlan): Promise<VectorMatch[]> {\n const db = await this.#ensure()\n const aql = this.#aql\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 col = db.collection(plan.collection)\n try {\n const doc = await col.document(plan.near.id)\n queryVector = doc.vec as number[]\n } catch {\n throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n }\n }\n }\n\n const offset = plan.offset ?? 0\n try {\n let rows: any[]\n if (queryVector) {\n // Use the exact AQL distance functions (COSINE_SIMILARITY / L2_DISTANCE) rather than the\n // APPROX_NEAR_* index functions: they need no index, are always correct, and avoid\n // ArangoDB's IVF \"not ready\" / nLists-vs-doc-count constraints. The IVF index is still\n // created lazily on upsert for production-scale ANN; here correctness comes first.\n const useL2 = metric === 'euclidean'\n const fn = useL2 ? 'L2_DISTANCE' : 'COSINE_SIMILARITY'\n const dir = useL2 ? 'ASC' : 'DESC'\n const k = plan.filter ? 100000 : plan.topK + offset\n const query =\n `FOR d IN @@col ` +\n `LET __score = ${fn}(d.vec, @qv) ` +\n `SORT __score ${dir} LIMIT @k ` +\n `RETURN { id: d._key, vec: d.vec, document: d.document, metadata: d.metadata, score: __score }`\n const cursor = await db.query(query, {\n '@col': plan.collection,\n 'qv': queryVector,\n k,\n })\n rows = await cursor.all()\n const filtered = plan.filter\n ? rows.filter((row) => evaluateFilter(plan.filter!, this.#parseMeta(row.metadata)))\n : rows\n return filtered\n .slice(offset, offset + plan.topK)\n .map((row) => this.#project(row, plan, true))\n } else {\n const cursor = await db.query(\n aql`FOR d IN ${db.collection(plan.collection)} RETURN { id: d._key, vec: d.vec, document: d.document, metadata: d.metadata }`\n )\n rows = await cursor.all()\n const filtered = plan.filter\n ? rows.filter((row) => evaluateFilter(plan.filter!, this.#parseMeta(row.metadata)))\n : rows\n return filtered\n .slice(offset, offset + plan.topK)\n .map((row) => this.#project(row, plan, false))\n }\n } catch (err) {\n throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n }\n }\n\n #parseMeta(val: unknown): VectorMetadata {\n if (typeof val === 'string') {\n try {\n return JSON.parse(val) as VectorMetadata\n } catch {\n return {}\n }\n }\n if (val && typeof val === 'object') return val as VectorMetadata\n return {}\n }\n\n #project(row: any, plan: SearchPlan, isKnn: boolean): VectorMatch {\n const proj = plan.projection\n const out: VectorMatch = {}\n if (proj.id) out.id = row.id as string\n if (proj.vector && Array.isArray(row.vec)) out.vector = (row.vec as number[]).map(Number)\n if (proj.document) out.document = (row.document ?? undefined) as string | undefined\n if (proj.metadata) out.metadata = this.#parseMeta(row.metadata)\n if (isKnn && row.score !== undefined && row.score !== null) {\n // APPROX_NEAR_COSINE returns cosine similarity in [0,1]; L2 returns a distance.\n const m = this.#opts.metric ?? 'cosine'\n out.score = m === 'euclidean' ? 1 / (1 + Number(row.score)) : Number(row.score)\n }\n return out\n }\n\n async executeDelete(plan: DeletePlan): Promise<void> {\n const db = await this.#ensure()\n const aql = this.#aql\n try {\n const col = db.collection(plan.collection)\n if (plan.ids && plan.ids.length > 0) {\n await col.removeAll(plan.ids).catch(async () => {\n for (const id of plan.ids!) await col.remove(id).catch(() => undefined)\n })\n } else if (plan.filter) {\n const cursor = await db.query(\n aql`FOR d IN ${col} RETURN { id: d._key, metadata: d.metadata }`\n )\n const rows = await cursor.all()\n const targets = rows\n .filter((row: any) => evaluateFilter(plan.filter!, this.#parseMeta(row.metadata)))\n .map((row: any) => row.id as string)\n if (targets.length > 0) {\n await col.removeAll(targets).catch(async () => {\n for (const id of targets) await col.remove(id).catch(() => undefined)\n })\n }\n } else {\n await col.truncate()\n }\n } catch (err) {\n throw new E_VECTOR_STORE_DELETE_FAILED([String(err)])\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -118,15 +118,19 @@ var FilterBuilder = class FilterBuilder {
|
|
|
118
118
|
}
|
|
119
119
|
return this.orWhere(field, "ne", value);
|
|
120
120
|
}
|
|
121
|
+
/** AND the condition that `field`'s value is one of `values`. */
|
|
121
122
|
whereIn(field, values) {
|
|
122
123
|
return this.where(field, "in", values);
|
|
123
124
|
}
|
|
125
|
+
/** AND the condition that `field`'s value is none of `values`. */
|
|
124
126
|
whereNotIn(field, values) {
|
|
125
127
|
return this.where(field, "nin", values);
|
|
126
128
|
}
|
|
129
|
+
/** AND the condition that `field` is absent (does not exist). */
|
|
127
130
|
whereNull(field) {
|
|
128
131
|
return this.where(field, "exists", false);
|
|
129
132
|
}
|
|
133
|
+
/** AND the condition that `field` is present (exists). */
|
|
130
134
|
whereExists(field) {
|
|
131
135
|
return this.where(field, "exists", true);
|
|
132
136
|
}
|
|
@@ -181,21 +185,44 @@ var VectorQueryBuilder = class extends FilterBuilder {
|
|
|
181
185
|
this.#collection = collection;
|
|
182
186
|
this.#topK = defaultTopK;
|
|
183
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Search by nearest neighbours to a client-supplied query `vector`. Mutually exclusive with the
|
|
190
|
+
* other `near*` clauses.
|
|
191
|
+
*
|
|
192
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
193
|
+
*/
|
|
184
194
|
nearVector(vector) {
|
|
185
195
|
if (this.#near !== void 0) throw new require_batteries_vector_exceptions.E_VECTOR_STORE_QUERY_CONFLICT(["a near* clause was already set"]);
|
|
186
196
|
this.#near = { vector };
|
|
187
197
|
return this;
|
|
188
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Search by nearest neighbours to `text`, embedded server-side by the backend. Mutually exclusive
|
|
201
|
+
* with the other `near*` clauses.
|
|
202
|
+
*
|
|
203
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
204
|
+
*/
|
|
189
205
|
nearText(text) {
|
|
190
206
|
if (this.#near !== void 0) throw new require_batteries_vector_exceptions.E_VECTOR_STORE_QUERY_CONFLICT(["a near* clause was already set"]);
|
|
191
207
|
this.#near = { serverText: text };
|
|
192
208
|
return this;
|
|
193
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Search by nearest neighbours to the stored vector of the record with the given `id`. Mutually
|
|
212
|
+
* exclusive with the other `near*` clauses.
|
|
213
|
+
*
|
|
214
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
215
|
+
*/
|
|
194
216
|
nearId(id) {
|
|
195
217
|
if (this.#near !== void 0) throw new require_batteries_vector_exceptions.E_VECTOR_STORE_QUERY_CONFLICT(["a near* clause was already set"]);
|
|
196
218
|
this.#near = { id };
|
|
197
219
|
return this;
|
|
198
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Declare which fields each match projects (id / vector / document / metadata). Required before a
|
|
223
|
+
* search terminal runs. Accepts {@link SelectArg}s: `'*'`, field names, `[field, config]` tuples,
|
|
224
|
+
* or `{ field: config }` maps.
|
|
225
|
+
*/
|
|
199
226
|
select(...args) {
|
|
200
227
|
this.#selectCalled = true;
|
|
201
228
|
for (const arg of args) if (typeof arg === "string") {
|
|
@@ -223,10 +250,12 @@ var VectorQueryBuilder = class extends FilterBuilder {
|
|
|
223
250
|
}
|
|
224
251
|
return this;
|
|
225
252
|
}
|
|
253
|
+
/** Cap the number of matches returned (the search `topK`). */
|
|
226
254
|
limit(n) {
|
|
227
255
|
this.#topK = n;
|
|
228
256
|
return this;
|
|
229
257
|
}
|
|
258
|
+
/** Skip the first `n` matches before returning results. */
|
|
230
259
|
offset(n) {
|
|
231
260
|
this.#offset = n;
|
|
232
261
|
return this;
|
|
@@ -259,6 +288,7 @@ var VectorQueryBuilder = class extends FilterBuilder {
|
|
|
259
288
|
this.#validateRawFilters(plan.filter);
|
|
260
289
|
return await this.#sink.executeSearch(plan);
|
|
261
290
|
}
|
|
291
|
+
/** Terminal: insert or replace `records` in the collection. */
|
|
262
292
|
async upsert(records) {
|
|
263
293
|
const plan = {
|
|
264
294
|
collection: this.#collection,
|
|
@@ -267,6 +297,7 @@ var VectorQueryBuilder = class extends FilterBuilder {
|
|
|
267
297
|
};
|
|
268
298
|
await this.#sink.executeUpsert(plan);
|
|
269
299
|
}
|
|
300
|
+
/** Terminal: delete records matching the accumulated filter (or the `id IN [...]` fast path). */
|
|
270
301
|
async delete() {
|
|
271
302
|
const ids = this.extractIdsFromFilter();
|
|
272
303
|
const filter = this.buildFilter();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.cjs","names":["#pushOrBranch","#sink","#collection","#topK","#near","#selectCalled","#projection","#offset","#consistency","#run","#validateRawFilters"],"sources":["../../../src/batteries/vector/builder.ts"],"sourcesContent":["/**\n * Knex-style chainable query builder for the vector storage battery.\n *\n * @module @nhtio/adk/batteries/vector/builder\n */\n\nimport { isRawFilter, isFilterCondition } from './filters'\nimport {\n E_VECTOR_STORE_QUERY_CONFLICT,\n E_VECTOR_STORE_PROJECTION_REQUIRED,\n E_VECTOR_STORE_RAW_BINDING_MISMATCH,\n E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR,\n} from './exceptions'\nimport type { VectorRecord, VectorMatch, VectorConsistency } from './types'\nimport type { SearchPlan, UpsertPlan, DeletePlan, Projection } from './plan'\nimport type { VectorFilter, FilterCondition, FilterOperator } from './filters'\n\nconst OP_ALIASES: Record<string, FilterOperator> = {\n '=': 'eq',\n '==': 'eq',\n '===': 'eq',\n '!=': 'ne',\n '<>': 'ne',\n '!==': 'ne',\n '>': 'gt',\n '>=': 'gte',\n '<': 'lt',\n '<=': 'lte',\n 'eq': 'eq',\n 'ne': 'ne',\n 'gt': 'gt',\n 'gte': 'gte',\n 'lt': 'lt',\n 'lte': 'lte',\n 'in': 'in',\n 'nin': 'nin',\n 'exists': 'exists',\n 'contains': 'contains',\n}\nconst normalizeOp = (op: string): FilterOperator => {\n const norm = OP_ALIASES[op]\n if (!norm) throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['builder', op])\n return norm\n}\n\nexport interface PlanSink {\n executeSearch(plan: SearchPlan): Promise<VectorMatch[]>\n executeUpsert(plan: UpsertPlan): Promise<void>\n executeDelete(plan: DeletePlan): Promise<void>\n}\n\nexport type SelectArg =\n | string\n | [string, Record<string, unknown>]\n | Record<string, Record<string, unknown> | true>\n\n/**\n * A callback that receives a fresh filter-only builder, used to express a parenthesized group of\n * conditions — `A AND (B OR C)`, `NOT (…)`, and arbitrary nesting. The callback mutates the builder\n * in place (knex-style); its accumulated conditions become a single nested `VectorFilter`.\n *\n * @see {@link FilterBuilder.where}\n */\nexport type FilterCallback = (qb: FilterBuilder) => void\n\n/**\n * The where-clause surface of the query builder, factored out so a grouping callback can be handed\n * a builder that only exposes filter methods (not `near*`/`select`/`limit` or the terminals).\n *\n * Chained `.where()` ANDs; the first `.orWhere()` snapshots the accumulated AND-list into the first\n * branch of an OR (knex semantics). Any of the where-methods also accepts a {@link FilterCallback}\n * to open a nested group, letting AND and OR mix to any depth.\n */\nclass FilterBuilder {\n protected andConditions: VectorFilter[] = []\n protected orBranches: VectorFilter[][] = []\n\n /** Build a nested group by running `cb` against a fresh {@link FilterBuilder}. */\n protected runGroup(cb: FilterCallback): VectorFilter | undefined {\n const fb = new FilterBuilder()\n cb(fb)\n return fb.buildFilter()\n }\n\n where(cb: FilterCallback): this\n where(a: string, b?: unknown, c?: unknown): this\n where(obj: Record<string, unknown>): this\n where(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n if (typeof a === 'function') {\n const group = this.runGroup(a)\n if (group !== undefined) {\n this.andConditions.push(group)\n }\n return this\n }\n if (typeof a === 'object' && !Array.isArray(a)) {\n for (const key of Object.keys(a)) {\n this.andConditions.push({\n field: key,\n op: 'eq',\n value: a[key] as FilterCondition['value'],\n })\n }\n return this\n }\n const field = a as string\n const value = b !== undefined ? (c !== undefined ? c : b) : b\n const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n this.andConditions.push({ field, op, value: value as FilterCondition['value'] })\n return this\n }\n\n andWhere(cb: FilterCallback): this\n andWhere(a: string, b?: unknown, c?: unknown): this\n andWhere(obj: Record<string, unknown>): this\n andWhere(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n return this.where(a as any, b, c)\n }\n\n /**\n * Open a new OR branch holding a single filter. The accumulated AND-list is contributed as the\n * first OR-group by {@link buildFilter}, so each branch carries only its own condition(s) — that\n * is what makes `where(A).where(B).orWhere(C)` resolve to `(A AND B) OR C`.\n */\n #pushOrBranch(filter: VectorFilter): void {\n this.orBranches.push([filter])\n }\n\n orWhere(cb: FilterCallback): this\n orWhere(field: string, value: unknown): this\n orWhere(field: string, op: FilterOperator, value: unknown): this\n orWhere(field: string | FilterCallback, b?: unknown, c?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.#pushOrBranch(group)\n }\n return this\n }\n const value = c !== undefined ? c : b\n const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n this.#pushOrBranch({ field, op, value: value as FilterCondition['value'] })\n return this\n }\n\n whereNot(cb: FilterCallback): this\n whereNot(field: string, value: unknown): this\n whereNot(field: string | FilterCallback, value?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.andConditions.push({ not: group })\n }\n return this\n }\n return this.where(field, 'ne', value as FilterCondition['value'])\n }\n\n orWhereNot(cb: FilterCallback): this\n orWhereNot(field: string, value: unknown): this\n orWhereNot(field: string | FilterCallback, value?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.#pushOrBranch({ not: group })\n }\n return this\n }\n return this.orWhere(field, 'ne', value)\n }\n\n whereIn(field: string, values: unknown[]): this {\n return this.where(field, 'in', values as FilterCondition['value'])\n }\n\n whereNotIn(field: string, values: unknown[]): this {\n return this.where(field, 'nin', values as FilterCondition['value'])\n }\n\n whereNull(field: string): this {\n return this.where(field, 'exists', false as FilterCondition['value'])\n }\n\n whereExists(field: string): this {\n return this.where(field, 'exists', true as FilterCondition['value'])\n }\n\n whereRaw(sql: string, bindings?: unknown[]): this\n whereRaw(rawObj: { $dialect: string; $raw: unknown; $bindings?: unknown[] }): this\n whereRaw(\n sqlOrObj: string | { $dialect: string; $raw: unknown; $bindings?: unknown[] },\n bindings?: unknown[]\n ): this {\n if (typeof sqlOrObj === 'object') {\n this.andConditions.push({\n $dialect: sqlOrObj.$dialect,\n $raw: sqlOrObj.$raw,\n $bindings: sqlOrObj.$bindings ?? [],\n })\n } else {\n this.andConditions.push({ $dialect: 'sql', $raw: sqlOrObj, $bindings: bindings ?? [] })\n }\n return this\n }\n\n protected buildFilter(): VectorFilter | undefined {\n if (this.andConditions.length === 0 && this.orBranches.length === 0) {\n return undefined\n }\n\n if (this.orBranches.length > 0) {\n const orGroups: VectorFilter[][] = []\n if (this.andConditions.length > 0) {\n orGroups.push(this.andConditions)\n }\n for (const branch of this.orBranches) {\n if (branch.length > 0) {\n orGroups.push(branch)\n }\n }\n if (orGroups.length === 1) {\n return { and: orGroups[0] }\n }\n return { or: orGroups.map((conds) => ({ and: conds })) }\n }\n\n return { and: this.andConditions }\n }\n\n protected extractIdsFromFilter(): string[] {\n const ids: string[] = []\n const only = this.andConditions.length === 1 ? this.andConditions[0] : undefined\n if (\n only &&\n isFilterCondition(only) &&\n only.field === 'id' &&\n only.op === 'in' &&\n Array.isArray(only.value)\n ) {\n ids.push(...(only.value as string[]))\n }\n return ids\n }\n}\n\nclass VectorQueryBuilder extends FilterBuilder implements PromiseLike<VectorMatch[]> {\n #sink: PlanSink\n #collection: string\n #near: { vector: number[] } | { serverText: string } | { id: string } | undefined\n #projection: Projection = { id: false, vector: false, document: false, metadata: false }\n #topK: number\n #offset: number = 0\n #selectCalled: boolean = false\n #consistency: VectorConsistency | undefined\n\n constructor(sink: PlanSink, collection: string, defaultTopK: number) {\n super()\n this.#sink = sink\n this.#collection = collection\n this.#topK = defaultTopK\n }\n\n nearVector(vector: number[]): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { vector }\n return this\n }\n\n nearText(text: string): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { serverText: text }\n return this\n }\n\n nearId(id: string): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { id }\n return this\n }\n\n select(...args: SelectArg[]): this {\n this.#selectCalled = true\n for (const arg of args) {\n if (typeof arg === 'string') {\n if (arg === '*') {\n this.#projection = { id: true, vector: {}, document: {}, metadata: {} }\n } else {\n if (arg === 'id') {\n this.#projection.id = true\n } else if (arg === 'vector') {\n this.#projection.vector = {}\n } else if (arg === 'document') {\n this.#projection.document = {}\n } else if (arg === 'metadata') {\n this.#projection.metadata = {}\n }\n }\n } else if (Array.isArray(arg)) {\n const [field, config] = arg\n if (field === 'vector') {\n this.#projection.vector = config as { name?: string }\n } else if (field === 'document') {\n this.#projection.document = config as { field?: string }\n } else if (field === 'metadata') {\n this.#projection.metadata = config as { fields?: string[] }\n } else if (field === 'id') {\n this.#projection.id = true\n }\n } else if (typeof arg === 'object') {\n for (const key of Object.keys(arg)) {\n if (key === 'vector') {\n this.#projection.vector = arg[key] as { name?: string }\n } else if (key === 'document') {\n this.#projection.document = arg[key] as { field?: string }\n } else if (key === 'metadata') {\n this.#projection.metadata = arg[key] as { fields?: string[] }\n } else if (key === 'id') {\n this.#projection.id = true\n }\n }\n }\n }\n return this\n }\n\n limit(n: number): this {\n this.#topK = n\n return this\n }\n\n offset(n: number): this {\n this.#offset = n\n return this\n }\n\n /**\n * Per-operation read-after-write override for the terminal `.upsert()` / `.delete()`.\n * Universal across adapters: strongly-consistent backends ignore it (no-op), so a chain\n * written for an eventually-consistent backend keeps working verbatim when the adapter is\n * swapped. Precedence: this > the store's `consistency` option > the adapter's declared\n * `capabilities.consistency.default`. See {@link VectorConsistency}.\n */\n consistency(mode: VectorConsistency): this {\n this.#consistency = mode\n return this\n }\n\n then<TR1 = VectorMatch[], TR2 = never>(\n onfulfilled?: ((value: VectorMatch[]) => TR1 | PromiseLike<TR1>) | null,\n onrejected?: ((reason: unknown) => TR2 | PromiseLike<TR2>) | null\n ): PromiseLike<TR1 | TR2> {\n return this.#run().then(onfulfilled as any, onrejected as any)\n }\n\n async #run(): Promise<VectorMatch[]> {\n if (!this.#selectCalled) {\n throw new E_VECTOR_STORE_PROJECTION_REQUIRED()\n }\n\n const filter = this.buildFilter()\n\n const plan: SearchPlan = {\n collection: this.#collection,\n near: this.#near,\n filter,\n topK: this.#topK,\n offset: this.#offset,\n projection: this.#projection,\n }\n\n this.#validateRawFilters(plan.filter)\n\n return await this.#sink.executeSearch(plan)\n }\n\n async upsert(records: VectorRecord[]): Promise<void> {\n const plan: UpsertPlan = {\n collection: this.#collection,\n records,\n consistency: this.#consistency,\n }\n await this.#sink.executeUpsert(plan)\n }\n\n async delete(): Promise<void> {\n const ids = this.extractIdsFromFilter()\n const filter = this.buildFilter()\n\n const plan: DeletePlan = {\n collection: this.#collection,\n ids: ids.length > 0 ? ids : undefined,\n filter: filter && Object.keys(filter).length > 0 ? filter : undefined,\n consistency: this.#consistency,\n }\n\n await this.#sink.executeDelete(plan)\n }\n\n #validateRawFilters(filter: VectorFilter | undefined): void {\n if (!filter) {\n return\n }\n\n if (isRawFilter(filter)) {\n const raw = filter.$raw as string\n const placeholders = (raw.match(/\\?/g) || []).length\n if (placeholders !== filter.$bindings?.length) {\n throw new E_VECTOR_STORE_RAW_BINDING_MISMATCH([placeholders, filter.$bindings?.length ?? 0])\n }\n return\n }\n\n if ('and' in filter && filter.and) {\n for (const f of filter.and) {\n this.#validateRawFilters(f)\n }\n }\n\n if ('or' in filter && filter.or) {\n for (const f of filter.or) {\n this.#validateRawFilters(f)\n }\n }\n\n if ('not' in filter && filter.not) {\n this.#validateRawFilters(filter.not)\n }\n }\n}\n\nexport { VectorQueryBuilder, FilterBuilder }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"builder.cjs","names":["#pushOrBranch","#sink","#collection","#topK","#near","#selectCalled","#projection","#offset","#consistency","#run","#validateRawFilters"],"sources":["../../../src/batteries/vector/builder.ts"],"sourcesContent":["/**\n * Knex-style chainable query builder for the vector storage battery.\n *\n * @module @nhtio/adk/batteries/vector/builder\n */\n\nimport { isRawFilter, isFilterCondition } from './filters'\nimport {\n E_VECTOR_STORE_QUERY_CONFLICT,\n E_VECTOR_STORE_PROJECTION_REQUIRED,\n E_VECTOR_STORE_RAW_BINDING_MISMATCH,\n E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR,\n} from './exceptions'\nimport type { VectorRecord, VectorMatch, VectorConsistency } from './types'\nimport type { SearchPlan, UpsertPlan, DeletePlan, Projection } from './plan'\nimport type { VectorFilter, FilterCondition, FilterOperator } from './filters'\n\nconst OP_ALIASES: Record<string, FilterOperator> = {\n '=': 'eq',\n '==': 'eq',\n '===': 'eq',\n '!=': 'ne',\n '<>': 'ne',\n '!==': 'ne',\n '>': 'gt',\n '>=': 'gte',\n '<': 'lt',\n '<=': 'lte',\n 'eq': 'eq',\n 'ne': 'ne',\n 'gt': 'gt',\n 'gte': 'gte',\n 'lt': 'lt',\n 'lte': 'lte',\n 'in': 'in',\n 'nin': 'nin',\n 'exists': 'exists',\n 'contains': 'contains',\n}\nconst normalizeOp = (op: string): FilterOperator => {\n const norm = OP_ALIASES[op]\n if (!norm) throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['builder', op])\n return norm\n}\n\n/**\n * The execution backend a {@link VectorQueryBuilder} drains its assembled plans into. Implemented\n * by the vector store; the builder produces {@link SearchPlan}/{@link UpsertPlan}/{@link DeletePlan}\n * objects and hands them here rather than touching the adapter directly.\n */\nexport interface PlanSink {\n /** Executes an assembled search plan and resolves the matching records. */\n executeSearch(plan: SearchPlan): Promise<VectorMatch[]>\n /** Executes an assembled upsert plan. */\n executeUpsert(plan: UpsertPlan): Promise<void>\n /** Executes an assembled delete plan. */\n executeDelete(plan: DeletePlan): Promise<void>\n}\n\n/**\n * An argument accepted by {@link VectorQueryBuilder.select} — a field name (or `'*'`), a\n * `[field, config]` tuple, or a `{ field: config }` map selecting and configuring projected fields.\n */\nexport type SelectArg =\n | string\n | [string, Record<string, unknown>]\n | Record<string, Record<string, unknown> | true>\n\n/**\n * A callback that receives a fresh filter-only builder, used to express a parenthesized group of\n * conditions — `A AND (B OR C)`, `NOT (…)`, and arbitrary nesting. The callback mutates the builder\n * in place (knex-style); its accumulated conditions become a single nested `VectorFilter`.\n *\n * @see {@link FilterBuilder.where}\n */\nexport type FilterCallback = (qb: FilterBuilder) => void\n\n/**\n * The where-clause surface of the query builder, factored out so a grouping callback can be handed\n * a builder that only exposes filter methods (not `near*`/`select`/`limit` or the terminals).\n *\n * Chained `.where()` ANDs; the first `.orWhere()` snapshots the accumulated AND-list into the first\n * branch of an OR (knex semantics). Any of the where-methods also accepts a {@link FilterCallback}\n * to open a nested group, letting AND and OR mix to any depth.\n */\nclass FilterBuilder {\n protected andConditions: VectorFilter[] = []\n protected orBranches: VectorFilter[][] = []\n\n /** Build a nested group by running `cb` against a fresh {@link FilterBuilder}. */\n protected runGroup(cb: FilterCallback): VectorFilter | undefined {\n const fb = new FilterBuilder()\n cb(fb)\n return fb.buildFilter()\n }\n\n /** Add a parenthesized condition group via a {@link FilterCallback}; ANDed with prior conditions. */\n where(cb: FilterCallback): this\n /** Add a condition `field op value` (or `field = value` when `c` is omitted); ANDed with prior conditions. */\n where(a: string, b?: unknown, c?: unknown): this\n /** Add equality conditions for each key of `obj`; ANDed with prior conditions. */\n where(obj: Record<string, unknown>): this\n where(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n if (typeof a === 'function') {\n const group = this.runGroup(a)\n if (group !== undefined) {\n this.andConditions.push(group)\n }\n return this\n }\n if (typeof a === 'object' && !Array.isArray(a)) {\n for (const key of Object.keys(a)) {\n this.andConditions.push({\n field: key,\n op: 'eq',\n value: a[key] as FilterCondition['value'],\n })\n }\n return this\n }\n const field = a as string\n const value = b !== undefined ? (c !== undefined ? c : b) : b\n const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n this.andConditions.push({ field, op, value: value as FilterCondition['value'] })\n return this\n }\n\n /** Alias of {@link FilterBuilder.where} (callback group form) for readability in a chain. */\n andWhere(cb: FilterCallback): this\n /** Alias of {@link FilterBuilder.where} (`field op value` form) for readability in a chain. */\n andWhere(a: string, b?: unknown, c?: unknown): this\n /** Alias of {@link FilterBuilder.where} (object form) for readability in a chain. */\n andWhere(obj: Record<string, unknown>): this\n andWhere(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n return this.where(a as any, b, c)\n }\n\n /**\n * Open a new OR branch holding a single filter. The accumulated AND-list is contributed as the\n * first OR-group by {@link buildFilter}, so each branch carries only its own condition(s) — that\n * is what makes `where(A).where(B).orWhere(C)` resolve to `(A AND B) OR C`.\n */\n #pushOrBranch(filter: VectorFilter): void {\n this.orBranches.push([filter])\n }\n\n /** Open a new OR branch holding a parenthesized condition group via a {@link FilterCallback}. */\n orWhere(cb: FilterCallback): this\n /** Open a new OR branch holding the equality condition `field = value`. */\n orWhere(field: string, value: unknown): this\n /** Open a new OR branch holding the condition `field op value`. */\n orWhere(field: string, op: FilterOperator, value: unknown): this\n orWhere(field: string | FilterCallback, b?: unknown, c?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.#pushOrBranch(group)\n }\n return this\n }\n const value = c !== undefined ? c : b\n const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n this.#pushOrBranch({ field, op, value: value as FilterCondition['value'] })\n return this\n }\n\n /** AND a negated parenthesized condition group via a {@link FilterCallback}. */\n whereNot(cb: FilterCallback): this\n /** AND the negated equality condition `field != value`. */\n whereNot(field: string, value: unknown): this\n whereNot(field: string | FilterCallback, value?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.andConditions.push({ not: group })\n }\n return this\n }\n return this.where(field, 'ne', value as FilterCondition['value'])\n }\n\n /** Open a new OR branch holding a negated parenthesized condition group via a {@link FilterCallback}. */\n orWhereNot(cb: FilterCallback): this\n /** Open a new OR branch holding the negated equality condition `field != value`. */\n orWhereNot(field: string, value: unknown): this\n orWhereNot(field: string | FilterCallback, value?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.#pushOrBranch({ not: group })\n }\n return this\n }\n return this.orWhere(field, 'ne', value)\n }\n\n /** AND the condition that `field`'s value is one of `values`. */\n whereIn(field: string, values: unknown[]): this {\n return this.where(field, 'in', values as FilterCondition['value'])\n }\n\n /** AND the condition that `field`'s value is none of `values`. */\n whereNotIn(field: string, values: unknown[]): this {\n return this.where(field, 'nin', values as FilterCondition['value'])\n }\n\n /** AND the condition that `field` is absent (does not exist). */\n whereNull(field: string): this {\n return this.where(field, 'exists', false as FilterCondition['value'])\n }\n\n /** AND the condition that `field` is present (exists). */\n whereExists(field: string): this {\n return this.where(field, 'exists', true as FilterCondition['value'])\n }\n\n /** AND a raw, adapter-dialect filter expressed as SQL text plus positional `bindings`. */\n whereRaw(sql: string, bindings?: unknown[]): this\n /** AND a raw, adapter-dialect filter expressed as a `{ $dialect, $raw, $bindings }` object. */\n whereRaw(rawObj: { $dialect: string; $raw: unknown; $bindings?: unknown[] }): this\n whereRaw(\n sqlOrObj: string | { $dialect: string; $raw: unknown; $bindings?: unknown[] },\n bindings?: unknown[]\n ): this {\n if (typeof sqlOrObj === 'object') {\n this.andConditions.push({\n $dialect: sqlOrObj.$dialect,\n $raw: sqlOrObj.$raw,\n $bindings: sqlOrObj.$bindings ?? [],\n })\n } else {\n this.andConditions.push({ $dialect: 'sql', $raw: sqlOrObj, $bindings: bindings ?? [] })\n }\n return this\n }\n\n protected buildFilter(): VectorFilter | undefined {\n if (this.andConditions.length === 0 && this.orBranches.length === 0) {\n return undefined\n }\n\n if (this.orBranches.length > 0) {\n const orGroups: VectorFilter[][] = []\n if (this.andConditions.length > 0) {\n orGroups.push(this.andConditions)\n }\n for (const branch of this.orBranches) {\n if (branch.length > 0) {\n orGroups.push(branch)\n }\n }\n if (orGroups.length === 1) {\n return { and: orGroups[0] }\n }\n return { or: orGroups.map((conds) => ({ and: conds })) }\n }\n\n return { and: this.andConditions }\n }\n\n protected extractIdsFromFilter(): string[] {\n const ids: string[] = []\n const only = this.andConditions.length === 1 ? this.andConditions[0] : undefined\n if (\n only &&\n isFilterCondition(only) &&\n only.field === 'id' &&\n only.op === 'in' &&\n Array.isArray(only.value)\n ) {\n ids.push(...(only.value as string[]))\n }\n return ids\n }\n}\n\nclass VectorQueryBuilder extends FilterBuilder implements PromiseLike<VectorMatch[]> {\n #sink: PlanSink\n #collection: string\n #near: { vector: number[] } | { serverText: string } | { id: string } | undefined\n #projection: Projection = { id: false, vector: false, document: false, metadata: false }\n #topK: number\n #offset: number = 0\n #selectCalled: boolean = false\n #consistency: VectorConsistency | undefined\n\n constructor(sink: PlanSink, collection: string, defaultTopK: number) {\n super()\n this.#sink = sink\n this.#collection = collection\n this.#topK = defaultTopK\n }\n\n /**\n * Search by nearest neighbours to a client-supplied query `vector`. Mutually exclusive with the\n * other `near*` clauses.\n *\n * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n */\n nearVector(vector: number[]): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { vector }\n return this\n }\n\n /**\n * Search by nearest neighbours to `text`, embedded server-side by the backend. Mutually exclusive\n * with the other `near*` clauses.\n *\n * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n */\n nearText(text: string): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { serverText: text }\n return this\n }\n\n /**\n * Search by nearest neighbours to the stored vector of the record with the given `id`. Mutually\n * exclusive with the other `near*` clauses.\n *\n * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n */\n nearId(id: string): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { id }\n return this\n }\n\n /**\n * Declare which fields each match projects (id / vector / document / metadata). Required before a\n * search terminal runs. Accepts {@link SelectArg}s: `'*'`, field names, `[field, config]` tuples,\n * or `{ field: config }` maps.\n */\n select(...args: SelectArg[]): this {\n this.#selectCalled = true\n for (const arg of args) {\n if (typeof arg === 'string') {\n if (arg === '*') {\n this.#projection = { id: true, vector: {}, document: {}, metadata: {} }\n } else {\n if (arg === 'id') {\n this.#projection.id = true\n } else if (arg === 'vector') {\n this.#projection.vector = {}\n } else if (arg === 'document') {\n this.#projection.document = {}\n } else if (arg === 'metadata') {\n this.#projection.metadata = {}\n }\n }\n } else if (Array.isArray(arg)) {\n const [field, config] = arg\n if (field === 'vector') {\n this.#projection.vector = config as { name?: string }\n } else if (field === 'document') {\n this.#projection.document = config as { field?: string }\n } else if (field === 'metadata') {\n this.#projection.metadata = config as { fields?: string[] }\n } else if (field === 'id') {\n this.#projection.id = true\n }\n } else if (typeof arg === 'object') {\n for (const key of Object.keys(arg)) {\n if (key === 'vector') {\n this.#projection.vector = arg[key] as { name?: string }\n } else if (key === 'document') {\n this.#projection.document = arg[key] as { field?: string }\n } else if (key === 'metadata') {\n this.#projection.metadata = arg[key] as { fields?: string[] }\n } else if (key === 'id') {\n this.#projection.id = true\n }\n }\n }\n }\n return this\n }\n\n /** Cap the number of matches returned (the search `topK`). */\n limit(n: number): this {\n this.#topK = n\n return this\n }\n\n /** Skip the first `n` matches before returning results. */\n offset(n: number): this {\n this.#offset = n\n return this\n }\n\n /**\n * Per-operation read-after-write override for the terminal `.upsert()` / `.delete()`.\n * Universal across adapters: strongly-consistent backends ignore it (no-op), so a chain\n * written for an eventually-consistent backend keeps working verbatim when the adapter is\n * swapped. Precedence: this > the store's `consistency` option > the adapter's declared\n * `capabilities.consistency.default`. See {@link VectorConsistency}.\n */\n consistency(mode: VectorConsistency): this {\n this.#consistency = mode\n return this\n }\n\n then<TR1 = VectorMatch[], TR2 = never>(\n onfulfilled?: ((value: VectorMatch[]) => TR1 | PromiseLike<TR1>) | null,\n onrejected?: ((reason: unknown) => TR2 | PromiseLike<TR2>) | null\n ): PromiseLike<TR1 | TR2> {\n return this.#run().then(onfulfilled as any, onrejected as any)\n }\n\n async #run(): Promise<VectorMatch[]> {\n if (!this.#selectCalled) {\n throw new E_VECTOR_STORE_PROJECTION_REQUIRED()\n }\n\n const filter = this.buildFilter()\n\n const plan: SearchPlan = {\n collection: this.#collection,\n near: this.#near,\n filter,\n topK: this.#topK,\n offset: this.#offset,\n projection: this.#projection,\n }\n\n this.#validateRawFilters(plan.filter)\n\n return await this.#sink.executeSearch(plan)\n }\n\n /** Terminal: insert or replace `records` in the collection. */\n async upsert(records: VectorRecord[]): Promise<void> {\n const plan: UpsertPlan = {\n collection: this.#collection,\n records,\n consistency: this.#consistency,\n }\n await this.#sink.executeUpsert(plan)\n }\n\n /** Terminal: delete records matching the accumulated filter (or the `id IN [...]` fast path). */\n async delete(): Promise<void> {\n const ids = this.extractIdsFromFilter()\n const filter = this.buildFilter()\n\n const plan: DeletePlan = {\n collection: this.#collection,\n ids: ids.length > 0 ? ids : undefined,\n filter: filter && Object.keys(filter).length > 0 ? filter : undefined,\n consistency: this.#consistency,\n }\n\n await this.#sink.executeDelete(plan)\n }\n\n #validateRawFilters(filter: VectorFilter | undefined): void {\n if (!filter) {\n return\n }\n\n if (isRawFilter(filter)) {\n const raw = filter.$raw as string\n const placeholders = (raw.match(/\\?/g) || []).length\n if (placeholders !== filter.$bindings?.length) {\n throw new E_VECTOR_STORE_RAW_BINDING_MISMATCH([placeholders, filter.$bindings?.length ?? 0])\n }\n return\n }\n\n if ('and' in filter && filter.and) {\n for (const f of filter.and) {\n this.#validateRawFilters(f)\n }\n }\n\n if ('or' in filter && filter.or) {\n for (const f of filter.or) {\n this.#validateRawFilters(f)\n }\n }\n\n if ('not' in filter && filter.not) {\n this.#validateRawFilters(filter.not)\n }\n }\n}\n\nexport { VectorQueryBuilder, FilterBuilder }\n"],"mappings":"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"}
|
|
@@ -6,11 +6,23 @@
|
|
|
6
6
|
import type { VectorRecord, VectorMatch, VectorConsistency } from "./types";
|
|
7
7
|
import type { SearchPlan, UpsertPlan, DeletePlan } from "./plan";
|
|
8
8
|
import type { VectorFilter, FilterOperator } from "./filters";
|
|
9
|
+
/**
|
|
10
|
+
* The execution backend a {@link VectorQueryBuilder} drains its assembled plans into. Implemented
|
|
11
|
+
* by the vector store; the builder produces {@link SearchPlan}/{@link UpsertPlan}/{@link DeletePlan}
|
|
12
|
+
* objects and hands them here rather than touching the adapter directly.
|
|
13
|
+
*/
|
|
9
14
|
export interface PlanSink {
|
|
15
|
+
/** Executes an assembled search plan and resolves the matching records. */
|
|
10
16
|
executeSearch(plan: SearchPlan): Promise<VectorMatch[]>;
|
|
17
|
+
/** Executes an assembled upsert plan. */
|
|
11
18
|
executeUpsert(plan: UpsertPlan): Promise<void>;
|
|
19
|
+
/** Executes an assembled delete plan. */
|
|
12
20
|
executeDelete(plan: DeletePlan): Promise<void>;
|
|
13
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* An argument accepted by {@link VectorQueryBuilder.select} — a field name (or `'*'`), a
|
|
24
|
+
* `[field, config]` tuple, or a `{ field: config }` map selecting and configuring projected fields.
|
|
25
|
+
*/
|
|
14
26
|
export type SelectArg = string | [
|
|
15
27
|
string,
|
|
16
28
|
Record<string, unknown>
|
|
@@ -37,24 +49,43 @@ declare class FilterBuilder {
|
|
|
37
49
|
protected orBranches: VectorFilter[][];
|
|
38
50
|
/** Build a nested group by running `cb` against a fresh {@link FilterBuilder}. */
|
|
39
51
|
protected runGroup(cb: FilterCallback): VectorFilter | undefined;
|
|
52
|
+
/** Add a parenthesized condition group via a {@link FilterCallback}; ANDed with prior conditions. */
|
|
40
53
|
where(cb: FilterCallback): this;
|
|
54
|
+
/** Add a condition `field op value` (or `field = value` when `c` is omitted); ANDed with prior conditions. */
|
|
41
55
|
where(a: string, b?: unknown, c?: unknown): this;
|
|
56
|
+
/** Add equality conditions for each key of `obj`; ANDed with prior conditions. */
|
|
42
57
|
where(obj: Record<string, unknown>): this;
|
|
58
|
+
/** Alias of {@link FilterBuilder.where} (callback group form) for readability in a chain. */
|
|
43
59
|
andWhere(cb: FilterCallback): this;
|
|
60
|
+
/** Alias of {@link FilterBuilder.where} (`field op value` form) for readability in a chain. */
|
|
44
61
|
andWhere(a: string, b?: unknown, c?: unknown): this;
|
|
62
|
+
/** Alias of {@link FilterBuilder.where} (object form) for readability in a chain. */
|
|
45
63
|
andWhere(obj: Record<string, unknown>): this;
|
|
64
|
+
/** Open a new OR branch holding a parenthesized condition group via a {@link FilterCallback}. */
|
|
46
65
|
orWhere(cb: FilterCallback): this;
|
|
66
|
+
/** Open a new OR branch holding the equality condition `field = value`. */
|
|
47
67
|
orWhere(field: string, value: unknown): this;
|
|
68
|
+
/** Open a new OR branch holding the condition `field op value`. */
|
|
48
69
|
orWhere(field: string, op: FilterOperator, value: unknown): this;
|
|
70
|
+
/** AND a negated parenthesized condition group via a {@link FilterCallback}. */
|
|
49
71
|
whereNot(cb: FilterCallback): this;
|
|
72
|
+
/** AND the negated equality condition `field != value`. */
|
|
50
73
|
whereNot(field: string, value: unknown): this;
|
|
74
|
+
/** Open a new OR branch holding a negated parenthesized condition group via a {@link FilterCallback}. */
|
|
51
75
|
orWhereNot(cb: FilterCallback): this;
|
|
76
|
+
/** Open a new OR branch holding the negated equality condition `field != value`. */
|
|
52
77
|
orWhereNot(field: string, value: unknown): this;
|
|
78
|
+
/** AND the condition that `field`'s value is one of `values`. */
|
|
53
79
|
whereIn(field: string, values: unknown[]): this;
|
|
80
|
+
/** AND the condition that `field`'s value is none of `values`. */
|
|
54
81
|
whereNotIn(field: string, values: unknown[]): this;
|
|
82
|
+
/** AND the condition that `field` is absent (does not exist). */
|
|
55
83
|
whereNull(field: string): this;
|
|
84
|
+
/** AND the condition that `field` is present (exists). */
|
|
56
85
|
whereExists(field: string): this;
|
|
86
|
+
/** AND a raw, adapter-dialect filter expressed as SQL text plus positional `bindings`. */
|
|
57
87
|
whereRaw(sql: string, bindings?: unknown[]): this;
|
|
88
|
+
/** AND a raw, adapter-dialect filter expressed as a `{ $dialect, $raw, $bindings }` object. */
|
|
58
89
|
whereRaw(rawObj: {
|
|
59
90
|
$dialect: string;
|
|
60
91
|
$raw: unknown;
|
|
@@ -66,11 +97,36 @@ declare class FilterBuilder {
|
|
|
66
97
|
declare class VectorQueryBuilder extends FilterBuilder implements PromiseLike<VectorMatch[]> {
|
|
67
98
|
#private;
|
|
68
99
|
constructor(sink: PlanSink, collection: string, defaultTopK: number);
|
|
100
|
+
/**
|
|
101
|
+
* Search by nearest neighbours to a client-supplied query `vector`. Mutually exclusive with the
|
|
102
|
+
* other `near*` clauses.
|
|
103
|
+
*
|
|
104
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
105
|
+
*/
|
|
69
106
|
nearVector(vector: number[]): this;
|
|
107
|
+
/**
|
|
108
|
+
* Search by nearest neighbours to `text`, embedded server-side by the backend. Mutually exclusive
|
|
109
|
+
* with the other `near*` clauses.
|
|
110
|
+
*
|
|
111
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
112
|
+
*/
|
|
70
113
|
nearText(text: string): this;
|
|
114
|
+
/**
|
|
115
|
+
* Search by nearest neighbours to the stored vector of the record with the given `id`. Mutually
|
|
116
|
+
* exclusive with the other `near*` clauses.
|
|
117
|
+
*
|
|
118
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
119
|
+
*/
|
|
71
120
|
nearId(id: string): this;
|
|
121
|
+
/**
|
|
122
|
+
* Declare which fields each match projects (id / vector / document / metadata). Required before a
|
|
123
|
+
* search terminal runs. Accepts {@link SelectArg}s: `'*'`, field names, `[field, config]` tuples,
|
|
124
|
+
* or `{ field: config }` maps.
|
|
125
|
+
*/
|
|
72
126
|
select(...args: SelectArg[]): this;
|
|
127
|
+
/** Cap the number of matches returned (the search `topK`). */
|
|
73
128
|
limit(n: number): this;
|
|
129
|
+
/** Skip the first `n` matches before returning results. */
|
|
74
130
|
offset(n: number): this;
|
|
75
131
|
/**
|
|
76
132
|
* Per-operation read-after-write override for the terminal `.upsert()` / `.delete()`.
|
|
@@ -81,7 +137,9 @@ declare class VectorQueryBuilder extends FilterBuilder implements PromiseLike<Ve
|
|
|
81
137
|
*/
|
|
82
138
|
consistency(mode: VectorConsistency): this;
|
|
83
139
|
then<TR1 = VectorMatch[], TR2 = never>(onfulfilled?: ((value: VectorMatch[]) => TR1 | PromiseLike<TR1>) | null, onrejected?: ((reason: unknown) => TR2 | PromiseLike<TR2>) | null): PromiseLike<TR1 | TR2>;
|
|
140
|
+
/** Terminal: insert or replace `records` in the collection. */
|
|
84
141
|
upsert(records: VectorRecord[]): Promise<void>;
|
|
142
|
+
/** Terminal: delete records matching the accumulated filter (or the `id IN [...]` fast path). */
|
|
85
143
|
delete(): Promise<void>;
|
|
86
144
|
}
|
|
87
145
|
export { VectorQueryBuilder, FilterBuilder };
|
|
@@ -116,15 +116,19 @@ var FilterBuilder = class FilterBuilder {
|
|
|
116
116
|
}
|
|
117
117
|
return this.orWhere(field, "ne", value);
|
|
118
118
|
}
|
|
119
|
+
/** AND the condition that `field`'s value is one of `values`. */
|
|
119
120
|
whereIn(field, values) {
|
|
120
121
|
return this.where(field, "in", values);
|
|
121
122
|
}
|
|
123
|
+
/** AND the condition that `field`'s value is none of `values`. */
|
|
122
124
|
whereNotIn(field, values) {
|
|
123
125
|
return this.where(field, "nin", values);
|
|
124
126
|
}
|
|
127
|
+
/** AND the condition that `field` is absent (does not exist). */
|
|
125
128
|
whereNull(field) {
|
|
126
129
|
return this.where(field, "exists", false);
|
|
127
130
|
}
|
|
131
|
+
/** AND the condition that `field` is present (exists). */
|
|
128
132
|
whereExists(field) {
|
|
129
133
|
return this.where(field, "exists", true);
|
|
130
134
|
}
|
|
@@ -179,21 +183,44 @@ var VectorQueryBuilder = class extends FilterBuilder {
|
|
|
179
183
|
this.#collection = collection;
|
|
180
184
|
this.#topK = defaultTopK;
|
|
181
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Search by nearest neighbours to a client-supplied query `vector`. Mutually exclusive with the
|
|
188
|
+
* other `near*` clauses.
|
|
189
|
+
*
|
|
190
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
191
|
+
*/
|
|
182
192
|
nearVector(vector) {
|
|
183
193
|
if (this.#near !== void 0) throw new E_VECTOR_STORE_QUERY_CONFLICT(["a near* clause was already set"]);
|
|
184
194
|
this.#near = { vector };
|
|
185
195
|
return this;
|
|
186
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Search by nearest neighbours to `text`, embedded server-side by the backend. Mutually exclusive
|
|
199
|
+
* with the other `near*` clauses.
|
|
200
|
+
*
|
|
201
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
202
|
+
*/
|
|
187
203
|
nearText(text) {
|
|
188
204
|
if (this.#near !== void 0) throw new E_VECTOR_STORE_QUERY_CONFLICT(["a near* clause was already set"]);
|
|
189
205
|
this.#near = { serverText: text };
|
|
190
206
|
return this;
|
|
191
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Search by nearest neighbours to the stored vector of the record with the given `id`. Mutually
|
|
210
|
+
* exclusive with the other `near*` clauses.
|
|
211
|
+
*
|
|
212
|
+
* @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.
|
|
213
|
+
*/
|
|
192
214
|
nearId(id) {
|
|
193
215
|
if (this.#near !== void 0) throw new E_VECTOR_STORE_QUERY_CONFLICT(["a near* clause was already set"]);
|
|
194
216
|
this.#near = { id };
|
|
195
217
|
return this;
|
|
196
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Declare which fields each match projects (id / vector / document / metadata). Required before a
|
|
221
|
+
* search terminal runs. Accepts {@link SelectArg}s: `'*'`, field names, `[field, config]` tuples,
|
|
222
|
+
* or `{ field: config }` maps.
|
|
223
|
+
*/
|
|
197
224
|
select(...args) {
|
|
198
225
|
this.#selectCalled = true;
|
|
199
226
|
for (const arg of args) if (typeof arg === "string") {
|
|
@@ -221,10 +248,12 @@ var VectorQueryBuilder = class extends FilterBuilder {
|
|
|
221
248
|
}
|
|
222
249
|
return this;
|
|
223
250
|
}
|
|
251
|
+
/** Cap the number of matches returned (the search `topK`). */
|
|
224
252
|
limit(n) {
|
|
225
253
|
this.#topK = n;
|
|
226
254
|
return this;
|
|
227
255
|
}
|
|
256
|
+
/** Skip the first `n` matches before returning results. */
|
|
228
257
|
offset(n) {
|
|
229
258
|
this.#offset = n;
|
|
230
259
|
return this;
|
|
@@ -257,6 +286,7 @@ var VectorQueryBuilder = class extends FilterBuilder {
|
|
|
257
286
|
this.#validateRawFilters(plan.filter);
|
|
258
287
|
return await this.#sink.executeSearch(plan);
|
|
259
288
|
}
|
|
289
|
+
/** Terminal: insert or replace `records` in the collection. */
|
|
260
290
|
async upsert(records) {
|
|
261
291
|
const plan = {
|
|
262
292
|
collection: this.#collection,
|
|
@@ -265,6 +295,7 @@ var VectorQueryBuilder = class extends FilterBuilder {
|
|
|
265
295
|
};
|
|
266
296
|
await this.#sink.executeUpsert(plan);
|
|
267
297
|
}
|
|
298
|
+
/** Terminal: delete records matching the accumulated filter (or the `id IN [...]` fast path). */
|
|
268
299
|
async delete() {
|
|
269
300
|
const ids = this.extractIdsFromFilter();
|
|
270
301
|
const filter = this.buildFilter();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.mjs","names":["#pushOrBranch","#sink","#collection","#topK","#near","#selectCalled","#projection","#offset","#consistency","#run","#validateRawFilters"],"sources":["../../../src/batteries/vector/builder.ts"],"sourcesContent":["/**\n * Knex-style chainable query builder for the vector storage battery.\n *\n * @module @nhtio/adk/batteries/vector/builder\n */\n\nimport { isRawFilter, isFilterCondition } from './filters'\nimport {\n E_VECTOR_STORE_QUERY_CONFLICT,\n E_VECTOR_STORE_PROJECTION_REQUIRED,\n E_VECTOR_STORE_RAW_BINDING_MISMATCH,\n E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR,\n} from './exceptions'\nimport type { VectorRecord, VectorMatch, VectorConsistency } from './types'\nimport type { SearchPlan, UpsertPlan, DeletePlan, Projection } from './plan'\nimport type { VectorFilter, FilterCondition, FilterOperator } from './filters'\n\nconst OP_ALIASES: Record<string, FilterOperator> = {\n '=': 'eq',\n '==': 'eq',\n '===': 'eq',\n '!=': 'ne',\n '<>': 'ne',\n '!==': 'ne',\n '>': 'gt',\n '>=': 'gte',\n '<': 'lt',\n '<=': 'lte',\n 'eq': 'eq',\n 'ne': 'ne',\n 'gt': 'gt',\n 'gte': 'gte',\n 'lt': 'lt',\n 'lte': 'lte',\n 'in': 'in',\n 'nin': 'nin',\n 'exists': 'exists',\n 'contains': 'contains',\n}\nconst normalizeOp = (op: string): FilterOperator => {\n const norm = OP_ALIASES[op]\n if (!norm) throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['builder', op])\n return norm\n}\n\nexport interface PlanSink {\n executeSearch(plan: SearchPlan): Promise<VectorMatch[]>\n executeUpsert(plan: UpsertPlan): Promise<void>\n executeDelete(plan: DeletePlan): Promise<void>\n}\n\nexport type SelectArg =\n | string\n | [string, Record<string, unknown>]\n | Record<string, Record<string, unknown> | true>\n\n/**\n * A callback that receives a fresh filter-only builder, used to express a parenthesized group of\n * conditions — `A AND (B OR C)`, `NOT (…)`, and arbitrary nesting. The callback mutates the builder\n * in place (knex-style); its accumulated conditions become a single nested `VectorFilter`.\n *\n * @see {@link FilterBuilder.where}\n */\nexport type FilterCallback = (qb: FilterBuilder) => void\n\n/**\n * The where-clause surface of the query builder, factored out so a grouping callback can be handed\n * a builder that only exposes filter methods (not `near*`/`select`/`limit` or the terminals).\n *\n * Chained `.where()` ANDs; the first `.orWhere()` snapshots the accumulated AND-list into the first\n * branch of an OR (knex semantics). Any of the where-methods also accepts a {@link FilterCallback}\n * to open a nested group, letting AND and OR mix to any depth.\n */\nclass FilterBuilder {\n protected andConditions: VectorFilter[] = []\n protected orBranches: VectorFilter[][] = []\n\n /** Build a nested group by running `cb` against a fresh {@link FilterBuilder}. */\n protected runGroup(cb: FilterCallback): VectorFilter | undefined {\n const fb = new FilterBuilder()\n cb(fb)\n return fb.buildFilter()\n }\n\n where(cb: FilterCallback): this\n where(a: string, b?: unknown, c?: unknown): this\n where(obj: Record<string, unknown>): this\n where(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n if (typeof a === 'function') {\n const group = this.runGroup(a)\n if (group !== undefined) {\n this.andConditions.push(group)\n }\n return this\n }\n if (typeof a === 'object' && !Array.isArray(a)) {\n for (const key of Object.keys(a)) {\n this.andConditions.push({\n field: key,\n op: 'eq',\n value: a[key] as FilterCondition['value'],\n })\n }\n return this\n }\n const field = a as string\n const value = b !== undefined ? (c !== undefined ? c : b) : b\n const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n this.andConditions.push({ field, op, value: value as FilterCondition['value'] })\n return this\n }\n\n andWhere(cb: FilterCallback): this\n andWhere(a: string, b?: unknown, c?: unknown): this\n andWhere(obj: Record<string, unknown>): this\n andWhere(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n return this.where(a as any, b, c)\n }\n\n /**\n * Open a new OR branch holding a single filter. The accumulated AND-list is contributed as the\n * first OR-group by {@link buildFilter}, so each branch carries only its own condition(s) — that\n * is what makes `where(A).where(B).orWhere(C)` resolve to `(A AND B) OR C`.\n */\n #pushOrBranch(filter: VectorFilter): void {\n this.orBranches.push([filter])\n }\n\n orWhere(cb: FilterCallback): this\n orWhere(field: string, value: unknown): this\n orWhere(field: string, op: FilterOperator, value: unknown): this\n orWhere(field: string | FilterCallback, b?: unknown, c?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.#pushOrBranch(group)\n }\n return this\n }\n const value = c !== undefined ? c : b\n const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n this.#pushOrBranch({ field, op, value: value as FilterCondition['value'] })\n return this\n }\n\n whereNot(cb: FilterCallback): this\n whereNot(field: string, value: unknown): this\n whereNot(field: string | FilterCallback, value?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.andConditions.push({ not: group })\n }\n return this\n }\n return this.where(field, 'ne', value as FilterCondition['value'])\n }\n\n orWhereNot(cb: FilterCallback): this\n orWhereNot(field: string, value: unknown): this\n orWhereNot(field: string | FilterCallback, value?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.#pushOrBranch({ not: group })\n }\n return this\n }\n return this.orWhere(field, 'ne', value)\n }\n\n whereIn(field: string, values: unknown[]): this {\n return this.where(field, 'in', values as FilterCondition['value'])\n }\n\n whereNotIn(field: string, values: unknown[]): this {\n return this.where(field, 'nin', values as FilterCondition['value'])\n }\n\n whereNull(field: string): this {\n return this.where(field, 'exists', false as FilterCondition['value'])\n }\n\n whereExists(field: string): this {\n return this.where(field, 'exists', true as FilterCondition['value'])\n }\n\n whereRaw(sql: string, bindings?: unknown[]): this\n whereRaw(rawObj: { $dialect: string; $raw: unknown; $bindings?: unknown[] }): this\n whereRaw(\n sqlOrObj: string | { $dialect: string; $raw: unknown; $bindings?: unknown[] },\n bindings?: unknown[]\n ): this {\n if (typeof sqlOrObj === 'object') {\n this.andConditions.push({\n $dialect: sqlOrObj.$dialect,\n $raw: sqlOrObj.$raw,\n $bindings: sqlOrObj.$bindings ?? [],\n })\n } else {\n this.andConditions.push({ $dialect: 'sql', $raw: sqlOrObj, $bindings: bindings ?? [] })\n }\n return this\n }\n\n protected buildFilter(): VectorFilter | undefined {\n if (this.andConditions.length === 0 && this.orBranches.length === 0) {\n return undefined\n }\n\n if (this.orBranches.length > 0) {\n const orGroups: VectorFilter[][] = []\n if (this.andConditions.length > 0) {\n orGroups.push(this.andConditions)\n }\n for (const branch of this.orBranches) {\n if (branch.length > 0) {\n orGroups.push(branch)\n }\n }\n if (orGroups.length === 1) {\n return { and: orGroups[0] }\n }\n return { or: orGroups.map((conds) => ({ and: conds })) }\n }\n\n return { and: this.andConditions }\n }\n\n protected extractIdsFromFilter(): string[] {\n const ids: string[] = []\n const only = this.andConditions.length === 1 ? this.andConditions[0] : undefined\n if (\n only &&\n isFilterCondition(only) &&\n only.field === 'id' &&\n only.op === 'in' &&\n Array.isArray(only.value)\n ) {\n ids.push(...(only.value as string[]))\n }\n return ids\n }\n}\n\nclass VectorQueryBuilder extends FilterBuilder implements PromiseLike<VectorMatch[]> {\n #sink: PlanSink\n #collection: string\n #near: { vector: number[] } | { serverText: string } | { id: string } | undefined\n #projection: Projection = { id: false, vector: false, document: false, metadata: false }\n #topK: number\n #offset: number = 0\n #selectCalled: boolean = false\n #consistency: VectorConsistency | undefined\n\n constructor(sink: PlanSink, collection: string, defaultTopK: number) {\n super()\n this.#sink = sink\n this.#collection = collection\n this.#topK = defaultTopK\n }\n\n nearVector(vector: number[]): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { vector }\n return this\n }\n\n nearText(text: string): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { serverText: text }\n return this\n }\n\n nearId(id: string): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { id }\n return this\n }\n\n select(...args: SelectArg[]): this {\n this.#selectCalled = true\n for (const arg of args) {\n if (typeof arg === 'string') {\n if (arg === '*') {\n this.#projection = { id: true, vector: {}, document: {}, metadata: {} }\n } else {\n if (arg === 'id') {\n this.#projection.id = true\n } else if (arg === 'vector') {\n this.#projection.vector = {}\n } else if (arg === 'document') {\n this.#projection.document = {}\n } else if (arg === 'metadata') {\n this.#projection.metadata = {}\n }\n }\n } else if (Array.isArray(arg)) {\n const [field, config] = arg\n if (field === 'vector') {\n this.#projection.vector = config as { name?: string }\n } else if (field === 'document') {\n this.#projection.document = config as { field?: string }\n } else if (field === 'metadata') {\n this.#projection.metadata = config as { fields?: string[] }\n } else if (field === 'id') {\n this.#projection.id = true\n }\n } else if (typeof arg === 'object') {\n for (const key of Object.keys(arg)) {\n if (key === 'vector') {\n this.#projection.vector = arg[key] as { name?: string }\n } else if (key === 'document') {\n this.#projection.document = arg[key] as { field?: string }\n } else if (key === 'metadata') {\n this.#projection.metadata = arg[key] as { fields?: string[] }\n } else if (key === 'id') {\n this.#projection.id = true\n }\n }\n }\n }\n return this\n }\n\n limit(n: number): this {\n this.#topK = n\n return this\n }\n\n offset(n: number): this {\n this.#offset = n\n return this\n }\n\n /**\n * Per-operation read-after-write override for the terminal `.upsert()` / `.delete()`.\n * Universal across adapters: strongly-consistent backends ignore it (no-op), so a chain\n * written for an eventually-consistent backend keeps working verbatim when the adapter is\n * swapped. Precedence: this > the store's `consistency` option > the adapter's declared\n * `capabilities.consistency.default`. See {@link VectorConsistency}.\n */\n consistency(mode: VectorConsistency): this {\n this.#consistency = mode\n return this\n }\n\n then<TR1 = VectorMatch[], TR2 = never>(\n onfulfilled?: ((value: VectorMatch[]) => TR1 | PromiseLike<TR1>) | null,\n onrejected?: ((reason: unknown) => TR2 | PromiseLike<TR2>) | null\n ): PromiseLike<TR1 | TR2> {\n return this.#run().then(onfulfilled as any, onrejected as any)\n }\n\n async #run(): Promise<VectorMatch[]> {\n if (!this.#selectCalled) {\n throw new E_VECTOR_STORE_PROJECTION_REQUIRED()\n }\n\n const filter = this.buildFilter()\n\n const plan: SearchPlan = {\n collection: this.#collection,\n near: this.#near,\n filter,\n topK: this.#topK,\n offset: this.#offset,\n projection: this.#projection,\n }\n\n this.#validateRawFilters(plan.filter)\n\n return await this.#sink.executeSearch(plan)\n }\n\n async upsert(records: VectorRecord[]): Promise<void> {\n const plan: UpsertPlan = {\n collection: this.#collection,\n records,\n consistency: this.#consistency,\n }\n await this.#sink.executeUpsert(plan)\n }\n\n async delete(): Promise<void> {\n const ids = this.extractIdsFromFilter()\n const filter = this.buildFilter()\n\n const plan: DeletePlan = {\n collection: this.#collection,\n ids: ids.length > 0 ? ids : undefined,\n filter: filter && Object.keys(filter).length > 0 ? filter : undefined,\n consistency: this.#consistency,\n }\n\n await this.#sink.executeDelete(plan)\n }\n\n #validateRawFilters(filter: VectorFilter | undefined): void {\n if (!filter) {\n return\n }\n\n if (isRawFilter(filter)) {\n const raw = filter.$raw as string\n const placeholders = (raw.match(/\\?/g) || []).length\n if (placeholders !== filter.$bindings?.length) {\n throw new E_VECTOR_STORE_RAW_BINDING_MISMATCH([placeholders, filter.$bindings?.length ?? 0])\n }\n return\n }\n\n if ('and' in filter && filter.and) {\n for (const f of filter.and) {\n this.#validateRawFilters(f)\n }\n }\n\n if ('or' in filter && filter.or) {\n for (const f of filter.or) {\n this.#validateRawFilters(f)\n }\n }\n\n if ('not' in filter && filter.not) {\n this.#validateRawFilters(filter.not)\n }\n }\n}\n\nexport { VectorQueryBuilder, FilterBuilder }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"builder.mjs","names":["#pushOrBranch","#sink","#collection","#topK","#near","#selectCalled","#projection","#offset","#consistency","#run","#validateRawFilters"],"sources":["../../../src/batteries/vector/builder.ts"],"sourcesContent":["/**\n * Knex-style chainable query builder for the vector storage battery.\n *\n * @module @nhtio/adk/batteries/vector/builder\n */\n\nimport { isRawFilter, isFilterCondition } from './filters'\nimport {\n E_VECTOR_STORE_QUERY_CONFLICT,\n E_VECTOR_STORE_PROJECTION_REQUIRED,\n E_VECTOR_STORE_RAW_BINDING_MISMATCH,\n E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR,\n} from './exceptions'\nimport type { VectorRecord, VectorMatch, VectorConsistency } from './types'\nimport type { SearchPlan, UpsertPlan, DeletePlan, Projection } from './plan'\nimport type { VectorFilter, FilterCondition, FilterOperator } from './filters'\n\nconst OP_ALIASES: Record<string, FilterOperator> = {\n '=': 'eq',\n '==': 'eq',\n '===': 'eq',\n '!=': 'ne',\n '<>': 'ne',\n '!==': 'ne',\n '>': 'gt',\n '>=': 'gte',\n '<': 'lt',\n '<=': 'lte',\n 'eq': 'eq',\n 'ne': 'ne',\n 'gt': 'gt',\n 'gte': 'gte',\n 'lt': 'lt',\n 'lte': 'lte',\n 'in': 'in',\n 'nin': 'nin',\n 'exists': 'exists',\n 'contains': 'contains',\n}\nconst normalizeOp = (op: string): FilterOperator => {\n const norm = OP_ALIASES[op]\n if (!norm) throw new E_VECTOR_STORE_UNSUPPORTED_FILTER_OPERATOR(['builder', op])\n return norm\n}\n\n/**\n * The execution backend a {@link VectorQueryBuilder} drains its assembled plans into. Implemented\n * by the vector store; the builder produces {@link SearchPlan}/{@link UpsertPlan}/{@link DeletePlan}\n * objects and hands them here rather than touching the adapter directly.\n */\nexport interface PlanSink {\n /** Executes an assembled search plan and resolves the matching records. */\n executeSearch(plan: SearchPlan): Promise<VectorMatch[]>\n /** Executes an assembled upsert plan. */\n executeUpsert(plan: UpsertPlan): Promise<void>\n /** Executes an assembled delete plan. */\n executeDelete(plan: DeletePlan): Promise<void>\n}\n\n/**\n * An argument accepted by {@link VectorQueryBuilder.select} — a field name (or `'*'`), a\n * `[field, config]` tuple, or a `{ field: config }` map selecting and configuring projected fields.\n */\nexport type SelectArg =\n | string\n | [string, Record<string, unknown>]\n | Record<string, Record<string, unknown> | true>\n\n/**\n * A callback that receives a fresh filter-only builder, used to express a parenthesized group of\n * conditions — `A AND (B OR C)`, `NOT (…)`, and arbitrary nesting. The callback mutates the builder\n * in place (knex-style); its accumulated conditions become a single nested `VectorFilter`.\n *\n * @see {@link FilterBuilder.where}\n */\nexport type FilterCallback = (qb: FilterBuilder) => void\n\n/**\n * The where-clause surface of the query builder, factored out so a grouping callback can be handed\n * a builder that only exposes filter methods (not `near*`/`select`/`limit` or the terminals).\n *\n * Chained `.where()` ANDs; the first `.orWhere()` snapshots the accumulated AND-list into the first\n * branch of an OR (knex semantics). Any of the where-methods also accepts a {@link FilterCallback}\n * to open a nested group, letting AND and OR mix to any depth.\n */\nclass FilterBuilder {\n protected andConditions: VectorFilter[] = []\n protected orBranches: VectorFilter[][] = []\n\n /** Build a nested group by running `cb` against a fresh {@link FilterBuilder}. */\n protected runGroup(cb: FilterCallback): VectorFilter | undefined {\n const fb = new FilterBuilder()\n cb(fb)\n return fb.buildFilter()\n }\n\n /** Add a parenthesized condition group via a {@link FilterCallback}; ANDed with prior conditions. */\n where(cb: FilterCallback): this\n /** Add a condition `field op value` (or `field = value` when `c` is omitted); ANDed with prior conditions. */\n where(a: string, b?: unknown, c?: unknown): this\n /** Add equality conditions for each key of `obj`; ANDed with prior conditions. */\n where(obj: Record<string, unknown>): this\n where(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n if (typeof a === 'function') {\n const group = this.runGroup(a)\n if (group !== undefined) {\n this.andConditions.push(group)\n }\n return this\n }\n if (typeof a === 'object' && !Array.isArray(a)) {\n for (const key of Object.keys(a)) {\n this.andConditions.push({\n field: key,\n op: 'eq',\n value: a[key] as FilterCondition['value'],\n })\n }\n return this\n }\n const field = a as string\n const value = b !== undefined ? (c !== undefined ? c : b) : b\n const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n this.andConditions.push({ field, op, value: value as FilterCondition['value'] })\n return this\n }\n\n /** Alias of {@link FilterBuilder.where} (callback group form) for readability in a chain. */\n andWhere(cb: FilterCallback): this\n /** Alias of {@link FilterBuilder.where} (`field op value` form) for readability in a chain. */\n andWhere(a: string, b?: unknown, c?: unknown): this\n /** Alias of {@link FilterBuilder.where} (object form) for readability in a chain. */\n andWhere(obj: Record<string, unknown>): this\n andWhere(a: string | Record<string, unknown> | FilterCallback, b?: unknown, c?: unknown): this {\n return this.where(a as any, b, c)\n }\n\n /**\n * Open a new OR branch holding a single filter. The accumulated AND-list is contributed as the\n * first OR-group by {@link buildFilter}, so each branch carries only its own condition(s) — that\n * is what makes `where(A).where(B).orWhere(C)` resolve to `(A AND B) OR C`.\n */\n #pushOrBranch(filter: VectorFilter): void {\n this.orBranches.push([filter])\n }\n\n /** Open a new OR branch holding a parenthesized condition group via a {@link FilterCallback}. */\n orWhere(cb: FilterCallback): this\n /** Open a new OR branch holding the equality condition `field = value`. */\n orWhere(field: string, value: unknown): this\n /** Open a new OR branch holding the condition `field op value`. */\n orWhere(field: string, op: FilterOperator, value: unknown): this\n orWhere(field: string | FilterCallback, b?: unknown, c?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.#pushOrBranch(group)\n }\n return this\n }\n const value = c !== undefined ? c : b\n const op = c !== undefined ? normalizeOp(b as string) : 'eq'\n this.#pushOrBranch({ field, op, value: value as FilterCondition['value'] })\n return this\n }\n\n /** AND a negated parenthesized condition group via a {@link FilterCallback}. */\n whereNot(cb: FilterCallback): this\n /** AND the negated equality condition `field != value`. */\n whereNot(field: string, value: unknown): this\n whereNot(field: string | FilterCallback, value?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.andConditions.push({ not: group })\n }\n return this\n }\n return this.where(field, 'ne', value as FilterCondition['value'])\n }\n\n /** Open a new OR branch holding a negated parenthesized condition group via a {@link FilterCallback}. */\n orWhereNot(cb: FilterCallback): this\n /** Open a new OR branch holding the negated equality condition `field != value`. */\n orWhereNot(field: string, value: unknown): this\n orWhereNot(field: string | FilterCallback, value?: unknown): this {\n if (typeof field === 'function') {\n const group = this.runGroup(field)\n if (group !== undefined) {\n this.#pushOrBranch({ not: group })\n }\n return this\n }\n return this.orWhere(field, 'ne', value)\n }\n\n /** AND the condition that `field`'s value is one of `values`. */\n whereIn(field: string, values: unknown[]): this {\n return this.where(field, 'in', values as FilterCondition['value'])\n }\n\n /** AND the condition that `field`'s value is none of `values`. */\n whereNotIn(field: string, values: unknown[]): this {\n return this.where(field, 'nin', values as FilterCondition['value'])\n }\n\n /** AND the condition that `field` is absent (does not exist). */\n whereNull(field: string): this {\n return this.where(field, 'exists', false as FilterCondition['value'])\n }\n\n /** AND the condition that `field` is present (exists). */\n whereExists(field: string): this {\n return this.where(field, 'exists', true as FilterCondition['value'])\n }\n\n /** AND a raw, adapter-dialect filter expressed as SQL text plus positional `bindings`. */\n whereRaw(sql: string, bindings?: unknown[]): this\n /** AND a raw, adapter-dialect filter expressed as a `{ $dialect, $raw, $bindings }` object. */\n whereRaw(rawObj: { $dialect: string; $raw: unknown; $bindings?: unknown[] }): this\n whereRaw(\n sqlOrObj: string | { $dialect: string; $raw: unknown; $bindings?: unknown[] },\n bindings?: unknown[]\n ): this {\n if (typeof sqlOrObj === 'object') {\n this.andConditions.push({\n $dialect: sqlOrObj.$dialect,\n $raw: sqlOrObj.$raw,\n $bindings: sqlOrObj.$bindings ?? [],\n })\n } else {\n this.andConditions.push({ $dialect: 'sql', $raw: sqlOrObj, $bindings: bindings ?? [] })\n }\n return this\n }\n\n protected buildFilter(): VectorFilter | undefined {\n if (this.andConditions.length === 0 && this.orBranches.length === 0) {\n return undefined\n }\n\n if (this.orBranches.length > 0) {\n const orGroups: VectorFilter[][] = []\n if (this.andConditions.length > 0) {\n orGroups.push(this.andConditions)\n }\n for (const branch of this.orBranches) {\n if (branch.length > 0) {\n orGroups.push(branch)\n }\n }\n if (orGroups.length === 1) {\n return { and: orGroups[0] }\n }\n return { or: orGroups.map((conds) => ({ and: conds })) }\n }\n\n return { and: this.andConditions }\n }\n\n protected extractIdsFromFilter(): string[] {\n const ids: string[] = []\n const only = this.andConditions.length === 1 ? this.andConditions[0] : undefined\n if (\n only &&\n isFilterCondition(only) &&\n only.field === 'id' &&\n only.op === 'in' &&\n Array.isArray(only.value)\n ) {\n ids.push(...(only.value as string[]))\n }\n return ids\n }\n}\n\nclass VectorQueryBuilder extends FilterBuilder implements PromiseLike<VectorMatch[]> {\n #sink: PlanSink\n #collection: string\n #near: { vector: number[] } | { serverText: string } | { id: string } | undefined\n #projection: Projection = { id: false, vector: false, document: false, metadata: false }\n #topK: number\n #offset: number = 0\n #selectCalled: boolean = false\n #consistency: VectorConsistency | undefined\n\n constructor(sink: PlanSink, collection: string, defaultTopK: number) {\n super()\n this.#sink = sink\n this.#collection = collection\n this.#topK = defaultTopK\n }\n\n /**\n * Search by nearest neighbours to a client-supplied query `vector`. Mutually exclusive with the\n * other `near*` clauses.\n *\n * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n */\n nearVector(vector: number[]): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { vector }\n return this\n }\n\n /**\n * Search by nearest neighbours to `text`, embedded server-side by the backend. Mutually exclusive\n * with the other `near*` clauses.\n *\n * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n */\n nearText(text: string): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { serverText: text }\n return this\n }\n\n /**\n * Search by nearest neighbours to the stored vector of the record with the given `id`. Mutually\n * exclusive with the other `near*` clauses.\n *\n * @throws {@link @nhtio/adk/batteries!E_VECTOR_STORE_QUERY_CONFLICT} when a `near*` clause is already set.\n */\n nearId(id: string): this {\n if (this.#near !== undefined) {\n throw new E_VECTOR_STORE_QUERY_CONFLICT(['a near* clause was already set'])\n }\n this.#near = { id }\n return this\n }\n\n /**\n * Declare which fields each match projects (id / vector / document / metadata). Required before a\n * search terminal runs. Accepts {@link SelectArg}s: `'*'`, field names, `[field, config]` tuples,\n * or `{ field: config }` maps.\n */\n select(...args: SelectArg[]): this {\n this.#selectCalled = true\n for (const arg of args) {\n if (typeof arg === 'string') {\n if (arg === '*') {\n this.#projection = { id: true, vector: {}, document: {}, metadata: {} }\n } else {\n if (arg === 'id') {\n this.#projection.id = true\n } else if (arg === 'vector') {\n this.#projection.vector = {}\n } else if (arg === 'document') {\n this.#projection.document = {}\n } else if (arg === 'metadata') {\n this.#projection.metadata = {}\n }\n }\n } else if (Array.isArray(arg)) {\n const [field, config] = arg\n if (field === 'vector') {\n this.#projection.vector = config as { name?: string }\n } else if (field === 'document') {\n this.#projection.document = config as { field?: string }\n } else if (field === 'metadata') {\n this.#projection.metadata = config as { fields?: string[] }\n } else if (field === 'id') {\n this.#projection.id = true\n }\n } else if (typeof arg === 'object') {\n for (const key of Object.keys(arg)) {\n if (key === 'vector') {\n this.#projection.vector = arg[key] as { name?: string }\n } else if (key === 'document') {\n this.#projection.document = arg[key] as { field?: string }\n } else if (key === 'metadata') {\n this.#projection.metadata = arg[key] as { fields?: string[] }\n } else if (key === 'id') {\n this.#projection.id = true\n }\n }\n }\n }\n return this\n }\n\n /** Cap the number of matches returned (the search `topK`). */\n limit(n: number): this {\n this.#topK = n\n return this\n }\n\n /** Skip the first `n` matches before returning results. */\n offset(n: number): this {\n this.#offset = n\n return this\n }\n\n /**\n * Per-operation read-after-write override for the terminal `.upsert()` / `.delete()`.\n * Universal across adapters: strongly-consistent backends ignore it (no-op), so a chain\n * written for an eventually-consistent backend keeps working verbatim when the adapter is\n * swapped. Precedence: this > the store's `consistency` option > the adapter's declared\n * `capabilities.consistency.default`. See {@link VectorConsistency}.\n */\n consistency(mode: VectorConsistency): this {\n this.#consistency = mode\n return this\n }\n\n then<TR1 = VectorMatch[], TR2 = never>(\n onfulfilled?: ((value: VectorMatch[]) => TR1 | PromiseLike<TR1>) | null,\n onrejected?: ((reason: unknown) => TR2 | PromiseLike<TR2>) | null\n ): PromiseLike<TR1 | TR2> {\n return this.#run().then(onfulfilled as any, onrejected as any)\n }\n\n async #run(): Promise<VectorMatch[]> {\n if (!this.#selectCalled) {\n throw new E_VECTOR_STORE_PROJECTION_REQUIRED()\n }\n\n const filter = this.buildFilter()\n\n const plan: SearchPlan = {\n collection: this.#collection,\n near: this.#near,\n filter,\n topK: this.#topK,\n offset: this.#offset,\n projection: this.#projection,\n }\n\n this.#validateRawFilters(plan.filter)\n\n return await this.#sink.executeSearch(plan)\n }\n\n /** Terminal: insert or replace `records` in the collection. */\n async upsert(records: VectorRecord[]): Promise<void> {\n const plan: UpsertPlan = {\n collection: this.#collection,\n records,\n consistency: this.#consistency,\n }\n await this.#sink.executeUpsert(plan)\n }\n\n /** Terminal: delete records matching the accumulated filter (or the `id IN [...]` fast path). */\n async delete(): Promise<void> {\n const ids = this.extractIdsFromFilter()\n const filter = this.buildFilter()\n\n const plan: DeletePlan = {\n collection: this.#collection,\n ids: ids.length > 0 ? ids : undefined,\n filter: filter && Object.keys(filter).length > 0 ? filter : undefined,\n consistency: this.#consistency,\n }\n\n await this.#sink.executeDelete(plan)\n }\n\n #validateRawFilters(filter: VectorFilter | undefined): void {\n if (!filter) {\n return\n }\n\n if (isRawFilter(filter)) {\n const raw = filter.$raw as string\n const placeholders = (raw.match(/\\?/g) || []).length\n if (placeholders !== filter.$bindings?.length) {\n throw new E_VECTOR_STORE_RAW_BINDING_MISMATCH([placeholders, filter.$bindings?.length ?? 0])\n }\n return\n }\n\n if ('and' in filter && filter.and) {\n for (const f of filter.and) {\n this.#validateRawFilters(f)\n }\n }\n\n if ('or' in filter && filter.or) {\n for (const f of filter.or) {\n this.#validateRawFilters(f)\n }\n }\n\n if ('not' in filter && filter.not) {\n this.#validateRawFilters(filter.not)\n }\n }\n}\n\nexport { VectorQueryBuilder, FilterBuilder }\n"],"mappings":"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"}
|