@nhtio/adk 1.20260607.2 → 1.20260609.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +230 -0
- package/batteries/embeddings/openai/adapter.cjs +1 -1
- package/batteries/embeddings/openai/adapter.mjs +1 -1
- package/batteries/embeddings/openai/exceptions.cjs +1 -1
- package/batteries/embeddings/openai/exceptions.mjs +1 -1
- package/batteries/embeddings/openai/types.d.ts +7 -0
- package/batteries/embeddings/webllm/adapter.cjs +1 -1
- package/batteries/embeddings/webllm/adapter.mjs +1 -1
- package/batteries/embeddings/webllm/exceptions.cjs +1 -1
- package/batteries/embeddings/webllm/exceptions.mjs +1 -1
- package/batteries/llm/chat_common/helpers.d.ts +165 -0
- package/batteries/llm/chat_common/types.d.ts +309 -0
- package/batteries/llm/index.d.ts +5 -0
- package/batteries/llm/ollama/adapter.cjs +736 -0
- package/batteries/llm/ollama/adapter.cjs.map +1 -0
- package/batteries/llm/ollama/adapter.d.ts +64 -0
- package/batteries/llm/ollama/adapter.mjs +734 -0
- package/batteries/llm/ollama/adapter.mjs.map +1 -0
- package/batteries/llm/ollama/exceptions.cjs +105 -0
- package/batteries/llm/ollama/exceptions.cjs.map +1 -0
- package/batteries/llm/ollama/exceptions.d.ts +112 -0
- package/batteries/llm/ollama/exceptions.mjs +96 -0
- package/batteries/llm/ollama/exceptions.mjs.map +1 -0
- package/batteries/llm/ollama/helpers.cjs +487 -0
- package/batteries/llm/ollama/helpers.cjs.map +1 -0
- package/batteries/llm/ollama/helpers.d.ts +158 -0
- package/batteries/llm/ollama/helpers.mjs +450 -0
- package/batteries/llm/ollama/helpers.mjs.map +1 -0
- package/batteries/llm/ollama/index.d.ts +29 -0
- package/batteries/llm/ollama/types.cjs +2 -0
- package/batteries/llm/ollama/types.d.ts +334 -0
- package/batteries/llm/ollama/types.mjs +0 -0
- package/batteries/llm/ollama/validation.cjs +130 -0
- package/batteries/llm/ollama/validation.cjs.map +1 -0
- package/batteries/llm/ollama/validation.d.ts +31 -0
- package/batteries/llm/ollama/validation.mjs +127 -0
- package/batteries/llm/ollama/validation.mjs.map +1 -0
- package/batteries/llm/ollama.cjs +54 -0
- package/batteries/llm/ollama.mjs +6 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs +36 -19
- package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/adapter.mjs +23 -6
- package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/exceptions.cjs +1 -1
- package/batteries/llm/openai_chat_completions/exceptions.mjs +1 -1
- package/batteries/llm/openai_chat_completions/helpers.cjs +80 -320
- package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/helpers.d.ts +68 -144
- package/batteries/llm/openai_chat_completions/helpers.mjs +40 -280
- package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/types.d.ts +273 -181
- package/batteries/llm/openai_chat_completions/validation.cjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/validation.mjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions.cjs +29 -28
- package/batteries/llm/openai_chat_completions.mjs +2 -1
- package/batteries/llm/webllm_chat_completions/adapter.cjs +38 -19
- package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.d.ts +18 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs +25 -6
- package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/exceptions.cjs +1 -1
- package/batteries/llm/webllm_chat_completions/exceptions.mjs +1 -1
- package/batteries/llm/webllm_chat_completions/helpers.cjs +29 -28
- package/batteries/llm/webllm_chat_completions/helpers.mjs +2 -1
- package/batteries/llm/webllm_chat_completions/types.d.ts +21 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs +13 -1
- package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/validation.d.ts +12 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs +13 -1
- package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions.cjs +29 -28
- package/batteries/llm/webllm_chat_completions.mjs +2 -1
- package/batteries/llm.cjs +44 -28
- package/batteries/llm.mjs +9 -4
- package/batteries/storage/flydrive.cjs +1 -1
- package/batteries/storage/flydrive.mjs +1 -1
- package/batteries/storage/in_memory/index.d.ts +1 -1
- package/batteries/storage/in_memory.cjs +2 -2
- package/batteries/storage/in_memory.cjs.map +1 -1
- package/batteries/storage/in_memory.mjs +2 -2
- package/batteries/storage/in_memory.mjs.map +1 -1
- package/batteries/storage/opfs/index.d.ts +19 -0
- package/batteries/storage/opfs.cjs +1 -1
- package/batteries/storage/opfs.cjs.map +1 -1
- package/batteries/storage/opfs.mjs +1 -1
- package/batteries/storage/opfs.mjs.map +1 -1
- package/batteries/tools/_shared/index.d.ts +121 -0
- package/batteries/tools/_shared.cjs +157 -0
- package/batteries/tools/_shared.cjs.map +1 -0
- package/batteries/tools/_shared.mjs +149 -0
- package/batteries/tools/_shared.mjs.map +1 -0
- package/batteries/tools/color.cjs +3 -2
- package/batteries/tools/color.cjs.map +1 -1
- package/batteries/tools/color.mjs +3 -2
- package/batteries/tools/color.mjs.map +1 -1
- package/batteries/tools/comparison.cjs +4 -3
- package/batteries/tools/comparison.cjs.map +1 -1
- package/batteries/tools/comparison.mjs +4 -3
- package/batteries/tools/comparison.mjs.map +1 -1
- package/batteries/tools/data_structure.cjs +30 -10
- package/batteries/tools/data_structure.cjs.map +1 -1
- package/batteries/tools/data_structure.mjs +30 -10
- package/batteries/tools/data_structure.mjs.map +1 -1
- package/batteries/tools/datetime_extended.cjs +5 -10
- package/batteries/tools/datetime_extended.cjs.map +1 -1
- package/batteries/tools/datetime_extended.mjs +5 -10
- package/batteries/tools/datetime_extended.mjs.map +1 -1
- package/batteries/tools/datetime_math.cjs +2 -2
- package/batteries/tools/datetime_math.mjs +2 -2
- package/batteries/tools/encoding.cjs +13 -4
- package/batteries/tools/encoding.cjs.map +1 -1
- package/batteries/tools/encoding.mjs +13 -4
- package/batteries/tools/encoding.mjs.map +1 -1
- package/batteries/tools/formatting.cjs +4 -4
- package/batteries/tools/formatting.cjs.map +1 -1
- package/batteries/tools/formatting.mjs +4 -4
- package/batteries/tools/formatting.mjs.map +1 -1
- package/batteries/tools/geo_basics.cjs +2 -2
- package/batteries/tools/geo_basics.mjs +2 -2
- package/batteries/tools/index.d.ts +3 -0
- package/batteries/tools/math.cjs +10 -8
- package/batteries/tools/math.cjs.map +1 -1
- package/batteries/tools/math.mjs +10 -8
- package/batteries/tools/math.mjs.map +1 -1
- package/batteries/tools/memory.cjs +5 -5
- package/batteries/tools/memory.mjs +5 -5
- package/batteries/tools/parsing.cjs +9 -5
- package/batteries/tools/parsing.cjs.map +1 -1
- package/batteries/tools/parsing.mjs +9 -5
- package/batteries/tools/parsing.mjs.map +1 -1
- package/batteries/tools/retrievables.cjs +4 -4
- package/batteries/tools/retrievables.mjs +4 -4
- package/batteries/tools/scrapper/exceptions.d.ts +21 -0
- package/batteries/tools/scrapper/index.d.ts +172 -0
- package/batteries/tools/scrapper/shared.d.ts +139 -0
- package/batteries/tools/scrapper.cjs +8 -0
- package/batteries/tools/scrapper.mjs +2 -0
- package/batteries/tools/searxng/exceptions.d.ts +21 -0
- package/batteries/tools/searxng/index.d.ts +177 -0
- package/batteries/tools/searxng.cjs +6 -0
- package/batteries/tools/searxng.mjs +2 -0
- package/batteries/tools/standing_instructions.cjs +4 -4
- package/batteries/tools/standing_instructions.mjs +4 -4
- package/batteries/tools/statistics.cjs +54 -43
- package/batteries/tools/statistics.cjs.map +1 -1
- package/batteries/tools/statistics.mjs +54 -43
- package/batteries/tools/statistics.mjs.map +1 -1
- package/batteries/tools/string_processing.cjs +5 -5
- package/batteries/tools/string_processing.cjs.map +1 -1
- package/batteries/tools/string_processing.mjs +5 -5
- package/batteries/tools/string_processing.mjs.map +1 -1
- package/batteries/tools/structured_data.cjs +8 -13
- package/batteries/tools/structured_data.cjs.map +1 -1
- package/batteries/tools/structured_data.mjs +8 -13
- package/batteries/tools/structured_data.mjs.map +1 -1
- package/batteries/tools/text_analysis.cjs +3 -3
- package/batteries/tools/text_analysis.mjs +3 -3
- package/batteries/tools/text_comparison.cjs +2 -2
- package/batteries/tools/text_comparison.mjs +2 -2
- package/batteries/tools/time.cjs +2 -2
- package/batteries/tools/time.mjs +2 -2
- package/batteries/tools/unit_conversion.cjs +10 -8
- package/batteries/tools/unit_conversion.cjs.map +1 -1
- package/batteries/tools/unit_conversion.mjs +10 -8
- package/batteries/tools/unit_conversion.mjs.map +1 -1
- package/batteries/tools/web_retrieval/index.d.ts +186 -0
- package/batteries/tools/web_retrieval.cjs +206 -0
- package/batteries/tools/web_retrieval.cjs.map +1 -0
- package/batteries/tools/web_retrieval.mjs +201 -0
- package/batteries/tools/web_retrieval.mjs.map +1 -0
- package/batteries/tools.cjs +15 -0
- package/batteries/tools.mjs +4 -1
- package/batteries/vector/arangodb/index.d.ts +2 -0
- package/batteries/vector/arangodb.cjs +2 -1
- package/batteries/vector/arangodb.cjs.map +1 -1
- package/batteries/vector/arangodb.mjs +2 -1
- package/batteries/vector/arangodb.mjs.map +1 -1
- package/batteries/vector/builder.cjs +31 -0
- package/batteries/vector/builder.cjs.map +1 -1
- package/batteries/vector/builder.d.ts +58 -0
- package/batteries/vector/builder.mjs +31 -0
- package/batteries/vector/builder.mjs.map +1 -1
- package/batteries/vector/chroma/index.d.ts +4 -0
- package/batteries/vector/chroma.cjs +3 -0
- package/batteries/vector/chroma.cjs.map +1 -1
- package/batteries/vector/chroma.mjs +3 -0
- package/batteries/vector/chroma.mjs.map +1 -1
- package/batteries/vector/clickhouse/index.d.ts +2 -0
- package/batteries/vector/clickhouse.cjs +2 -1
- package/batteries/vector/clickhouse.cjs.map +1 -1
- package/batteries/vector/clickhouse.mjs +2 -1
- package/batteries/vector/clickhouse.mjs.map +1 -1
- package/batteries/vector/cloudflare/index.d.ts +2 -0
- package/batteries/vector/cloudflare.cjs +2 -1
- package/batteries/vector/cloudflare.cjs.map +1 -1
- package/batteries/vector/cloudflare.mjs +2 -1
- package/batteries/vector/cloudflare.mjs.map +1 -1
- package/batteries/vector/conformance/index.d.ts +22 -0
- package/batteries/vector/conformance.cjs +22 -0
- package/batteries/vector/conformance.cjs.map +1 -1
- package/batteries/vector/conformance.mjs +22 -0
- package/batteries/vector/conformance.mjs.map +1 -1
- package/batteries/vector/contract.cjs +22 -0
- package/batteries/vector/contract.cjs.map +1 -1
- package/batteries/vector/contract.d.ts +51 -0
- package/batteries/vector/contract.mjs +22 -0
- package/batteries/vector/contract.mjs.map +1 -1
- package/batteries/vector/couchbase/index.d.ts +2 -0
- package/batteries/vector/couchbase.cjs +2 -1
- package/batteries/vector/couchbase.cjs.map +1 -1
- package/batteries/vector/couchbase.mjs +2 -1
- package/batteries/vector/couchbase.mjs.map +1 -1
- package/batteries/vector/duckdb/index.d.ts +2 -0
- package/batteries/vector/duckdb.cjs +2 -1
- package/batteries/vector/duckdb.cjs.map +1 -1
- package/batteries/vector/duckdb.mjs +2 -1
- package/batteries/vector/duckdb.mjs.map +1 -1
- package/batteries/vector/elasticsearch/index.d.ts +2 -0
- package/batteries/vector/elasticsearch.cjs +2 -1
- package/batteries/vector/elasticsearch.cjs.map +1 -1
- package/batteries/vector/elasticsearch.mjs +2 -1
- package/batteries/vector/elasticsearch.mjs.map +1 -1
- package/batteries/vector/exceptions.cjs +1 -1
- package/batteries/vector/exceptions.mjs +1 -1
- package/batteries/vector/factory.cjs +6 -0
- package/batteries/vector/factory.cjs.map +1 -1
- package/batteries/vector/factory.d.ts +14 -0
- package/batteries/vector/factory.mjs +6 -0
- package/batteries/vector/factory.mjs.map +1 -1
- package/batteries/vector/filters.cjs +22 -1
- package/batteries/vector/filters.cjs.map +1 -1
- package/batteries/vector/filters.d.ts +38 -0
- package/batteries/vector/filters.mjs +22 -1
- package/batteries/vector/filters.mjs.map +1 -1
- package/batteries/vector/helpers.cjs +13 -0
- package/batteries/vector/helpers.cjs.map +1 -1
- package/batteries/vector/helpers.d.ts +14 -0
- package/batteries/vector/helpers.mjs +13 -0
- package/batteries/vector/helpers.mjs.map +1 -1
- package/batteries/vector/hnswlib/index.d.ts +2 -0
- package/batteries/vector/hnswlib.cjs +2 -1
- package/batteries/vector/hnswlib.cjs.map +1 -1
- package/batteries/vector/hnswlib.mjs +2 -1
- package/batteries/vector/hnswlib.mjs.map +1 -1
- package/batteries/vector/in_memory/index.d.ts +1 -0
- package/batteries/vector/in_memory.cjs +1 -0
- package/batteries/vector/in_memory.cjs.map +1 -1
- package/batteries/vector/in_memory.mjs +1 -0
- package/batteries/vector/in_memory.mjs.map +1 -1
- package/batteries/vector/lancedb/index.d.ts +2 -0
- package/batteries/vector/lancedb.cjs +2 -1
- package/batteries/vector/lancedb.cjs.map +1 -1
- package/batteries/vector/lancedb.mjs +2 -1
- package/batteries/vector/lancedb.mjs.map +1 -1
- package/batteries/vector/mariadb/index.d.ts +2 -0
- package/batteries/vector/mariadb.cjs +2 -1
- package/batteries/vector/mariadb.cjs.map +1 -1
- package/batteries/vector/mariadb.mjs +2 -1
- package/batteries/vector/mariadb.mjs.map +1 -1
- package/batteries/vector/meilisearch/index.d.ts +2 -0
- package/batteries/vector/meilisearch.cjs +2 -1
- package/batteries/vector/meilisearch.cjs.map +1 -1
- package/batteries/vector/meilisearch.mjs +2 -1
- package/batteries/vector/meilisearch.mjs.map +1 -1
- package/batteries/vector/migrate.cjs +18 -1
- package/batteries/vector/migrate.cjs.map +1 -1
- package/batteries/vector/migrate.d.ts +31 -0
- package/batteries/vector/migrate.mjs +18 -1
- package/batteries/vector/migrate.mjs.map +1 -1
- package/batteries/vector/milvus/index.d.ts +5 -0
- package/batteries/vector/milvus.cjs +4 -0
- package/batteries/vector/milvus.cjs.map +1 -1
- package/batteries/vector/milvus.mjs +4 -0
- package/batteries/vector/milvus.mjs.map +1 -1
- package/batteries/vector/mongodb/index.d.ts +2 -0
- package/batteries/vector/mongodb.cjs +2 -1
- package/batteries/vector/mongodb.cjs.map +1 -1
- package/batteries/vector/mongodb.mjs +2 -1
- package/batteries/vector/mongodb.mjs.map +1 -1
- package/batteries/vector/neo4j/index.d.ts +2 -0
- package/batteries/vector/neo4j.cjs +2 -1
- package/batteries/vector/neo4j.cjs.map +1 -1
- package/batteries/vector/neo4j.mjs +2 -1
- package/batteries/vector/neo4j.mjs.map +1 -1
- package/batteries/vector/opensearch/index.d.ts +2 -0
- package/batteries/vector/opensearch.cjs +2 -1
- package/batteries/vector/opensearch.cjs.map +1 -1
- package/batteries/vector/opensearch.mjs +2 -1
- package/batteries/vector/opensearch.mjs.map +1 -1
- package/batteries/vector/oracle23ai/index.d.ts +2 -0
- package/batteries/vector/oracle23ai.cjs +2 -1
- package/batteries/vector/oracle23ai.cjs.map +1 -1
- package/batteries/vector/oracle23ai.mjs +2 -1
- package/batteries/vector/oracle23ai.mjs.map +1 -1
- package/batteries/vector/orama/index.d.ts +1 -0
- package/batteries/vector/orama.cjs +1 -0
- package/batteries/vector/orama.cjs.map +1 -1
- package/batteries/vector/orama.mjs +1 -0
- package/batteries/vector/orama.mjs.map +1 -1
- package/batteries/vector/pgvector/index.d.ts +9 -2
- package/batteries/vector/pgvector.cjs +4 -0
- package/batteries/vector/pgvector.cjs.map +1 -1
- package/batteries/vector/pgvector.mjs +4 -0
- package/batteries/vector/pgvector.mjs.map +1 -1
- package/batteries/vector/pinecone/index.d.ts +5 -0
- package/batteries/vector/pinecone.cjs +3 -1
- package/batteries/vector/pinecone.cjs.map +1 -1
- package/batteries/vector/pinecone.mjs +3 -1
- package/batteries/vector/pinecone.mjs.map +1 -1
- package/batteries/vector/plan.d.ts +27 -0
- package/batteries/vector/qdrant/index.d.ts +5 -0
- package/batteries/vector/qdrant.cjs +4 -0
- package/batteries/vector/qdrant.cjs.map +1 -1
- package/batteries/vector/qdrant.mjs +4 -0
- package/batteries/vector/qdrant.mjs.map +1 -1
- package/batteries/vector/redis/index.d.ts +2 -0
- package/batteries/vector/redis.cjs +2 -1
- package/batteries/vector/redis.cjs.map +1 -1
- package/batteries/vector/redis.mjs +2 -1
- package/batteries/vector/redis.mjs.map +1 -1
- package/batteries/vector/retrievable.cjs +9 -1
- package/batteries/vector/retrievable.cjs.map +1 -1
- package/batteries/vector/retrievable.mjs +9 -1
- package/batteries/vector/retrievable.mjs.map +1 -1
- package/batteries/vector/retrievable_glue.d.ts +21 -0
- package/batteries/vector/s3vectors/index.d.ts +2 -0
- package/batteries/vector/s3vectors.cjs +2 -1
- package/batteries/vector/s3vectors.cjs.map +1 -1
- package/batteries/vector/s3vectors.mjs +2 -1
- package/batteries/vector/s3vectors.mjs.map +1 -1
- package/batteries/vector/schema.cjs +28 -0
- package/batteries/vector/schema.cjs.map +1 -1
- package/batteries/vector/schema.d.ts +39 -0
- package/batteries/vector/schema.mjs +28 -0
- package/batteries/vector/schema.mjs.map +1 -1
- package/batteries/vector/solr/index.d.ts +2 -0
- package/batteries/vector/solr.cjs +2 -1
- package/batteries/vector/solr.cjs.map +1 -1
- package/batteries/vector/solr.mjs +2 -1
- package/batteries/vector/solr.mjs.map +1 -1
- package/batteries/vector/sqlite_vec/index.d.ts +6 -3
- package/batteries/vector/sqlite_vec.cjs +2 -0
- package/batteries/vector/sqlite_vec.cjs.map +1 -1
- package/batteries/vector/sqlite_vec.mjs +2 -0
- package/batteries/vector/sqlite_vec.mjs.map +1 -1
- package/batteries/vector/surrealdb/index.d.ts +2 -0
- package/batteries/vector/surrealdb.cjs +2 -1
- package/batteries/vector/surrealdb.cjs.map +1 -1
- package/batteries/vector/surrealdb.mjs +2 -1
- package/batteries/vector/surrealdb.mjs.map +1 -1
- package/batteries/vector/types.d.ts +27 -0
- package/batteries/vector/typesense/index.d.ts +2 -0
- package/batteries/vector/typesense.cjs +2 -1
- package/batteries/vector/typesense.cjs.map +1 -1
- package/batteries/vector/typesense.mjs +2 -1
- package/batteries/vector/typesense.mjs.map +1 -1
- package/batteries/vector/validation.cjs +14 -0
- package/batteries/vector/validation.cjs.map +1 -1
- package/batteries/vector/validation.d.ts +14 -0
- package/batteries/vector/validation.mjs +14 -0
- package/batteries/vector/validation.mjs.map +1 -1
- package/batteries/vector/vector_store_constructor.cjs +1 -1
- package/batteries/vector/vector_store_constructor.cjs.map +1 -1
- package/batteries/vector/vector_store_constructor.d.ts +1 -1
- package/batteries/vector/vector_store_constructor.mjs +1 -1
- package/batteries/vector/vector_store_constructor.mjs.map +1 -1
- package/batteries/vector/vespa/index.d.ts +2 -0
- package/batteries/vector/vespa.cjs +2 -1
- package/batteries/vector/vespa.cjs.map +1 -1
- package/batteries/vector/vespa.mjs +2 -1
- package/batteries/vector/vespa.mjs.map +1 -1
- package/batteries/vector/weaviate/index.d.ts +2 -0
- package/batteries/vector/weaviate.cjs +2 -1
- package/batteries/vector/weaviate.cjs.map +1 -1
- package/batteries/vector/weaviate.mjs +2 -1
- package/batteries/vector/weaviate.mjs.map +1 -1
- package/batteries.cjs +58 -28
- package/batteries.mjs +12 -5
- package/{common-BT0nfCi9.mjs → common-DYDUi99O.mjs} +9 -9
- package/common-DYDUi99O.mjs.map +1 -0
- package/{common-Cj8TaQ9U.js → common-DZl3ADJs.js} +9 -9
- package/common-DZl3ADJs.js.map +1 -0
- package/common.cjs +7 -7
- package/common.mjs +7 -7
- package/{dispatch_runner-DPcS7Y_M.mjs → dispatch_runner--ZhdDWRZ.mjs} +27 -5
- package/{dispatch_runner-DPcS7Y_M.mjs.map → dispatch_runner--ZhdDWRZ.mjs.map} +1 -1
- package/{dispatch_runner-BHBNupqp.js → dispatch_runner-nHDKkxye.js} +27 -5
- package/{dispatch_runner-BHBNupqp.js.map → dispatch_runner-nHDKkxye.js.map} +1 -1
- package/dispatch_runner.cjs +1 -1
- package/dispatch_runner.d.ts +1 -1
- package/dispatch_runner.mjs +1 -1
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs.map +1 -1
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.d.ts +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.mjs +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.mjs.map +1 -1
- package/eslint/rules/no_model_in_tool_handler.cjs +1 -0
- package/eslint/rules/no_model_in_tool_handler.cjs.map +1 -1
- package/eslint/rules/no_model_in_tool_handler.d.ts +1 -0
- package/eslint/rules/no_model_in_tool_handler.mjs +1 -0
- package/eslint/rules/no_model_in_tool_handler.mjs.map +1 -1
- package/eslint/rules/require_validator_any_required.cjs +1 -0
- package/eslint/rules/require_validator_any_required.cjs.map +1 -1
- package/eslint/rules/require_validator_any_required.d.ts +1 -0
- package/eslint/rules/require_validator_any_required.mjs +1 -0
- package/eslint/rules/require_validator_any_required.mjs.map +1 -1
- package/eslint/rules/thought_payload_requires_replay_tag.cjs +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.cjs.map +1 -1
- package/eslint/rules/thought_payload_requires_replay_tag.d.ts +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.mjs +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.mjs.map +1 -1
- package/eslint/rules/token_encoding_requires_context_window.cjs +1 -0
- package/eslint/rules/token_encoding_requires_context_window.cjs.map +1 -1
- package/eslint/rules/token_encoding_requires_context_window.d.ts +1 -0
- package/eslint/rules/token_encoding_requires_context_window.mjs +1 -0
- package/eslint/rules/token_encoding_requires_context_window.mjs.map +1 -1
- package/eslint/rules.cjs +1 -1
- package/eslint/rules.mjs +1 -1
- package/eslint.cjs +2 -2
- package/eslint.mjs +2 -2
- package/{exceptions-BeWH2FwP.mjs → exceptions-BDhN0Xzr.mjs} +3 -2
- package/exceptions-BDhN0Xzr.mjs.map +1 -0
- package/{exceptions-CitH5wZI.js → exceptions-BRXrUKiW.js} +3 -2
- package/exceptions-BRXrUKiW.js.map +1 -0
- package/exceptions.cjs +2 -2
- package/exceptions.mjs +2 -2
- package/factories.cjs +1 -1
- package/factories.mjs +1 -1
- package/forge.cjs +4 -4
- package/forge.d.ts +1 -1
- package/forge.mjs +4 -4
- package/guards.cjs +9 -9
- package/guards.mjs +9 -9
- package/helpers-DSTFxTiC.js +497 -0
- package/helpers-DSTFxTiC.js.map +1 -0
- package/helpers-xhrQbMAG.mjs +306 -0
- package/helpers-xhrQbMAG.mjs.map +1 -0
- package/index.cjs +12 -12
- package/index.mjs +12 -12
- package/lib/classes/base_exception.d.ts +1 -0
- package/lib/classes/media.d.ts +10 -0
- package/lib/classes/retrievable.d.ts +1 -1
- package/lib/classes/spooled_json_artifact.d.ts +1 -1
- package/lib/classes/spooled_markdown_artifact.d.ts +1 -0
- package/lib/classes/tokenizable.d.ts +3 -0
- package/lib/classes/tool.d.ts +8 -0
- package/lib/classes/turn_gate.d.ts +6 -0
- package/lib/dispatch_runner.d.ts +4 -32
- package/lib/helpers/bignum.cjs +82 -0
- package/lib/helpers/bignum.cjs.map +1 -0
- package/lib/helpers/bignum.d.ts +52 -0
- package/lib/helpers/bignum.mjs +74 -0
- package/lib/helpers/bignum.mjs.map +1 -0
- package/lib/turn_runner.d.ts +1 -1
- package/lib/types/dispatch_runner.d.ts +83 -0
- package/lib/utils/exceptions.d.ts +1 -1
- package/lib/utils/retry.cjs.map +1 -1
- package/lib/utils/retry.d.ts +2 -0
- package/lib/utils/retry.mjs.map +1 -1
- package/mcp/adk-docs-corpus.json +1 -1
- package/package.json +259 -204
- package/{runtime-j92CNi5z.mjs → runtime-Bz5zA8wc.mjs} +2 -2
- package/{runtime-j92CNi5z.mjs.map → runtime-Bz5zA8wc.mjs.map} +1 -1
- package/{runtime-MFFcJrRv.js → runtime-DslE1aBw.js} +2 -2
- package/{runtime-MFFcJrRv.js.map → runtime-DslE1aBw.js.map} +1 -1
- package/scrapper-BHM1mCde.mjs +432 -0
- package/scrapper-BHM1mCde.mjs.map +1 -0
- package/scrapper-BeweWurk.js +462 -0
- package/scrapper-BeweWurk.js.map +1 -0
- package/searxng-BJFulNcK.mjs +247 -0
- package/searxng-BJFulNcK.mjs.map +1 -0
- package/searxng-B_D--V5q.js +265 -0
- package/searxng-B_D--V5q.js.map +1 -0
- package/skills/adk-assembly/SKILL.md +2 -2
- package/{spooled_artifact-CHoZgWwI.mjs → spooled_artifact-7eePq7JA.mjs} +5 -5
- package/{spooled_artifact-CHoZgWwI.mjs.map → spooled_artifact-7eePq7JA.mjs.map} +1 -1
- package/{spooled_artifact-BTq6Nzfy.js → spooled_artifact-DX8LLyUX.js} +5 -5
- package/{spooled_artifact-BTq6Nzfy.js.map → spooled_artifact-DX8LLyUX.js.map} +1 -1
- package/spooled_artifact.cjs +2 -2
- package/spooled_artifact.mjs +2 -2
- package/{spooled_markdown_artifact-CALSDxIx.js → spooled_markdown_artifact-ClX72lek.js} +4 -4
- package/spooled_markdown_artifact-ClX72lek.js.map +1 -0
- package/{spooled_markdown_artifact-Ci5UL7l4.mjs → spooled_markdown_artifact-wkrBF3oX.mjs} +4 -4
- package/spooled_markdown_artifact-wkrBF3oX.mjs.map +1 -0
- package/{thought-D34QQZZ9.mjs → thought-B_vxAiKU.mjs} +5 -5
- package/{thought-D34QQZZ9.mjs.map → thought-B_vxAiKU.mjs.map} +1 -1
- package/{thought-BbwhJ1wb.js → thought-DLwpF7MI.js} +5 -5
- package/{thought-BbwhJ1wb.js.map → thought-DLwpF7MI.js.map} +1 -1
- package/{tool-CVyZkFC7.js → tool-D5WGVIcI.js} +4 -4
- package/{tool-CVyZkFC7.js.map → tool-D5WGVIcI.js.map} +1 -1
- package/{tool-CMhaDRNd.mjs → tool-wMYMVl60.mjs} +4 -4
- package/{tool-CMhaDRNd.mjs.map → tool-wMYMVl60.mjs.map} +1 -1
- package/{tool_call-CV5qVNlb.mjs → tool_call-B4-_-vjG.mjs} +5 -5
- package/tool_call-B4-_-vjG.mjs.map +1 -0
- package/{tool_call-Db68hB7y.js → tool_call-DixVlW40.js} +5 -5
- package/tool_call-DixVlW40.js.map +1 -0
- package/{tool_registry-D1pSSlsd.mjs → tool_registry-791Vrjtf.mjs} +4 -3
- package/tool_registry-791Vrjtf.mjs.map +1 -0
- package/{tool_registry-DYUYqXvo.js → tool_registry-CKJPze3j.js} +4 -3
- package/tool_registry-CKJPze3j.js.map +1 -0
- package/{turn_runner-DqWHNP80.js → turn_runner-HXImLGIn.js} +7 -7
- package/turn_runner-HXImLGIn.js.map +1 -0
- package/{turn_runner-fg1Wc3dK.mjs → turn_runner-ZyYO-Kti.mjs} +7 -7
- package/turn_runner-ZyYO-Kti.mjs.map +1 -0
- package/turn_runner.cjs +1 -1
- package/turn_runner.mjs +1 -1
- package/types.d.ts +1 -1
- package/common-BT0nfCi9.mjs.map +0 -1
- package/common-Cj8TaQ9U.js.map +0 -1
- package/exceptions-BeWH2FwP.mjs.map +0 -1
- package/exceptions-CitH5wZI.js.map +0 -1
- package/spooled_markdown_artifact-CALSDxIx.js.map +0 -1
- package/spooled_markdown_artifact-Ci5UL7l4.mjs.map +0 -1
- package/tool_call-CV5qVNlb.mjs.map +0 -1
- package/tool_call-Db68hB7y.js.map +0 -1
- package/tool_registry-D1pSSlsd.mjs.map +0 -1
- package/tool_registry-DYUYqXvo.js.map +0 -1
- package/turn_runner-DqWHNP80.js.map +0 -1
- package/turn_runner-fg1Wc3dK.mjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Ble4zEEl.js");
|
|
3
|
-
const require_tool_registry = require("../../tool_registry-
|
|
4
|
-
const require_tool = require("../../tool-
|
|
5
|
-
require("../../common-
|
|
3
|
+
const require_tool_registry = require("../../tool_registry-CKJPze3j.js");
|
|
4
|
+
const require_tool = require("../../tool-D5WGVIcI.js");
|
|
5
|
+
require("../../common-DZl3ADJs.js");
|
|
6
6
|
require("../../guards.cjs");
|
|
7
7
|
let _nhtio_validation = require("@nhtio/validation");
|
|
8
8
|
//#region src/batteries/tools/comparison/index.ts
|
|
@@ -124,6 +124,7 @@ var compareRecordsTool = new require_tool.Tool({
|
|
|
124
124
|
if (x === y) return true;
|
|
125
125
|
if (typeof x !== typeof y) return false;
|
|
126
126
|
if (x === null || y === null) return x === y;
|
|
127
|
+
if (Array.isArray(x) !== Array.isArray(y)) return false;
|
|
127
128
|
if (Array.isArray(x) && Array.isArray(y)) {
|
|
128
129
|
if (x.length !== y.length) return false;
|
|
129
130
|
for (const [i, element] of x.entries()) if (!isEqual(element, y[i])) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comparison.cjs","names":[],"sources":["../../../src/batteries/tools/comparison/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for comparing primitive values, arrays, and ranges.\n *\n * @module @nhtio/adk/batteries/tools/comparison\n *\n * @remarks\n * Pre-constructed bundled tools for the `comparison` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { isError } from '@nhtio/adk/guards'\nimport { validator } from '@nhtio/validation'\n\ntype Primitive = string | number | boolean | null | undefined\n\nfunction coerce(value: Primitive): number | string | boolean | null {\n if (value === null || value === undefined) return null\n if (typeof value === 'number' || typeof value === 'boolean') return value\n const n = Number(value)\n if (!Number.isNaN(n) && value.trim() !== '') return n\n return value\n}\n\nfunction compareTwo(a: Primitive, b: Primitive): number {\n const ca = coerce(a)\n const cb = coerce(b)\n if (ca === null && cb === null) return 0\n if (ca === null) return -1\n if (cb === null) return 1\n if (typeof ca === 'number' && typeof cb === 'number') return ca - cb\n return String(ca).localeCompare(String(cb))\n}\n\n/**\n * Compare two values and return their relationship (`equal`, `greater_than`, `less_than`).\n *\n * @remarks\n * Handles numbers, strings (lexicographic), booleans, ISO date strings, and null/undefined.\n * Use `type_hint` to force a specific interpretation; the default `auto` infers from the\n * values themselves.\n */\nexport const compareValuesTool = new Tool({\n name: 'compare_values',\n description:\n 'Compare two values and return their relationship: equal, greater_than, less_than, or not_comparable. Handles numbers, strings (lexicographic), booleans, dates (ISO strings), null/undefined.',\n inputSchema: validator.object({\n a: validator.any().required().description('First value to compare'),\n b: validator.any().required().description('Second value to compare'),\n type_hint: validator\n .string()\n .valid('auto', 'string', 'number', 'date')\n .default('auto')\n .description(\n 'Force interpretation: \"auto\" detects, \"date\" parses ISO date strings, \"string\" compares lexicographically, \"number\" coerces to numbers (default: auto)'\n ),\n case_insensitive: validator\n .boolean()\n .default(false)\n .description('For string comparisons: ignore case (default: false)'),\n }),\n handler: async (args) => {\n const {\n a: rawA,\n b: rawB,\n type_hint: typeHint,\n case_insensitive: ci,\n } = args as {\n a: unknown\n b: unknown\n type_hint: string\n case_insensitive: boolean\n }\n\n let av: unknown = rawA\n let bv: unknown = rawB\n\n try {\n if (typeHint === 'date') {\n const da = new Date(av as string)\n const db = new Date(bv as string)\n if (Number.isNaN(da.getTime())) return `Error: Cannot parse \"${av}\" as a date.`\n if (Number.isNaN(db.getTime())) return `Error: Cannot parse \"${bv}\" as a date.`\n const diff = da.getTime() - db.getTime()\n const rel = diff === 0 ? 'equal' : diff > 0 ? 'greater_than' : 'less_than'\n return `${rel}\\na = ${da.toISOString()}\\nb = ${db.toISOString()}`\n }\n\n if (typeHint === 'number') {\n const na = Number(av)\n const nb = Number(bv)\n if (Number.isNaN(na)) return `Error: Cannot convert \"${av}\" to a number.`\n if (Number.isNaN(nb)) return `Error: Cannot convert \"${bv}\" to a number.`\n const diff = na - nb\n return diff === 0 ? 'equal' : diff > 0 ? 'greater_than' : 'less_than'\n }\n\n if (typeHint === 'string') {\n const sa = ci ? String(av).toLowerCase() : String(av)\n const sb = ci ? String(bv).toLowerCase() : String(bv)\n const cmp = sa.localeCompare(sb)\n return cmp === 0 ? 'equal' : cmp > 0 ? 'greater_than' : 'less_than'\n }\n\n // auto\n if (ci && typeof av === 'string' && typeof bv === 'string') {\n av = av.toLowerCase()\n bv = bv.toLowerCase()\n }\n const cmp = compareTwo(av as Primitive, bv as Primitive)\n return cmp === 0 ? 'equal' : cmp > 0 ? 'greater_than' : 'less_than'\n } catch (err) {\n return `Error: ${isError(err) ? err.message : String(err)}`\n }\n },\n})\n\n/**\n * Compare two JSON objects and report keys only in A, keys only in B, keys with matching\n * values, and keys with differing values.\n *\n * @remarks\n * Accepts JSON strings (not pre-parsed objects) so the schema can validate the input\n * shape uniformly across providers. When `deep` is true (default), nested objects and arrays\n * are compared structurally; when false, comparison reduces to JSON serialisation equality.\n */\nexport const compareRecordsTool = new Tool({\n name: 'compare_records',\n description:\n 'Compare two JSON objects and report: keys only in A, keys only in B, keys present in both with the same value, and keys present in both with different values.',\n inputSchema: validator.object({\n record_a: validator.string().required().description('First JSON object (as a string)'),\n record_b: validator.string().required().description('Second JSON object (as a string)'),\n deep: validator\n .boolean()\n .default(true)\n .description(\n 'Use deep equality for nested values (default: true). When false, compares by JSON serialization.'\n ),\n }),\n handler: async (args) => {\n const {\n record_a: recordA,\n record_b: recordB,\n deep,\n } = args as { record_a: string; record_b: string; deep: boolean }\n\n let a: Record<string, unknown>\n let b: Record<string, unknown>\n\n try {\n a = JSON.parse(recordA) as Record<string, unknown>\n } catch {\n return 'Error: record_a is not valid JSON.'\n }\n try {\n b = JSON.parse(recordB) as Record<string, unknown>\n } catch {\n return 'Error: record_b is not valid JSON.'\n }\n\n if (typeof a !== 'object' || a === null || Array.isArray(a))\n return 'Error: record_a must be a JSON object (not array or primitive).'\n if (typeof b !== 'object' || b === null || Array.isArray(b))\n return 'Error: record_b must be a JSON object (not array or primitive).'\n\n function isEqual(x: unknown, y: unknown): boolean {\n if (!deep) return JSON.stringify(x) === JSON.stringify(y)\n if (x === y) return true\n if (typeof x !== typeof y) return false\n if (x === null || y === null) return x === y\n if (Array.isArray(x) && Array.isArray(y)) {\n if (x.length !== y.length) return false\n for (const [i, element] of x.entries()) {\n if (!isEqual(element, y[i])) return false\n }\n return true\n }\n if (typeof x === 'object' && typeof y === 'object') {\n const xk = Object.keys(x as object).sort()\n const yk = Object.keys(y as object).sort()\n if (JSON.stringify(xk) !== JSON.stringify(yk)) return false\n for (const k of xk) {\n if (!isEqual((x as Record<string, unknown>)[k], (y as Record<string, unknown>)[k]))\n return false\n }\n return true\n }\n return false\n }\n\n const keysA = new Set(Object.keys(a))\n const keysB = new Set(Object.keys(b))\n\n const onlyInA: string[] = []\n const onlyInB: string[] = []\n const same: string[] = []\n const different: Array<{ key: string; a: unknown; b: unknown }> = []\n\n for (const k of keysA) {\n if (!keysB.has(k)) {\n onlyInA.push(k)\n } else if (isEqual(a[k], b[k])) {\n same.push(k)\n } else {\n different.push({ key: k, a: a[k], b: b[k] })\n }\n }\n\n for (const k of keysB) {\n if (!keysA.has(k)) onlyInB.push(k)\n }\n\n const lines: string[] = []\n\n if (onlyInA.length > 0) lines.push(`Only in A (${onlyInA.length}): ${onlyInA.join(', ')}`)\n if (onlyInB.length > 0) lines.push(`Only in B (${onlyInB.length}): ${onlyInB.join(', ')}`)\n if (same.length > 0) lines.push(`Same value (${same.length}): ${same.join(', ')}`)\n\n if (different.length > 0) {\n lines.push(`Different value (${different.length}):`)\n for (const { key, a: av, b: bv } of different) {\n lines.push(` ${key}: A=${JSON.stringify(av)}, B=${JSON.stringify(bv)}`)\n }\n }\n\n if (lines.length === 0) return 'Records are identical.'\n return lines.join('\\n')\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"comparison.cjs","names":[],"sources":["../../../src/batteries/tools/comparison/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for comparing primitive values, arrays, and ranges.\n *\n * @module @nhtio/adk/batteries/tools/comparison\n *\n * @remarks\n * Pre-constructed bundled tools for the `comparison` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { isError } from '@nhtio/adk/guards'\nimport { validator } from '@nhtio/validation'\n\ntype Primitive = string | number | boolean | null | undefined\n\nfunction coerce(value: Primitive): number | string | boolean | null {\n if (value === null || value === undefined) return null\n if (typeof value === 'number' || typeof value === 'boolean') return value\n const n = Number(value)\n if (!Number.isNaN(n) && value.trim() !== '') return n\n return value\n}\n\nfunction compareTwo(a: Primitive, b: Primitive): number {\n const ca = coerce(a)\n const cb = coerce(b)\n if (ca === null && cb === null) return 0\n if (ca === null) return -1\n if (cb === null) return 1\n if (typeof ca === 'number' && typeof cb === 'number') return ca - cb\n return String(ca).localeCompare(String(cb))\n}\n\n/**\n * Compare two values and return their relationship (`equal`, `greater_than`, `less_than`).\n *\n * @remarks\n * Handles numbers, strings (lexicographic), booleans, ISO date strings, and null/undefined.\n * Use `type_hint` to force a specific interpretation; the default `auto` infers from the\n * values themselves.\n */\nexport const compareValuesTool = new Tool({\n name: 'compare_values',\n description:\n 'Compare two values and return their relationship: equal, greater_than, less_than, or not_comparable. Handles numbers, strings (lexicographic), booleans, dates (ISO strings), null/undefined.',\n inputSchema: validator.object({\n a: validator.any().required().description('First value to compare'),\n b: validator.any().required().description('Second value to compare'),\n type_hint: validator\n .string()\n .valid('auto', 'string', 'number', 'date')\n .default('auto')\n .description(\n 'Force interpretation: \"auto\" detects, \"date\" parses ISO date strings, \"string\" compares lexicographically, \"number\" coerces to numbers (default: auto)'\n ),\n case_insensitive: validator\n .boolean()\n .default(false)\n .description('For string comparisons: ignore case (default: false)'),\n }),\n handler: async (args) => {\n const {\n a: rawA,\n b: rawB,\n type_hint: typeHint,\n case_insensitive: ci,\n } = args as {\n a: unknown\n b: unknown\n type_hint: string\n case_insensitive: boolean\n }\n\n let av: unknown = rawA\n let bv: unknown = rawB\n\n try {\n if (typeHint === 'date') {\n const da = new Date(av as string)\n const db = new Date(bv as string)\n if (Number.isNaN(da.getTime())) return `Error: Cannot parse \"${av}\" as a date.`\n if (Number.isNaN(db.getTime())) return `Error: Cannot parse \"${bv}\" as a date.`\n const diff = da.getTime() - db.getTime()\n const rel = diff === 0 ? 'equal' : diff > 0 ? 'greater_than' : 'less_than'\n return `${rel}\\na = ${da.toISOString()}\\nb = ${db.toISOString()}`\n }\n\n if (typeHint === 'number') {\n const na = Number(av)\n const nb = Number(bv)\n if (Number.isNaN(na)) return `Error: Cannot convert \"${av}\" to a number.`\n if (Number.isNaN(nb)) return `Error: Cannot convert \"${bv}\" to a number.`\n const diff = na - nb\n return diff === 0 ? 'equal' : diff > 0 ? 'greater_than' : 'less_than'\n }\n\n if (typeHint === 'string') {\n const sa = ci ? String(av).toLowerCase() : String(av)\n const sb = ci ? String(bv).toLowerCase() : String(bv)\n const cmp = sa.localeCompare(sb)\n return cmp === 0 ? 'equal' : cmp > 0 ? 'greater_than' : 'less_than'\n }\n\n // auto\n if (ci && typeof av === 'string' && typeof bv === 'string') {\n av = av.toLowerCase()\n bv = bv.toLowerCase()\n }\n const cmp = compareTwo(av as Primitive, bv as Primitive)\n return cmp === 0 ? 'equal' : cmp > 0 ? 'greater_than' : 'less_than'\n } catch (err) {\n return `Error: ${isError(err) ? err.message : String(err)}`\n }\n },\n})\n\n/**\n * Compare two JSON objects and report keys only in A, keys only in B, keys with matching\n * values, and keys with differing values.\n *\n * @remarks\n * Accepts JSON strings (not pre-parsed objects) so the schema can validate the input\n * shape uniformly across providers. When `deep` is true (default), nested objects and arrays\n * are compared structurally; when false, comparison reduces to JSON serialisation equality.\n */\nexport const compareRecordsTool = new Tool({\n name: 'compare_records',\n description:\n 'Compare two JSON objects and report: keys only in A, keys only in B, keys present in both with the same value, and keys present in both with different values.',\n inputSchema: validator.object({\n record_a: validator.string().required().description('First JSON object (as a string)'),\n record_b: validator.string().required().description('Second JSON object (as a string)'),\n deep: validator\n .boolean()\n .default(true)\n .description(\n 'Use deep equality for nested values (default: true). When false, compares by JSON serialization.'\n ),\n }),\n handler: async (args) => {\n const {\n record_a: recordA,\n record_b: recordB,\n deep,\n } = args as { record_a: string; record_b: string; deep: boolean }\n\n let a: Record<string, unknown>\n let b: Record<string, unknown>\n\n try {\n a = JSON.parse(recordA) as Record<string, unknown>\n } catch {\n return 'Error: record_a is not valid JSON.'\n }\n try {\n b = JSON.parse(recordB) as Record<string, unknown>\n } catch {\n return 'Error: record_b is not valid JSON.'\n }\n\n if (typeof a !== 'object' || a === null || Array.isArray(a))\n return 'Error: record_a must be a JSON object (not array or primitive).'\n if (typeof b !== 'object' || b === null || Array.isArray(b))\n return 'Error: record_b must be a JSON object (not array or primitive).'\n\n function isEqual(x: unknown, y: unknown): boolean {\n if (!deep) return JSON.stringify(x) === JSON.stringify(y)\n if (x === y) return true\n if (typeof x !== typeof y) return false\n if (x === null || y === null) return x === y\n // An array and a plain object are never equal, even if the object has matching integer-like\n // keys ([1,2] vs {\"0\":1,\"1\":2}). Without this guard, a one-sided array falls through to the\n // Object.keys() comparison and is wrongly reported as identical.\n if (Array.isArray(x) !== Array.isArray(y)) return false\n if (Array.isArray(x) && Array.isArray(y)) {\n if (x.length !== y.length) return false\n for (const [i, element] of x.entries()) {\n if (!isEqual(element, y[i])) return false\n }\n return true\n }\n if (typeof x === 'object' && typeof y === 'object') {\n const xk = Object.keys(x as object).sort()\n const yk = Object.keys(y as object).sort()\n if (JSON.stringify(xk) !== JSON.stringify(yk)) return false\n for (const k of xk) {\n if (!isEqual((x as Record<string, unknown>)[k], (y as Record<string, unknown>)[k]))\n return false\n }\n return true\n }\n return false\n }\n\n const keysA = new Set(Object.keys(a))\n const keysB = new Set(Object.keys(b))\n\n const onlyInA: string[] = []\n const onlyInB: string[] = []\n const same: string[] = []\n const different: Array<{ key: string; a: unknown; b: unknown }> = []\n\n for (const k of keysA) {\n if (!keysB.has(k)) {\n onlyInA.push(k)\n } else if (isEqual(a[k], b[k])) {\n same.push(k)\n } else {\n different.push({ key: k, a: a[k], b: b[k] })\n }\n }\n\n for (const k of keysB) {\n if (!keysA.has(k)) onlyInB.push(k)\n }\n\n const lines: string[] = []\n\n if (onlyInA.length > 0) lines.push(`Only in A (${onlyInA.length}): ${onlyInA.join(', ')}`)\n if (onlyInB.length > 0) lines.push(`Only in B (${onlyInB.length}): ${onlyInB.join(', ')}`)\n if (same.length > 0) lines.push(`Same value (${same.length}): ${same.join(', ')}`)\n\n if (different.length > 0) {\n lines.push(`Different value (${different.length}):`)\n for (const { key, a: av, b: bv } of different) {\n lines.push(` ${key}: A=${JSON.stringify(av)}, B=${JSON.stringify(bv)}`)\n }\n }\n\n if (lines.length === 0) return 'Records are identical.'\n return lines.join('\\n')\n },\n})\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,SAAS,OAAO,OAAoD;CAClE,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO;CAClD,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW,OAAO;CACpE,MAAM,IAAI,OAAO,KAAK;CACtB,IAAI,CAAC,OAAO,MAAM,CAAC,KAAK,MAAM,KAAK,MAAM,IAAI,OAAO;CACpD,OAAO;AACT;AAEA,SAAS,WAAW,GAAc,GAAsB;CACtD,MAAM,KAAK,OAAO,CAAC;CACnB,MAAM,KAAK,OAAO,CAAC;CACnB,IAAI,OAAO,QAAQ,OAAO,MAAM,OAAO;CACvC,IAAI,OAAO,MAAM,OAAO;CACxB,IAAI,OAAO,MAAM,OAAO;CACxB,IAAI,OAAO,OAAO,YAAY,OAAO,OAAO,UAAU,OAAO,KAAK;CAClE,OAAO,OAAO,EAAE,EAAE,cAAc,OAAO,EAAE,CAAC;AAC5C;;;;;;;;;AAUA,IAAa,oBAAoB,IAAI,aAAA,KAAK;CACxC,MAAM;CACN,aACE;CACF,aAAa,kBAAA,UAAU,OAAO;EAC5B,GAAG,kBAAA,UAAU,IAAI,EAAE,SAAS,EAAE,YAAY,wBAAwB;EAClE,GAAG,kBAAA,UAAU,IAAI,EAAE,SAAS,EAAE,YAAY,yBAAyB;EACnE,WAAW,kBAAA,UACR,OAAO,EACP,MAAM,QAAQ,UAAU,UAAU,MAAM,EACxC,QAAQ,MAAM,EACd,YACC,gKACF;EACF,kBAAkB,kBAAA,UACf,QAAQ,EACR,QAAQ,KAAK,EACb,YAAY,sDAAsD;CACvE,CAAC;CACD,SAAS,OAAO,SAAS;EACvB,MAAM,EACJ,GAAG,MACH,GAAG,MACH,WAAW,UACX,kBAAkB,OAChB;EAOJ,IAAI,KAAc;EAClB,IAAI,KAAc;EAElB,IAAI;GACF,IAAI,aAAa,QAAQ;IACvB,MAAM,KAAK,IAAI,KAAK,EAAY;IAChC,MAAM,KAAK,IAAI,KAAK,EAAY;IAChC,IAAI,OAAO,MAAM,GAAG,QAAQ,CAAC,GAAG,OAAO,wBAAwB,GAAG;IAClE,IAAI,OAAO,MAAM,GAAG,QAAQ,CAAC,GAAG,OAAO,wBAAwB,GAAG;IAClE,MAAM,OAAO,GAAG,QAAQ,IAAI,GAAG,QAAQ;IAEvC,OAAO,GADK,SAAS,IAAI,UAAU,OAAO,IAAI,iBAAiB,YACjD,QAAQ,GAAG,YAAY,EAAE,QAAQ,GAAG,YAAY;GAChE;GAEA,IAAI,aAAa,UAAU;IACzB,MAAM,KAAK,OAAO,EAAE;IACpB,MAAM,KAAK,OAAO,EAAE;IACpB,IAAI,OAAO,MAAM,EAAE,GAAG,OAAO,0BAA0B,GAAG;IAC1D,IAAI,OAAO,MAAM,EAAE,GAAG,OAAO,0BAA0B,GAAG;IAC1D,MAAM,OAAO,KAAK;IAClB,OAAO,SAAS,IAAI,UAAU,OAAO,IAAI,iBAAiB;GAC5D;GAEA,IAAI,aAAa,UAAU;IACzB,MAAM,KAAK,KAAK,OAAO,EAAE,EAAE,YAAY,IAAI,OAAO,EAAE;IACpD,MAAM,KAAK,KAAK,OAAO,EAAE,EAAE,YAAY,IAAI,OAAO,EAAE;IACpD,MAAM,MAAM,GAAG,cAAc,EAAE;IAC/B,OAAO,QAAQ,IAAI,UAAU,MAAM,IAAI,iBAAiB;GAC1D;GAGA,IAAI,MAAM,OAAO,OAAO,YAAY,OAAO,OAAO,UAAU;IAC1D,KAAK,GAAG,YAAY;IACpB,KAAK,GAAG,YAAY;GACtB;GACA,MAAM,MAAM,WAAW,IAAiB,EAAe;GACvD,OAAO,QAAQ,IAAI,UAAU,MAAM,IAAI,iBAAiB;EAC1D,SAAS,KAAK;GACZ,OAAO,UAAU,sBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG;EAC1D;CACF;AACF,CAAC;;;;;;;;;;AAWD,IAAa,qBAAqB,IAAI,aAAA,KAAK;CACzC,MAAM;CACN,aACE;CACF,aAAa,kBAAA,UAAU,OAAO;EAC5B,UAAU,kBAAA,UAAU,OAAO,EAAE,SAAS,EAAE,YAAY,iCAAiC;EACrF,UAAU,kBAAA,UAAU,OAAO,EAAE,SAAS,EAAE,YAAY,kCAAkC;EACtF,MAAM,kBAAA,UACH,QAAQ,EACR,QAAQ,IAAI,EACZ,YACC,kGACF;CACJ,CAAC;CACD,SAAS,OAAO,SAAS;EACvB,MAAM,EACJ,UAAU,SACV,UAAU,SACV,SACE;EAEJ,IAAI;EACJ,IAAI;EAEJ,IAAI;GACF,IAAI,KAAK,MAAM,OAAO;EACxB,QAAQ;GACN,OAAO;EACT;EACA,IAAI;GACF,IAAI,KAAK,MAAM,OAAO;EACxB,QAAQ;GACN,OAAO;EACT;EAEA,IAAI,OAAO,MAAM,YAAY,MAAM,QAAQ,MAAM,QAAQ,CAAC,GACxD,OAAO;EACT,IAAI,OAAO,MAAM,YAAY,MAAM,QAAQ,MAAM,QAAQ,CAAC,GACxD,OAAO;EAET,SAAS,QAAQ,GAAY,GAAqB;GAChD,IAAI,CAAC,MAAM,OAAO,KAAK,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC;GACxD,IAAI,MAAM,GAAG,OAAO;GACpB,IAAI,OAAO,MAAM,OAAO,GAAG,OAAO;GAClC,IAAI,MAAM,QAAQ,MAAM,MAAM,OAAO,MAAM;GAI3C,IAAI,MAAM,QAAQ,CAAC,MAAM,MAAM,QAAQ,CAAC,GAAG,OAAO;GAClD,IAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GAAG;IACxC,IAAI,EAAE,WAAW,EAAE,QAAQ,OAAO;IAClC,KAAK,MAAM,CAAC,GAAG,YAAY,EAAE,QAAQ,GACnC,IAAI,CAAC,QAAQ,SAAS,EAAE,EAAE,GAAG,OAAO;IAEtC,OAAO;GACT;GACA,IAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU;IAClD,MAAM,KAAK,OAAO,KAAK,CAAW,EAAE,KAAK;IACzC,MAAM,KAAK,OAAO,KAAK,CAAW,EAAE,KAAK;IACzC,IAAI,KAAK,UAAU,EAAE,MAAM,KAAK,UAAU,EAAE,GAAG,OAAO;IACtD,KAAK,MAAM,KAAK,IACd,IAAI,CAAC,QAAS,EAA8B,IAAK,EAA8B,EAAE,GAC/E,OAAO;IAEX,OAAO;GACT;GACA,OAAO;EACT;EAEA,MAAM,QAAQ,IAAI,IAAI,OAAO,KAAK,CAAC,CAAC;EACpC,MAAM,QAAQ,IAAI,IAAI,OAAO,KAAK,CAAC,CAAC;EAEpC,MAAM,UAAoB,CAAC;EAC3B,MAAM,UAAoB,CAAC;EAC3B,MAAM,OAAiB,CAAC;EACxB,MAAM,YAA4D,CAAC;EAEnE,KAAK,MAAM,KAAK,OACd,IAAI,CAAC,MAAM,IAAI,CAAC,GACd,QAAQ,KAAK,CAAC;OACT,IAAI,QAAQ,EAAE,IAAI,EAAE,EAAE,GAC3B,KAAK,KAAK,CAAC;OAEX,UAAU,KAAK;GAAE,KAAK;GAAG,GAAG,EAAE;GAAI,GAAG,EAAE;EAAG,CAAC;EAI/C,KAAK,MAAM,KAAK,OACd,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,QAAQ,KAAK,CAAC;EAGnC,MAAM,QAAkB,CAAC;EAEzB,IAAI,QAAQ,SAAS,GAAG,MAAM,KAAK,cAAc,QAAQ,OAAO,KAAK,QAAQ,KAAK,IAAI,GAAG;EACzF,IAAI,QAAQ,SAAS,GAAG,MAAM,KAAK,cAAc,QAAQ,OAAO,KAAK,QAAQ,KAAK,IAAI,GAAG;EACzF,IAAI,KAAK,SAAS,GAAG,MAAM,KAAK,eAAe,KAAK,OAAO,KAAK,KAAK,KAAK,IAAI,GAAG;EAEjF,IAAI,UAAU,SAAS,GAAG;GACxB,MAAM,KAAK,oBAAoB,UAAU,OAAO,GAAG;GACnD,KAAK,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,QAAQ,WAClC,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,UAAU,EAAE,EAAE,MAAM,KAAK,UAAU,EAAE,GAAG;EAE3E;EAEA,IAAI,MAAM,WAAW,GAAG,OAAO;EAC/B,OAAO,MAAM,KAAK,IAAI;CACxB;AACF,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { o as isError } from "../../tool_registry-
|
|
2
|
-
import { t as Tool } from "../../tool-
|
|
3
|
-
import "../../common-
|
|
1
|
+
import { o as isError } from "../../tool_registry-791Vrjtf.mjs";
|
|
2
|
+
import { t as Tool } from "../../tool-wMYMVl60.mjs";
|
|
3
|
+
import "../../common-DYDUi99O.mjs";
|
|
4
4
|
import "../../guards.mjs";
|
|
5
5
|
import { validator } from "@nhtio/validation";
|
|
6
6
|
//#region src/batteries/tools/comparison/index.ts
|
|
@@ -122,6 +122,7 @@ var compareRecordsTool = new Tool({
|
|
|
122
122
|
if (x === y) return true;
|
|
123
123
|
if (typeof x !== typeof y) return false;
|
|
124
124
|
if (x === null || y === null) return x === y;
|
|
125
|
+
if (Array.isArray(x) !== Array.isArray(y)) return false;
|
|
125
126
|
if (Array.isArray(x) && Array.isArray(y)) {
|
|
126
127
|
if (x.length !== y.length) return false;
|
|
127
128
|
for (const [i, element] of x.entries()) if (!isEqual(element, y[i])) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comparison.mjs","names":[],"sources":["../../../src/batteries/tools/comparison/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for comparing primitive values, arrays, and ranges.\n *\n * @module @nhtio/adk/batteries/tools/comparison\n *\n * @remarks\n * Pre-constructed bundled tools for the `comparison` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { isError } from '@nhtio/adk/guards'\nimport { validator } from '@nhtio/validation'\n\ntype Primitive = string | number | boolean | null | undefined\n\nfunction coerce(value: Primitive): number | string | boolean | null {\n if (value === null || value === undefined) return null\n if (typeof value === 'number' || typeof value === 'boolean') return value\n const n = Number(value)\n if (!Number.isNaN(n) && value.trim() !== '') return n\n return value\n}\n\nfunction compareTwo(a: Primitive, b: Primitive): number {\n const ca = coerce(a)\n const cb = coerce(b)\n if (ca === null && cb === null) return 0\n if (ca === null) return -1\n if (cb === null) return 1\n if (typeof ca === 'number' && typeof cb === 'number') return ca - cb\n return String(ca).localeCompare(String(cb))\n}\n\n/**\n * Compare two values and return their relationship (`equal`, `greater_than`, `less_than`).\n *\n * @remarks\n * Handles numbers, strings (lexicographic), booleans, ISO date strings, and null/undefined.\n * Use `type_hint` to force a specific interpretation; the default `auto` infers from the\n * values themselves.\n */\nexport const compareValuesTool = new Tool({\n name: 'compare_values',\n description:\n 'Compare two values and return their relationship: equal, greater_than, less_than, or not_comparable. Handles numbers, strings (lexicographic), booleans, dates (ISO strings), null/undefined.',\n inputSchema: validator.object({\n a: validator.any().required().description('First value to compare'),\n b: validator.any().required().description('Second value to compare'),\n type_hint: validator\n .string()\n .valid('auto', 'string', 'number', 'date')\n .default('auto')\n .description(\n 'Force interpretation: \"auto\" detects, \"date\" parses ISO date strings, \"string\" compares lexicographically, \"number\" coerces to numbers (default: auto)'\n ),\n case_insensitive: validator\n .boolean()\n .default(false)\n .description('For string comparisons: ignore case (default: false)'),\n }),\n handler: async (args) => {\n const {\n a: rawA,\n b: rawB,\n type_hint: typeHint,\n case_insensitive: ci,\n } = args as {\n a: unknown\n b: unknown\n type_hint: string\n case_insensitive: boolean\n }\n\n let av: unknown = rawA\n let bv: unknown = rawB\n\n try {\n if (typeHint === 'date') {\n const da = new Date(av as string)\n const db = new Date(bv as string)\n if (Number.isNaN(da.getTime())) return `Error: Cannot parse \"${av}\" as a date.`\n if (Number.isNaN(db.getTime())) return `Error: Cannot parse \"${bv}\" as a date.`\n const diff = da.getTime() - db.getTime()\n const rel = diff === 0 ? 'equal' : diff > 0 ? 'greater_than' : 'less_than'\n return `${rel}\\na = ${da.toISOString()}\\nb = ${db.toISOString()}`\n }\n\n if (typeHint === 'number') {\n const na = Number(av)\n const nb = Number(bv)\n if (Number.isNaN(na)) return `Error: Cannot convert \"${av}\" to a number.`\n if (Number.isNaN(nb)) return `Error: Cannot convert \"${bv}\" to a number.`\n const diff = na - nb\n return diff === 0 ? 'equal' : diff > 0 ? 'greater_than' : 'less_than'\n }\n\n if (typeHint === 'string') {\n const sa = ci ? String(av).toLowerCase() : String(av)\n const sb = ci ? String(bv).toLowerCase() : String(bv)\n const cmp = sa.localeCompare(sb)\n return cmp === 0 ? 'equal' : cmp > 0 ? 'greater_than' : 'less_than'\n }\n\n // auto\n if (ci && typeof av === 'string' && typeof bv === 'string') {\n av = av.toLowerCase()\n bv = bv.toLowerCase()\n }\n const cmp = compareTwo(av as Primitive, bv as Primitive)\n return cmp === 0 ? 'equal' : cmp > 0 ? 'greater_than' : 'less_than'\n } catch (err) {\n return `Error: ${isError(err) ? err.message : String(err)}`\n }\n },\n})\n\n/**\n * Compare two JSON objects and report keys only in A, keys only in B, keys with matching\n * values, and keys with differing values.\n *\n * @remarks\n * Accepts JSON strings (not pre-parsed objects) so the schema can validate the input\n * shape uniformly across providers. When `deep` is true (default), nested objects and arrays\n * are compared structurally; when false, comparison reduces to JSON serialisation equality.\n */\nexport const compareRecordsTool = new Tool({\n name: 'compare_records',\n description:\n 'Compare two JSON objects and report: keys only in A, keys only in B, keys present in both with the same value, and keys present in both with different values.',\n inputSchema: validator.object({\n record_a: validator.string().required().description('First JSON object (as a string)'),\n record_b: validator.string().required().description('Second JSON object (as a string)'),\n deep: validator\n .boolean()\n .default(true)\n .description(\n 'Use deep equality for nested values (default: true). When false, compares by JSON serialization.'\n ),\n }),\n handler: async (args) => {\n const {\n record_a: recordA,\n record_b: recordB,\n deep,\n } = args as { record_a: string; record_b: string; deep: boolean }\n\n let a: Record<string, unknown>\n let b: Record<string, unknown>\n\n try {\n a = JSON.parse(recordA) as Record<string, unknown>\n } catch {\n return 'Error: record_a is not valid JSON.'\n }\n try {\n b = JSON.parse(recordB) as Record<string, unknown>\n } catch {\n return 'Error: record_b is not valid JSON.'\n }\n\n if (typeof a !== 'object' || a === null || Array.isArray(a))\n return 'Error: record_a must be a JSON object (not array or primitive).'\n if (typeof b !== 'object' || b === null || Array.isArray(b))\n return 'Error: record_b must be a JSON object (not array or primitive).'\n\n function isEqual(x: unknown, y: unknown): boolean {\n if (!deep) return JSON.stringify(x) === JSON.stringify(y)\n if (x === y) return true\n if (typeof x !== typeof y) return false\n if (x === null || y === null) return x === y\n if (Array.isArray(x) && Array.isArray(y)) {\n if (x.length !== y.length) return false\n for (const [i, element] of x.entries()) {\n if (!isEqual(element, y[i])) return false\n }\n return true\n }\n if (typeof x === 'object' && typeof y === 'object') {\n const xk = Object.keys(x as object).sort()\n const yk = Object.keys(y as object).sort()\n if (JSON.stringify(xk) !== JSON.stringify(yk)) return false\n for (const k of xk) {\n if (!isEqual((x as Record<string, unknown>)[k], (y as Record<string, unknown>)[k]))\n return false\n }\n return true\n }\n return false\n }\n\n const keysA = new Set(Object.keys(a))\n const keysB = new Set(Object.keys(b))\n\n const onlyInA: string[] = []\n const onlyInB: string[] = []\n const same: string[] = []\n const different: Array<{ key: string; a: unknown; b: unknown }> = []\n\n for (const k of keysA) {\n if (!keysB.has(k)) {\n onlyInA.push(k)\n } else if (isEqual(a[k], b[k])) {\n same.push(k)\n } else {\n different.push({ key: k, a: a[k], b: b[k] })\n }\n }\n\n for (const k of keysB) {\n if (!keysA.has(k)) onlyInB.push(k)\n }\n\n const lines: string[] = []\n\n if (onlyInA.length > 0) lines.push(`Only in A (${onlyInA.length}): ${onlyInA.join(', ')}`)\n if (onlyInB.length > 0) lines.push(`Only in B (${onlyInB.length}): ${onlyInB.join(', ')}`)\n if (same.length > 0) lines.push(`Same value (${same.length}): ${same.join(', ')}`)\n\n if (different.length > 0) {\n lines.push(`Different value (${different.length}):`)\n for (const { key, a: av, b: bv } of different) {\n lines.push(` ${key}: A=${JSON.stringify(av)}, B=${JSON.stringify(bv)}`)\n }\n }\n\n if (lines.length === 0) return 'Records are identical.'\n return lines.join('\\n')\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"comparison.mjs","names":[],"sources":["../../../src/batteries/tools/comparison/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for comparing primitive values, arrays, and ranges.\n *\n * @module @nhtio/adk/batteries/tools/comparison\n *\n * @remarks\n * Pre-constructed bundled tools for the `comparison` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { isError } from '@nhtio/adk/guards'\nimport { validator } from '@nhtio/validation'\n\ntype Primitive = string | number | boolean | null | undefined\n\nfunction coerce(value: Primitive): number | string | boolean | null {\n if (value === null || value === undefined) return null\n if (typeof value === 'number' || typeof value === 'boolean') return value\n const n = Number(value)\n if (!Number.isNaN(n) && value.trim() !== '') return n\n return value\n}\n\nfunction compareTwo(a: Primitive, b: Primitive): number {\n const ca = coerce(a)\n const cb = coerce(b)\n if (ca === null && cb === null) return 0\n if (ca === null) return -1\n if (cb === null) return 1\n if (typeof ca === 'number' && typeof cb === 'number') return ca - cb\n return String(ca).localeCompare(String(cb))\n}\n\n/**\n * Compare two values and return their relationship (`equal`, `greater_than`, `less_than`).\n *\n * @remarks\n * Handles numbers, strings (lexicographic), booleans, ISO date strings, and null/undefined.\n * Use `type_hint` to force a specific interpretation; the default `auto` infers from the\n * values themselves.\n */\nexport const compareValuesTool = new Tool({\n name: 'compare_values',\n description:\n 'Compare two values and return their relationship: equal, greater_than, less_than, or not_comparable. Handles numbers, strings (lexicographic), booleans, dates (ISO strings), null/undefined.',\n inputSchema: validator.object({\n a: validator.any().required().description('First value to compare'),\n b: validator.any().required().description('Second value to compare'),\n type_hint: validator\n .string()\n .valid('auto', 'string', 'number', 'date')\n .default('auto')\n .description(\n 'Force interpretation: \"auto\" detects, \"date\" parses ISO date strings, \"string\" compares lexicographically, \"number\" coerces to numbers (default: auto)'\n ),\n case_insensitive: validator\n .boolean()\n .default(false)\n .description('For string comparisons: ignore case (default: false)'),\n }),\n handler: async (args) => {\n const {\n a: rawA,\n b: rawB,\n type_hint: typeHint,\n case_insensitive: ci,\n } = args as {\n a: unknown\n b: unknown\n type_hint: string\n case_insensitive: boolean\n }\n\n let av: unknown = rawA\n let bv: unknown = rawB\n\n try {\n if (typeHint === 'date') {\n const da = new Date(av as string)\n const db = new Date(bv as string)\n if (Number.isNaN(da.getTime())) return `Error: Cannot parse \"${av}\" as a date.`\n if (Number.isNaN(db.getTime())) return `Error: Cannot parse \"${bv}\" as a date.`\n const diff = da.getTime() - db.getTime()\n const rel = diff === 0 ? 'equal' : diff > 0 ? 'greater_than' : 'less_than'\n return `${rel}\\na = ${da.toISOString()}\\nb = ${db.toISOString()}`\n }\n\n if (typeHint === 'number') {\n const na = Number(av)\n const nb = Number(bv)\n if (Number.isNaN(na)) return `Error: Cannot convert \"${av}\" to a number.`\n if (Number.isNaN(nb)) return `Error: Cannot convert \"${bv}\" to a number.`\n const diff = na - nb\n return diff === 0 ? 'equal' : diff > 0 ? 'greater_than' : 'less_than'\n }\n\n if (typeHint === 'string') {\n const sa = ci ? String(av).toLowerCase() : String(av)\n const sb = ci ? String(bv).toLowerCase() : String(bv)\n const cmp = sa.localeCompare(sb)\n return cmp === 0 ? 'equal' : cmp > 0 ? 'greater_than' : 'less_than'\n }\n\n // auto\n if (ci && typeof av === 'string' && typeof bv === 'string') {\n av = av.toLowerCase()\n bv = bv.toLowerCase()\n }\n const cmp = compareTwo(av as Primitive, bv as Primitive)\n return cmp === 0 ? 'equal' : cmp > 0 ? 'greater_than' : 'less_than'\n } catch (err) {\n return `Error: ${isError(err) ? err.message : String(err)}`\n }\n },\n})\n\n/**\n * Compare two JSON objects and report keys only in A, keys only in B, keys with matching\n * values, and keys with differing values.\n *\n * @remarks\n * Accepts JSON strings (not pre-parsed objects) so the schema can validate the input\n * shape uniformly across providers. When `deep` is true (default), nested objects and arrays\n * are compared structurally; when false, comparison reduces to JSON serialisation equality.\n */\nexport const compareRecordsTool = new Tool({\n name: 'compare_records',\n description:\n 'Compare two JSON objects and report: keys only in A, keys only in B, keys present in both with the same value, and keys present in both with different values.',\n inputSchema: validator.object({\n record_a: validator.string().required().description('First JSON object (as a string)'),\n record_b: validator.string().required().description('Second JSON object (as a string)'),\n deep: validator\n .boolean()\n .default(true)\n .description(\n 'Use deep equality for nested values (default: true). When false, compares by JSON serialization.'\n ),\n }),\n handler: async (args) => {\n const {\n record_a: recordA,\n record_b: recordB,\n deep,\n } = args as { record_a: string; record_b: string; deep: boolean }\n\n let a: Record<string, unknown>\n let b: Record<string, unknown>\n\n try {\n a = JSON.parse(recordA) as Record<string, unknown>\n } catch {\n return 'Error: record_a is not valid JSON.'\n }\n try {\n b = JSON.parse(recordB) as Record<string, unknown>\n } catch {\n return 'Error: record_b is not valid JSON.'\n }\n\n if (typeof a !== 'object' || a === null || Array.isArray(a))\n return 'Error: record_a must be a JSON object (not array or primitive).'\n if (typeof b !== 'object' || b === null || Array.isArray(b))\n return 'Error: record_b must be a JSON object (not array or primitive).'\n\n function isEqual(x: unknown, y: unknown): boolean {\n if (!deep) return JSON.stringify(x) === JSON.stringify(y)\n if (x === y) return true\n if (typeof x !== typeof y) return false\n if (x === null || y === null) return x === y\n // An array and a plain object are never equal, even if the object has matching integer-like\n // keys ([1,2] vs {\"0\":1,\"1\":2}). Without this guard, a one-sided array falls through to the\n // Object.keys() comparison and is wrongly reported as identical.\n if (Array.isArray(x) !== Array.isArray(y)) return false\n if (Array.isArray(x) && Array.isArray(y)) {\n if (x.length !== y.length) return false\n for (const [i, element] of x.entries()) {\n if (!isEqual(element, y[i])) return false\n }\n return true\n }\n if (typeof x === 'object' && typeof y === 'object') {\n const xk = Object.keys(x as object).sort()\n const yk = Object.keys(y as object).sort()\n if (JSON.stringify(xk) !== JSON.stringify(yk)) return false\n for (const k of xk) {\n if (!isEqual((x as Record<string, unknown>)[k], (y as Record<string, unknown>)[k]))\n return false\n }\n return true\n }\n return false\n }\n\n const keysA = new Set(Object.keys(a))\n const keysB = new Set(Object.keys(b))\n\n const onlyInA: string[] = []\n const onlyInB: string[] = []\n const same: string[] = []\n const different: Array<{ key: string; a: unknown; b: unknown }> = []\n\n for (const k of keysA) {\n if (!keysB.has(k)) {\n onlyInA.push(k)\n } else if (isEqual(a[k], b[k])) {\n same.push(k)\n } else {\n different.push({ key: k, a: a[k], b: b[k] })\n }\n }\n\n for (const k of keysB) {\n if (!keysA.has(k)) onlyInB.push(k)\n }\n\n const lines: string[] = []\n\n if (onlyInA.length > 0) lines.push(`Only in A (${onlyInA.length}): ${onlyInA.join(', ')}`)\n if (onlyInB.length > 0) lines.push(`Only in B (${onlyInB.length}): ${onlyInB.join(', ')}`)\n if (same.length > 0) lines.push(`Same value (${same.length}): ${same.join(', ')}`)\n\n if (different.length > 0) {\n lines.push(`Different value (${different.length}):`)\n for (const { key, a: av, b: bv } of different) {\n lines.push(` ${key}: A=${JSON.stringify(av)}, B=${JSON.stringify(bv)}`)\n }\n }\n\n if (lines.length === 0) return 'Records are identical.'\n return lines.join('\\n')\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Ble4zEEl.js");
|
|
3
|
-
const require_tool_registry = require("../../tool_registry-
|
|
4
|
-
const require_tool = require("../../tool-
|
|
5
|
-
require("../../common-
|
|
3
|
+
const require_tool_registry = require("../../tool_registry-CKJPze3j.js");
|
|
4
|
+
const require_tool = require("../../tool-D5WGVIcI.js");
|
|
5
|
+
require("../../common-DZl3ADJs.js");
|
|
6
6
|
require("../../guards.cjs");
|
|
7
|
+
const require_lib_helpers_bignum = require("../../lib/helpers/bignum.cjs");
|
|
7
8
|
let _nhtio_validation = require("@nhtio/validation");
|
|
8
9
|
//#region src/batteries/tools/data_structure/index.ts
|
|
9
10
|
/**
|
|
@@ -15,6 +16,18 @@ let _nhtio_validation = require("@nhtio/validation");
|
|
|
15
16
|
* Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole
|
|
16
17
|
* category, or import every tool via `@nhtio/adk/batteries`.
|
|
17
18
|
*/
|
|
19
|
+
/**
|
|
20
|
+
* Render a {@link BigNumber} aggregate as a JSON-friendly value: a plain `number` when the result
|
|
21
|
+
* is exactly representable as a float64 (|x| ≤ Number.MAX_SAFE_INTEGER, so existing consumers and
|
|
22
|
+
* tests see a number with no precision loss), or a full-precision string otherwise — covering both
|
|
23
|
+
* overflow (which `JSON.stringify` would turn into `null`) and the gap above 2^53 where float64
|
|
24
|
+
* silently rounds (e.g. 3 × MAX_SAFE_INTEGER).
|
|
25
|
+
*/
|
|
26
|
+
function aggregateValue(big) {
|
|
27
|
+
const asNum = require_lib_helpers_bignum.bigToNumber(big);
|
|
28
|
+
if (Number.isFinite(asNum) && Math.abs(asNum) <= Number.MAX_SAFE_INTEGER) return asNum;
|
|
29
|
+
return require_lib_helpers_bignum.formatBig(big, 16);
|
|
30
|
+
}
|
|
18
31
|
function getPath(obj, path) {
|
|
19
32
|
const parts = path.split(".");
|
|
20
33
|
let current = obj;
|
|
@@ -53,6 +66,7 @@ function applyTemplate(template, item) {
|
|
|
53
66
|
});
|
|
54
67
|
}
|
|
55
68
|
function applyOperation(data, op) {
|
|
69
|
+
if (op === null || typeof op !== "object" || typeof op.op !== "string") throw new Error("Each operation must be an object with a string \"op\" field.");
|
|
56
70
|
if (op.op === "count") {
|
|
57
71
|
if (Array.isArray(data)) return data.length;
|
|
58
72
|
if (require_tool_registry.isObject(data)) return Object.keys(data).length;
|
|
@@ -94,7 +108,8 @@ function applyOperation(data, op) {
|
|
|
94
108
|
case "unique_by": {
|
|
95
109
|
const seen = /* @__PURE__ */ new Set();
|
|
96
110
|
return arr.filter((item) => {
|
|
97
|
-
const
|
|
111
|
+
const raw = getPath(item, op.key);
|
|
112
|
+
const key = typeof raw === "object" && raw !== null ? JSON.stringify(raw) : `${typeof raw}:${String(raw)}`;
|
|
98
113
|
if (seen.has(key)) return false;
|
|
99
114
|
seen.add(key);
|
|
100
115
|
return true;
|
|
@@ -111,14 +126,18 @@ function applyOperation(data, op) {
|
|
|
111
126
|
}
|
|
112
127
|
case "flatten": return arr.flat(op.depth ?? 1);
|
|
113
128
|
case "reverse": return [...arr].reverse();
|
|
114
|
-
case "sum":
|
|
129
|
+
case "sum": {
|
|
130
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
131
|
+
if (nums.length === 0 && arr.length > 0) throw new Error(op.key ? `No numeric values found at key "${op.key}".` : "No numeric values to sum. For an array of objects, pass a \"key\".");
|
|
132
|
+
return aggregateValue(require_lib_helpers_bignum.bigSum(nums));
|
|
133
|
+
}
|
|
115
134
|
case "avg": {
|
|
116
|
-
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number");
|
|
135
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
117
136
|
if (nums.length === 0) return null;
|
|
118
|
-
return
|
|
137
|
+
return aggregateValue(require_lib_helpers_bignum.bigMean(nums));
|
|
119
138
|
}
|
|
120
139
|
case "median": {
|
|
121
|
-
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number");
|
|
140
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
122
141
|
if (nums.length === 0) return null;
|
|
123
142
|
return medianOf(nums);
|
|
124
143
|
}
|
|
@@ -149,7 +168,7 @@ function applyOperation(data, op) {
|
|
|
149
168
|
return freq;
|
|
150
169
|
}
|
|
151
170
|
case "top_n": {
|
|
152
|
-
const dir = op.direction === "asc" ? 1 :
|
|
171
|
+
const dir = op.direction === "asc" ? -1 : 1;
|
|
153
172
|
return [...arr].sort((a, b) => {
|
|
154
173
|
const av = getPath(a, op.key);
|
|
155
174
|
const bv = getPath(b, op.key);
|
|
@@ -190,7 +209,8 @@ var jsonTransformTool = new require_tool.Tool({
|
|
|
190
209
|
for (const [i, operation] of operations.entries()) try {
|
|
191
210
|
current = applyOperation(current, operation);
|
|
192
211
|
} catch (err) {
|
|
193
|
-
|
|
212
|
+
const opName = operation && typeof operation === "object" && "op" in operation ? String(operation.op) : String(operation);
|
|
213
|
+
return `Error in operation ${i + 1} ("${opName}"): ${require_tool_registry.isError(err) ? err.message : String(err)}`;
|
|
194
214
|
}
|
|
195
215
|
if (typeof current === "string") return current;
|
|
196
216
|
return JSON.stringify(current, null, 2);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data_structure.cjs","names":[],"sources":["../../../src/batteries/tools/data_structure/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for querying, filtering, grouping, and reshaping structured values.\n *\n * @module @nhtio/adk/batteries/tools/data_structure\n *\n * @remarks\n * Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { validator } from '@nhtio/validation'\nimport { isError, isObject } from '@nhtio/adk/guards'\n\nfunction getPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current = obj\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\ntype FilterOperator =\n | 'eq'\n | 'ne'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains'\n | 'starts_with'\n | 'ends_with'\n | 'exists'\n\nfunction matchesFilter(\n item: unknown,\n key: string,\n operator: FilterOperator,\n value: unknown\n): boolean {\n const actual = getPath(item, key)\n switch (operator) {\n case 'eq':\n return actual === value\n case 'ne':\n return actual !== value\n case 'gt':\n return typeof actual === 'number' && actual > (value as number)\n case 'gte':\n return typeof actual === 'number' && actual >= (value as number)\n case 'lt':\n return typeof actual === 'number' && actual < (value as number)\n case 'lte':\n return typeof actual === 'number' && actual <= (value as number)\n case 'contains':\n return typeof actual === 'string' && actual.includes(String(value))\n case 'starts_with':\n return typeof actual === 'string' && actual.startsWith(String(value))\n case 'ends_with':\n return typeof actual === 'string' && actual.endsWith(String(value))\n case 'exists':\n return actual !== undefined && actual !== null\n default:\n return false\n }\n}\n\nfunction medianOf(nums: number[]): number {\n const sorted = [...nums].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]\n}\n\nfunction applyTemplate(template: string, item: unknown): string {\n if (typeof item !== 'object' || item === null) return String(item)\n return template.replace(/\\{\\{([^}]+)\\}\\}/g, (_, key) => {\n const val = getPath(item, key.trim())\n return val === undefined || val === null ? '' : String(val)\n })\n}\n\ntype Operation =\n | { op: 'filter'; key: string; operator: FilterOperator; value?: unknown }\n | { op: 'sort'; key: string; direction?: 'asc' | 'desc' }\n | { op: 'select_keys'; keys: string[] }\n | { op: 'pluck'; key: string }\n | { op: 'slice'; start: number; end?: number }\n | { op: 'unique' }\n | { op: 'unique_by'; key: string }\n | { op: 'group_by'; key: string }\n | { op: 'flatten'; depth?: number }\n | { op: 'reverse' }\n | { op: 'count' }\n | { op: 'sum'; key?: string }\n | { op: 'avg'; key?: string }\n | { op: 'median'; key?: string }\n | { op: 'min'; key?: string }\n | { op: 'max'; key?: string }\n | { op: 'first'; n?: number }\n | { op: 'last'; n?: number }\n | { op: 'chunk'; size: number }\n | { op: 'frequency_count'; key?: string }\n | { op: 'top_n'; n: number; key: string; direction?: 'asc' | 'desc' }\n | { op: 'map_template'; template: string }\n\nfunction applyOperation(data: unknown, op: Operation): unknown {\n if (op.op === 'count') {\n if (Array.isArray(data)) return data.length\n if (isObject(data)) return Object.keys(data).length\n return 0\n }\n\n if (!Array.isArray(data)) {\n throw new Error(`Operation \"${op.op}\" requires an array input.`)\n }\n\n const arr = data as unknown[]\n\n switch (op.op) {\n case 'filter':\n return arr.filter((item) => matchesFilter(item, op.key, op.operator, op.value))\n\n case 'sort': {\n const dir = op.direction === 'desc' ? -1 : 1\n return [...arr].sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (av === bv) return 0\n if (av === undefined || av === null) return 1\n if (bv === undefined || bv === null) return -1\n if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * dir\n return String(av).localeCompare(String(bv)) * dir\n })\n }\n\n case 'select_keys':\n return arr.map((item) => {\n if (typeof item !== 'object' || item === null) return item\n const result: Record<string, unknown> = {}\n for (const key of op.keys) result[key] = (item as Record<string, unknown>)[key]\n return result\n })\n\n case 'pluck':\n return arr.map((item) => getPath(item, op.key))\n\n case 'slice':\n return arr.slice(op.start, op.end)\n\n case 'unique': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = typeof item === 'object' ? JSON.stringify(item) : String(item)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'unique_by': {\n const seen = new Set<unknown>()\n return arr.filter((item) => {\n const key = getPath(item, op.key)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'group_by': {\n const groups: Record<string, unknown[]> = {}\n for (const item of arr) {\n const key = String(getPath(item, op.key) ?? '__undefined__')\n if (!groups[key]) groups[key] = []\n groups[key].push(item)\n }\n return groups\n }\n\n case 'flatten':\n return arr.flat(op.depth ?? 1)\n\n case 'reverse':\n return [...arr].reverse()\n\n case 'sum': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n return values.reduce<number>((acc, v) => acc + (typeof v === 'number' ? v : 0), 0)\n }\n\n case 'avg': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return nums.reduce((a, b) => a + b, 0) / nums.length\n }\n\n case 'median': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return medianOf(nums)\n }\n\n case 'min': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.min(...nums)\n }\n\n case 'max': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.max(...nums)\n }\n\n case 'first':\n return op.n !== undefined ? arr.slice(0, op.n) : arr[0]\n\n case 'last':\n return op.n !== undefined ? arr.slice(-op.n) : arr[arr.length - 1]\n\n case 'chunk': {\n const size = Math.max(1, Math.floor(op.size))\n const chunks: unknown[][] = []\n for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size))\n return chunks\n }\n\n case 'frequency_count': {\n const freq: Record<string, number> = {}\n for (const item of arr) {\n const key = op.key ? String(getPath(item, op.key) ?? '__undefined__') : String(item)\n freq[key] = (freq[key] ?? 0) + 1\n }\n return freq\n }\n\n case 'top_n': {\n const dir = op.direction === 'asc' ? 1 : -1\n return [...arr]\n .sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (typeof av === 'number' && typeof bv === 'number') return (bv - av) * dir\n return String(bv).localeCompare(String(av)) * dir\n })\n .slice(0, op.n)\n }\n\n case 'map_template':\n return arr.map((item) => applyTemplate(op.template, item))\n\n default:\n throw new Error(`Unknown operation: ${(op as { op: string }).op}`)\n }\n}\n\n/**\n * Apply a pipeline of operations to a JSON array or object.\n *\n * @remarks\n * Operations are applied in order; each step transforms the output of the previous. Supported\n * operations: `filter`, `sort`, `select_keys`, `pluck`, `slice`, `unique`, `unique_by`,\n * `group_by`, `flatten`, `reverse`, `count`, `sum`, `avg`, `median`, `min`, `max`, `first`,\n * `last`, `chunk`, `frequency_count`, `top_n`, `map_template`. Dot-notation paths are supported\n * for nested key access in every operation that takes a `key` field.\n */\nexport const jsonTransformTool = new Tool({\n name: 'json_transform',\n description:\n 'Apply a pipeline of operations to a JSON array or object: filter, sort, group, aggregate (sum/avg/median/min/max), pluck fields, deduplicate, flatten, chunk, frequency count, top-N, and more.',\n inputSchema: validator.object({\n data: validator.string().required().description('JSON data as a string (array or object)'),\n operations: validator\n .array()\n .items(validator.object().unknown(true))\n .required()\n .description(\n 'Pipeline of operations to apply in order. Each step transforms the output of the previous.'\n ),\n }),\n handler: async (args) => {\n const { data: dataStr, operations } = args as {\n data: string\n operations: Operation[]\n }\n\n let data: unknown\n try {\n data = JSON.parse(dataStr)\n } catch {\n return 'Error: Invalid JSON input.'\n }\n\n let current: unknown = data\n\n for (const [i, operation] of operations.entries()) {\n try {\n current = applyOperation(current, operation)\n } catch (err) {\n return `Error in operation ${i + 1} (\"${operation.op}\"): ${isError(err) ? err.message : String(err)}`\n }\n }\n\n if (typeof current === 'string') return current\n return JSON.stringify(current, null, 2)\n },\n})\n\n/**\n * Perform set operations on two JSON arrays.\n *\n * @remarks\n * Supported operations: `intersection`, `union`, `difference`, `symmetric_difference`,\n * `is_member`, `is_subset`, `is_superset`. For arrays of objects, an optional `compare_key`\n * narrows equality to a single property rather than deep structural comparison.\n */\nexport const setOperationsTool = new Tool({\n name: 'set_operations',\n description:\n 'Perform set operations on two JSON arrays: intersection (common elements), union (all elements), difference (in A but not B), symmetric difference, or membership check.',\n inputSchema: validator.object({\n data_a: validator.string().required().description('First JSON array'),\n data_b: validator.string().optional().description('Second JSON array'),\n operation: validator\n .string()\n .valid(\n 'intersection',\n 'union',\n 'difference',\n 'symmetric_difference',\n 'is_member',\n 'is_subset',\n 'is_superset'\n )\n .required()\n .description('Set operation to perform'),\n item: validator.any().optional().description('For is_member: the value to look up in data_a.'),\n compare_key: validator\n .string()\n .optional()\n .description(\n 'For arrays of objects: use this key for equality comparison instead of deep equality.'\n ),\n }),\n handler: async (args) => {\n const {\n data_a: dataA,\n data_b: dataB,\n operation,\n item,\n compare_key: compareKey,\n } = args as {\n data_a: string\n data_b?: string\n operation: string\n item?: unknown\n compare_key?: string\n }\n\n let a: unknown[]\n let b: unknown[] = []\n\n try {\n a = JSON.parse(dataA)\n } catch {\n return 'Error: data_a is not valid JSON.'\n }\n if (!Array.isArray(a)) return 'Error: data_a must be a JSON array.'\n\n if (dataB !== undefined) {\n try {\n b = JSON.parse(dataB)\n } catch {\n return 'Error: data_b is not valid JSON.'\n }\n if (!Array.isArray(b)) return 'Error: data_b must be a JSON array.'\n }\n\n const toKey = (val: unknown): string =>\n compareKey && isObject(val)\n ? String((val as Record<string, unknown>)[compareKey])\n : JSON.stringify(val)\n\n if (operation === 'is_member') {\n const needle = JSON.stringify(item)\n const found = a.some((entry) => JSON.stringify(entry) === needle)\n return found ? `Found: item is in the array.` : `Not found: item is not in the array.`\n }\n\n const setA = new Set(a.map(toKey))\n const setB = new Set(b.map(toKey))\n const indexA = new Map(a.map((entry) => [toKey(entry), entry]))\n\n switch (operation) {\n case 'intersection': {\n const result = [...setA].filter((k) => setB.has(k)).map((k) => indexA.get(k))\n return JSON.stringify(result, null, 2)\n }\n case 'union': {\n const result = [...a, ...b.filter((entry) => !setA.has(toKey(entry)))]\n return JSON.stringify(result, null, 2)\n }\n case 'difference': {\n const result = a.filter((entry) => !setB.has(toKey(entry)))\n return JSON.stringify(result, null, 2)\n }\n case 'symmetric_difference': {\n const result = [\n ...a.filter((entry) => !setB.has(toKey(entry))),\n ...b.filter((entry) => !setA.has(toKey(entry))),\n ]\n return JSON.stringify(result, null, 2)\n }\n case 'is_subset':\n return [...setA].every((k) => setB.has(k))\n ? `Yes: A is a subset of B (all ${a.length} elements of A are in B).`\n : `No: A is not a subset of B.`\n case 'is_superset':\n return [...setB].every((k) => setA.has(k))\n ? `Yes: A is a superset of B (A contains all ${b.length} elements of B).`\n : `No: A is not a superset of B.`\n default:\n return `Error: Unknown operation \"${operation}\".`\n }\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data_structure.cjs","names":[],"sources":["../../../src/batteries/tools/data_structure/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for querying, filtering, grouping, and reshaping structured values.\n *\n * @module @nhtio/adk/batteries/tools/data_structure\n *\n * @remarks\n * Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { validator } from '@nhtio/validation'\nimport { isError, isObject } from '@nhtio/adk/guards'\nimport { bigSum, bigMean, formatBig, bigToNumber } from '@nhtio/adk/lib/helpers/bignum'\nimport type { BigNumber } from 'mathjs'\n\n/**\n * Render a {@link BigNumber} aggregate as a JSON-friendly value: a plain `number` when the result\n * is exactly representable as a float64 (|x| ≤ Number.MAX_SAFE_INTEGER, so existing consumers and\n * tests see a number with no precision loss), or a full-precision string otherwise — covering both\n * overflow (which `JSON.stringify` would turn into `null`) and the gap above 2^53 where float64\n * silently rounds (e.g. 3 × MAX_SAFE_INTEGER).\n */\nfunction aggregateValue(big: BigNumber): number | string {\n const asNum = bigToNumber(big)\n if (Number.isFinite(asNum) && Math.abs(asNum) <= Number.MAX_SAFE_INTEGER) return asNum\n return formatBig(big, 16)\n}\n\nfunction getPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current = obj\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\ntype FilterOperator =\n | 'eq'\n | 'ne'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains'\n | 'starts_with'\n | 'ends_with'\n | 'exists'\n\nfunction matchesFilter(\n item: unknown,\n key: string,\n operator: FilterOperator,\n value: unknown\n): boolean {\n const actual = getPath(item, key)\n switch (operator) {\n case 'eq':\n return actual === value\n case 'ne':\n return actual !== value\n case 'gt':\n return typeof actual === 'number' && actual > (value as number)\n case 'gte':\n return typeof actual === 'number' && actual >= (value as number)\n case 'lt':\n return typeof actual === 'number' && actual < (value as number)\n case 'lte':\n return typeof actual === 'number' && actual <= (value as number)\n case 'contains':\n return typeof actual === 'string' && actual.includes(String(value))\n case 'starts_with':\n return typeof actual === 'string' && actual.startsWith(String(value))\n case 'ends_with':\n return typeof actual === 'string' && actual.endsWith(String(value))\n case 'exists':\n return actual !== undefined && actual !== null\n default:\n return false\n }\n}\n\nfunction medianOf(nums: number[]): number {\n const sorted = [...nums].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]\n}\n\nfunction applyTemplate(template: string, item: unknown): string {\n if (typeof item !== 'object' || item === null) return String(item)\n return template.replace(/\\{\\{([^}]+)\\}\\}/g, (_, key) => {\n const val = getPath(item, key.trim())\n return val === undefined || val === null ? '' : String(val)\n })\n}\n\ntype Operation =\n | { op: 'filter'; key: string; operator: FilterOperator; value?: unknown }\n | { op: 'sort'; key: string; direction?: 'asc' | 'desc' }\n | { op: 'select_keys'; keys: string[] }\n | { op: 'pluck'; key: string }\n | { op: 'slice'; start: number; end?: number }\n | { op: 'unique' }\n | { op: 'unique_by'; key: string }\n | { op: 'group_by'; key: string }\n | { op: 'flatten'; depth?: number }\n | { op: 'reverse' }\n | { op: 'count' }\n | { op: 'sum'; key?: string }\n | { op: 'avg'; key?: string }\n | { op: 'median'; key?: string }\n | { op: 'min'; key?: string }\n | { op: 'max'; key?: string }\n | { op: 'first'; n?: number }\n | { op: 'last'; n?: number }\n | { op: 'chunk'; size: number }\n | { op: 'frequency_count'; key?: string }\n | { op: 'top_n'; n: number; key: string; direction?: 'asc' | 'desc' }\n | { op: 'map_template'; template: string }\n\nfunction applyOperation(data: unknown, op: Operation): unknown {\n // Guard malformed pipeline entries (null, non-object, or missing `op`) so they produce a clear\n // error string rather than a TypeError from dereferencing `op.op`.\n if (op === null || typeof op !== 'object' || typeof (op as { op?: unknown }).op !== 'string') {\n throw new Error('Each operation must be an object with a string \"op\" field.')\n }\n\n if (op.op === 'count') {\n if (Array.isArray(data)) return data.length\n if (isObject(data)) return Object.keys(data).length\n return 0\n }\n\n if (!Array.isArray(data)) {\n throw new Error(`Operation \"${op.op}\" requires an array input.`)\n }\n\n const arr = data as unknown[]\n\n switch (op.op) {\n case 'filter':\n return arr.filter((item) => matchesFilter(item, op.key, op.operator, op.value))\n\n case 'sort': {\n const dir = op.direction === 'desc' ? -1 : 1\n return [...arr].sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (av === bv) return 0\n if (av === undefined || av === null) return 1\n if (bv === undefined || bv === null) return -1\n if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * dir\n return String(av).localeCompare(String(bv)) * dir\n })\n }\n\n case 'select_keys':\n return arr.map((item) => {\n if (typeof item !== 'object' || item === null) return item\n const result: Record<string, unknown> = {}\n for (const key of op.keys) result[key] = (item as Record<string, unknown>)[key]\n return result\n })\n\n case 'pluck':\n return arr.map((item) => getPath(item, op.key))\n\n case 'slice':\n return arr.slice(op.start, op.end)\n\n case 'unique': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = typeof item === 'object' ? JSON.stringify(item) : String(item)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'unique_by': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const raw = getPath(item, op.key)\n // Serialise the key value so deep-equal objects/arrays dedupe by VALUE, not reference —\n // JSON.parse produces a distinct reference per row, so a raw Set never matched them. This\n // must catch BOTH plain objects and arrays, so a raw `typeof === 'object'` is intended here\n // rather than the plain-object-only `isObject` guard.\n // eslint-disable-next-line adk/prefer-is-object\n const isObjectOrArray = typeof raw === 'object' && raw !== null\n const key = isObjectOrArray ? JSON.stringify(raw) : `${typeof raw}:${String(raw)}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'group_by': {\n const groups: Record<string, unknown[]> = {}\n for (const item of arr) {\n const key = String(getPath(item, op.key) ?? '__undefined__')\n if (!groups[key]) groups[key] = []\n groups[key].push(item)\n }\n return groups\n }\n\n case 'flatten':\n return arr.flat(op.depth ?? 1)\n\n case 'reverse':\n return [...arr].reverse()\n\n case 'sum': {\n // The total is accumulated in BigNumber so a sum exceeding float64 stays exact (returned as\n // a precise string) instead of silently becoming Infinity → JSON null.\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n // A non-empty input with no numeric values is almost always a mistake (e.g. an array of\n // objects summed without a `key`). Returning 0 would be silently wrong, so error instead.\n if (nums.length === 0 && arr.length > 0) {\n throw new Error(\n op.key\n ? `No numeric values found at key \"${op.key}\".`\n : 'No numeric values to sum. For an array of objects, pass a \"key\".'\n )\n }\n return aggregateValue(bigSum(nums))\n }\n\n case 'avg': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n // null (not 0) signals \"no numeric data\" — unlike sum, an average has no neutral element,\n // so null is an honest \"no result\" rather than a misleading number.\n if (nums.length === 0) return null\n return aggregateValue(bigMean(nums))\n }\n\n case 'median': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n if (nums.length === 0) return null\n return medianOf(nums)\n }\n\n case 'min': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.min(...nums)\n }\n\n case 'max': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.max(...nums)\n }\n\n case 'first':\n return op.n !== undefined ? arr.slice(0, op.n) : arr[0]\n\n case 'last':\n return op.n !== undefined ? arr.slice(-op.n) : arr[arr.length - 1]\n\n case 'chunk': {\n const size = Math.max(1, Math.floor(op.size))\n const chunks: unknown[][] = []\n for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size))\n return chunks\n }\n\n case 'frequency_count': {\n const freq: Record<string, number> = {}\n for (const item of arr) {\n const key = op.key ? String(getPath(item, op.key) ?? '__undefined__') : String(item)\n freq[key] = (freq[key] ?? 0) + 1\n }\n return freq\n }\n\n case 'top_n': {\n // desc (default) ranks largest-first; asc ranks smallest-first. The base comparator\n // `(bv - av)` / `localeCompare(bv, av)` is descending, so asc flips it.\n const dir = op.direction === 'asc' ? -1 : 1\n return [...arr]\n .sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (typeof av === 'number' && typeof bv === 'number') return (bv - av) * dir\n return String(bv).localeCompare(String(av)) * dir\n })\n .slice(0, op.n)\n }\n\n case 'map_template':\n return arr.map((item) => applyTemplate(op.template, item))\n\n default:\n throw new Error(`Unknown operation: ${(op as { op: string }).op}`)\n }\n}\n\n/**\n * Apply a pipeline of operations to a JSON array or object.\n *\n * @remarks\n * Operations are applied in order; each step transforms the output of the previous. Supported\n * operations: `filter`, `sort`, `select_keys`, `pluck`, `slice`, `unique`, `unique_by`,\n * `group_by`, `flatten`, `reverse`, `count`, `sum`, `avg`, `median`, `min`, `max`, `first`,\n * `last`, `chunk`, `frequency_count`, `top_n`, `map_template`. Dot-notation paths are supported\n * for nested key access in every operation that takes a `key` field.\n */\nexport const jsonTransformTool = new Tool({\n name: 'json_transform',\n description:\n 'Apply a pipeline of operations to a JSON array or object: filter, sort, group, aggregate (sum/avg/median/min/max), pluck fields, deduplicate, flatten, chunk, frequency count, top-N, and more.',\n inputSchema: validator.object({\n data: validator.string().required().description('JSON data as a string (array or object)'),\n operations: validator\n .array()\n .items(validator.object().unknown(true))\n .required()\n .description(\n 'Pipeline of operations to apply in order. Each step transforms the output of the previous.'\n ),\n }),\n handler: async (args) => {\n const { data: dataStr, operations } = args as {\n data: string\n operations: Operation[]\n }\n\n let data: unknown\n try {\n data = JSON.parse(dataStr)\n } catch {\n return 'Error: Invalid JSON input.'\n }\n\n let current: unknown = data\n\n for (const [i, operation] of operations.entries()) {\n try {\n current = applyOperation(current, operation)\n } catch (err) {\n const opName =\n operation && typeof operation === 'object' && 'op' in operation\n ? String((operation as { op: unknown }).op)\n : String(operation)\n return `Error in operation ${i + 1} (\"${opName}\"): ${isError(err) ? err.message : String(err)}`\n }\n }\n\n if (typeof current === 'string') return current\n return JSON.stringify(current, null, 2)\n },\n})\n\n/**\n * Perform set operations on two JSON arrays.\n *\n * @remarks\n * Supported operations: `intersection`, `union`, `difference`, `symmetric_difference`,\n * `is_member`, `is_subset`, `is_superset`. For arrays of objects, an optional `compare_key`\n * narrows equality to a single property rather than deep structural comparison.\n */\nexport const setOperationsTool = new Tool({\n name: 'set_operations',\n description:\n 'Perform set operations on two JSON arrays: intersection (common elements), union (all elements), difference (in A but not B), symmetric difference, or membership check.',\n inputSchema: validator.object({\n data_a: validator.string().required().description('First JSON array'),\n data_b: validator.string().optional().description('Second JSON array'),\n operation: validator\n .string()\n .valid(\n 'intersection',\n 'union',\n 'difference',\n 'symmetric_difference',\n 'is_member',\n 'is_subset',\n 'is_superset'\n )\n .required()\n .description('Set operation to perform'),\n item: validator.any().optional().description('For is_member: the value to look up in data_a.'),\n compare_key: validator\n .string()\n .optional()\n .description(\n 'For arrays of objects: use this key for equality comparison instead of deep equality.'\n ),\n }),\n handler: async (args) => {\n const {\n data_a: dataA,\n data_b: dataB,\n operation,\n item,\n compare_key: compareKey,\n } = args as {\n data_a: string\n data_b?: string\n operation: string\n item?: unknown\n compare_key?: string\n }\n\n let a: unknown[]\n let b: unknown[] = []\n\n try {\n a = JSON.parse(dataA)\n } catch {\n return 'Error: data_a is not valid JSON.'\n }\n if (!Array.isArray(a)) return 'Error: data_a must be a JSON array.'\n\n if (dataB !== undefined) {\n try {\n b = JSON.parse(dataB)\n } catch {\n return 'Error: data_b is not valid JSON.'\n }\n if (!Array.isArray(b)) return 'Error: data_b must be a JSON array.'\n }\n\n const toKey = (val: unknown): string =>\n compareKey && isObject(val)\n ? String((val as Record<string, unknown>)[compareKey])\n : JSON.stringify(val)\n\n if (operation === 'is_member') {\n const needle = JSON.stringify(item)\n const found = a.some((entry) => JSON.stringify(entry) === needle)\n return found ? `Found: item is in the array.` : `Not found: item is not in the array.`\n }\n\n const setA = new Set(a.map(toKey))\n const setB = new Set(b.map(toKey))\n const indexA = new Map(a.map((entry) => [toKey(entry), entry]))\n\n switch (operation) {\n case 'intersection': {\n const result = [...setA].filter((k) => setB.has(k)).map((k) => indexA.get(k))\n return JSON.stringify(result, null, 2)\n }\n case 'union': {\n const result = [...a, ...b.filter((entry) => !setA.has(toKey(entry)))]\n return JSON.stringify(result, null, 2)\n }\n case 'difference': {\n const result = a.filter((entry) => !setB.has(toKey(entry)))\n return JSON.stringify(result, null, 2)\n }\n case 'symmetric_difference': {\n const result = [\n ...a.filter((entry) => !setB.has(toKey(entry))),\n ...b.filter((entry) => !setA.has(toKey(entry))),\n ]\n return JSON.stringify(result, null, 2)\n }\n case 'is_subset':\n return [...setA].every((k) => setB.has(k))\n ? `Yes: A is a subset of B (all ${a.length} elements of A are in B).`\n : `No: A is not a subset of B.`\n case 'is_superset':\n return [...setB].every((k) => setA.has(k))\n ? `Yes: A is a superset of B (A contains all ${b.length} elements of B).`\n : `No: A is not a superset of B.`\n default:\n return `Error: Unknown operation \"${operation}\".`\n }\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { c as isObject, o as isError } from "../../tool_registry-
|
|
2
|
-
import { t as Tool } from "../../tool-
|
|
3
|
-
import "../../common-
|
|
1
|
+
import { c as isObject, o as isError } from "../../tool_registry-791Vrjtf.mjs";
|
|
2
|
+
import { t as Tool } from "../../tool-wMYMVl60.mjs";
|
|
3
|
+
import "../../common-DYDUi99O.mjs";
|
|
4
4
|
import "../../guards.mjs";
|
|
5
|
+
import { bigMean, bigSum, bigToNumber, formatBig } from "../../lib/helpers/bignum.mjs";
|
|
5
6
|
import { validator } from "@nhtio/validation";
|
|
6
7
|
//#region src/batteries/tools/data_structure/index.ts
|
|
7
8
|
/**
|
|
@@ -13,6 +14,18 @@ import { validator } from "@nhtio/validation";
|
|
|
13
14
|
* Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole
|
|
14
15
|
* category, or import every tool via `@nhtio/adk/batteries`.
|
|
15
16
|
*/
|
|
17
|
+
/**
|
|
18
|
+
* Render a {@link BigNumber} aggregate as a JSON-friendly value: a plain `number` when the result
|
|
19
|
+
* is exactly representable as a float64 (|x| ≤ Number.MAX_SAFE_INTEGER, so existing consumers and
|
|
20
|
+
* tests see a number with no precision loss), or a full-precision string otherwise — covering both
|
|
21
|
+
* overflow (which `JSON.stringify` would turn into `null`) and the gap above 2^53 where float64
|
|
22
|
+
* silently rounds (e.g. 3 × MAX_SAFE_INTEGER).
|
|
23
|
+
*/
|
|
24
|
+
function aggregateValue(big) {
|
|
25
|
+
const asNum = bigToNumber(big);
|
|
26
|
+
if (Number.isFinite(asNum) && Math.abs(asNum) <= Number.MAX_SAFE_INTEGER) return asNum;
|
|
27
|
+
return formatBig(big, 16);
|
|
28
|
+
}
|
|
16
29
|
function getPath(obj, path) {
|
|
17
30
|
const parts = path.split(".");
|
|
18
31
|
let current = obj;
|
|
@@ -51,6 +64,7 @@ function applyTemplate(template, item) {
|
|
|
51
64
|
});
|
|
52
65
|
}
|
|
53
66
|
function applyOperation(data, op) {
|
|
67
|
+
if (op === null || typeof op !== "object" || typeof op.op !== "string") throw new Error("Each operation must be an object with a string \"op\" field.");
|
|
54
68
|
if (op.op === "count") {
|
|
55
69
|
if (Array.isArray(data)) return data.length;
|
|
56
70
|
if (isObject(data)) return Object.keys(data).length;
|
|
@@ -92,7 +106,8 @@ function applyOperation(data, op) {
|
|
|
92
106
|
case "unique_by": {
|
|
93
107
|
const seen = /* @__PURE__ */ new Set();
|
|
94
108
|
return arr.filter((item) => {
|
|
95
|
-
const
|
|
109
|
+
const raw = getPath(item, op.key);
|
|
110
|
+
const key = typeof raw === "object" && raw !== null ? JSON.stringify(raw) : `${typeof raw}:${String(raw)}`;
|
|
96
111
|
if (seen.has(key)) return false;
|
|
97
112
|
seen.add(key);
|
|
98
113
|
return true;
|
|
@@ -109,14 +124,18 @@ function applyOperation(data, op) {
|
|
|
109
124
|
}
|
|
110
125
|
case "flatten": return arr.flat(op.depth ?? 1);
|
|
111
126
|
case "reverse": return [...arr].reverse();
|
|
112
|
-
case "sum":
|
|
127
|
+
case "sum": {
|
|
128
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
129
|
+
if (nums.length === 0 && arr.length > 0) throw new Error(op.key ? `No numeric values found at key "${op.key}".` : "No numeric values to sum. For an array of objects, pass a \"key\".");
|
|
130
|
+
return aggregateValue(bigSum(nums));
|
|
131
|
+
}
|
|
113
132
|
case "avg": {
|
|
114
|
-
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number");
|
|
133
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
115
134
|
if (nums.length === 0) return null;
|
|
116
|
-
return
|
|
135
|
+
return aggregateValue(bigMean(nums));
|
|
117
136
|
}
|
|
118
137
|
case "median": {
|
|
119
|
-
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number");
|
|
138
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
120
139
|
if (nums.length === 0) return null;
|
|
121
140
|
return medianOf(nums);
|
|
122
141
|
}
|
|
@@ -147,7 +166,7 @@ function applyOperation(data, op) {
|
|
|
147
166
|
return freq;
|
|
148
167
|
}
|
|
149
168
|
case "top_n": {
|
|
150
|
-
const dir = op.direction === "asc" ? 1 :
|
|
169
|
+
const dir = op.direction === "asc" ? -1 : 1;
|
|
151
170
|
return [...arr].sort((a, b) => {
|
|
152
171
|
const av = getPath(a, op.key);
|
|
153
172
|
const bv = getPath(b, op.key);
|
|
@@ -188,7 +207,8 @@ var jsonTransformTool = new Tool({
|
|
|
188
207
|
for (const [i, operation] of operations.entries()) try {
|
|
189
208
|
current = applyOperation(current, operation);
|
|
190
209
|
} catch (err) {
|
|
191
|
-
|
|
210
|
+
const opName = operation && typeof operation === "object" && "op" in operation ? String(operation.op) : String(operation);
|
|
211
|
+
return `Error in operation ${i + 1} ("${opName}"): ${isError(err) ? err.message : String(err)}`;
|
|
192
212
|
}
|
|
193
213
|
if (typeof current === "string") return current;
|
|
194
214
|
return JSON.stringify(current, null, 2);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data_structure.mjs","names":[],"sources":["../../../src/batteries/tools/data_structure/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for querying, filtering, grouping, and reshaping structured values.\n *\n * @module @nhtio/adk/batteries/tools/data_structure\n *\n * @remarks\n * Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { validator } from '@nhtio/validation'\nimport { isError, isObject } from '@nhtio/adk/guards'\n\nfunction getPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current = obj\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\ntype FilterOperator =\n | 'eq'\n | 'ne'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains'\n | 'starts_with'\n | 'ends_with'\n | 'exists'\n\nfunction matchesFilter(\n item: unknown,\n key: string,\n operator: FilterOperator,\n value: unknown\n): boolean {\n const actual = getPath(item, key)\n switch (operator) {\n case 'eq':\n return actual === value\n case 'ne':\n return actual !== value\n case 'gt':\n return typeof actual === 'number' && actual > (value as number)\n case 'gte':\n return typeof actual === 'number' && actual >= (value as number)\n case 'lt':\n return typeof actual === 'number' && actual < (value as number)\n case 'lte':\n return typeof actual === 'number' && actual <= (value as number)\n case 'contains':\n return typeof actual === 'string' && actual.includes(String(value))\n case 'starts_with':\n return typeof actual === 'string' && actual.startsWith(String(value))\n case 'ends_with':\n return typeof actual === 'string' && actual.endsWith(String(value))\n case 'exists':\n return actual !== undefined && actual !== null\n default:\n return false\n }\n}\n\nfunction medianOf(nums: number[]): number {\n const sorted = [...nums].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]\n}\n\nfunction applyTemplate(template: string, item: unknown): string {\n if (typeof item !== 'object' || item === null) return String(item)\n return template.replace(/\\{\\{([^}]+)\\}\\}/g, (_, key) => {\n const val = getPath(item, key.trim())\n return val === undefined || val === null ? '' : String(val)\n })\n}\n\ntype Operation =\n | { op: 'filter'; key: string; operator: FilterOperator; value?: unknown }\n | { op: 'sort'; key: string; direction?: 'asc' | 'desc' }\n | { op: 'select_keys'; keys: string[] }\n | { op: 'pluck'; key: string }\n | { op: 'slice'; start: number; end?: number }\n | { op: 'unique' }\n | { op: 'unique_by'; key: string }\n | { op: 'group_by'; key: string }\n | { op: 'flatten'; depth?: number }\n | { op: 'reverse' }\n | { op: 'count' }\n | { op: 'sum'; key?: string }\n | { op: 'avg'; key?: string }\n | { op: 'median'; key?: string }\n | { op: 'min'; key?: string }\n | { op: 'max'; key?: string }\n | { op: 'first'; n?: number }\n | { op: 'last'; n?: number }\n | { op: 'chunk'; size: number }\n | { op: 'frequency_count'; key?: string }\n | { op: 'top_n'; n: number; key: string; direction?: 'asc' | 'desc' }\n | { op: 'map_template'; template: string }\n\nfunction applyOperation(data: unknown, op: Operation): unknown {\n if (op.op === 'count') {\n if (Array.isArray(data)) return data.length\n if (isObject(data)) return Object.keys(data).length\n return 0\n }\n\n if (!Array.isArray(data)) {\n throw new Error(`Operation \"${op.op}\" requires an array input.`)\n }\n\n const arr = data as unknown[]\n\n switch (op.op) {\n case 'filter':\n return arr.filter((item) => matchesFilter(item, op.key, op.operator, op.value))\n\n case 'sort': {\n const dir = op.direction === 'desc' ? -1 : 1\n return [...arr].sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (av === bv) return 0\n if (av === undefined || av === null) return 1\n if (bv === undefined || bv === null) return -1\n if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * dir\n return String(av).localeCompare(String(bv)) * dir\n })\n }\n\n case 'select_keys':\n return arr.map((item) => {\n if (typeof item !== 'object' || item === null) return item\n const result: Record<string, unknown> = {}\n for (const key of op.keys) result[key] = (item as Record<string, unknown>)[key]\n return result\n })\n\n case 'pluck':\n return arr.map((item) => getPath(item, op.key))\n\n case 'slice':\n return arr.slice(op.start, op.end)\n\n case 'unique': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = typeof item === 'object' ? JSON.stringify(item) : String(item)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'unique_by': {\n const seen = new Set<unknown>()\n return arr.filter((item) => {\n const key = getPath(item, op.key)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'group_by': {\n const groups: Record<string, unknown[]> = {}\n for (const item of arr) {\n const key = String(getPath(item, op.key) ?? '__undefined__')\n if (!groups[key]) groups[key] = []\n groups[key].push(item)\n }\n return groups\n }\n\n case 'flatten':\n return arr.flat(op.depth ?? 1)\n\n case 'reverse':\n return [...arr].reverse()\n\n case 'sum': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n return values.reduce<number>((acc, v) => acc + (typeof v === 'number' ? v : 0), 0)\n }\n\n case 'avg': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return nums.reduce((a, b) => a + b, 0) / nums.length\n }\n\n case 'median': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return medianOf(nums)\n }\n\n case 'min': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.min(...nums)\n }\n\n case 'max': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.max(...nums)\n }\n\n case 'first':\n return op.n !== undefined ? arr.slice(0, op.n) : arr[0]\n\n case 'last':\n return op.n !== undefined ? arr.slice(-op.n) : arr[arr.length - 1]\n\n case 'chunk': {\n const size = Math.max(1, Math.floor(op.size))\n const chunks: unknown[][] = []\n for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size))\n return chunks\n }\n\n case 'frequency_count': {\n const freq: Record<string, number> = {}\n for (const item of arr) {\n const key = op.key ? String(getPath(item, op.key) ?? '__undefined__') : String(item)\n freq[key] = (freq[key] ?? 0) + 1\n }\n return freq\n }\n\n case 'top_n': {\n const dir = op.direction === 'asc' ? 1 : -1\n return [...arr]\n .sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (typeof av === 'number' && typeof bv === 'number') return (bv - av) * dir\n return String(bv).localeCompare(String(av)) * dir\n })\n .slice(0, op.n)\n }\n\n case 'map_template':\n return arr.map((item) => applyTemplate(op.template, item))\n\n default:\n throw new Error(`Unknown operation: ${(op as { op: string }).op}`)\n }\n}\n\n/**\n * Apply a pipeline of operations to a JSON array or object.\n *\n * @remarks\n * Operations are applied in order; each step transforms the output of the previous. Supported\n * operations: `filter`, `sort`, `select_keys`, `pluck`, `slice`, `unique`, `unique_by`,\n * `group_by`, `flatten`, `reverse`, `count`, `sum`, `avg`, `median`, `min`, `max`, `first`,\n * `last`, `chunk`, `frequency_count`, `top_n`, `map_template`. Dot-notation paths are supported\n * for nested key access in every operation that takes a `key` field.\n */\nexport const jsonTransformTool = new Tool({\n name: 'json_transform',\n description:\n 'Apply a pipeline of operations to a JSON array or object: filter, sort, group, aggregate (sum/avg/median/min/max), pluck fields, deduplicate, flatten, chunk, frequency count, top-N, and more.',\n inputSchema: validator.object({\n data: validator.string().required().description('JSON data as a string (array or object)'),\n operations: validator\n .array()\n .items(validator.object().unknown(true))\n .required()\n .description(\n 'Pipeline of operations to apply in order. Each step transforms the output of the previous.'\n ),\n }),\n handler: async (args) => {\n const { data: dataStr, operations } = args as {\n data: string\n operations: Operation[]\n }\n\n let data: unknown\n try {\n data = JSON.parse(dataStr)\n } catch {\n return 'Error: Invalid JSON input.'\n }\n\n let current: unknown = data\n\n for (const [i, operation] of operations.entries()) {\n try {\n current = applyOperation(current, operation)\n } catch (err) {\n return `Error in operation ${i + 1} (\"${operation.op}\"): ${isError(err) ? err.message : String(err)}`\n }\n }\n\n if (typeof current === 'string') return current\n return JSON.stringify(current, null, 2)\n },\n})\n\n/**\n * Perform set operations on two JSON arrays.\n *\n * @remarks\n * Supported operations: `intersection`, `union`, `difference`, `symmetric_difference`,\n * `is_member`, `is_subset`, `is_superset`. For arrays of objects, an optional `compare_key`\n * narrows equality to a single property rather than deep structural comparison.\n */\nexport const setOperationsTool = new Tool({\n name: 'set_operations',\n description:\n 'Perform set operations on two JSON arrays: intersection (common elements), union (all elements), difference (in A but not B), symmetric difference, or membership check.',\n inputSchema: validator.object({\n data_a: validator.string().required().description('First JSON array'),\n data_b: validator.string().optional().description('Second JSON array'),\n operation: validator\n .string()\n .valid(\n 'intersection',\n 'union',\n 'difference',\n 'symmetric_difference',\n 'is_member',\n 'is_subset',\n 'is_superset'\n )\n .required()\n .description('Set operation to perform'),\n item: validator.any().optional().description('For is_member: the value to look up in data_a.'),\n compare_key: validator\n .string()\n .optional()\n .description(\n 'For arrays of objects: use this key for equality comparison instead of deep equality.'\n ),\n }),\n handler: async (args) => {\n const {\n data_a: dataA,\n data_b: dataB,\n operation,\n item,\n compare_key: compareKey,\n } = args as {\n data_a: string\n data_b?: string\n operation: string\n item?: unknown\n compare_key?: string\n }\n\n let a: unknown[]\n let b: unknown[] = []\n\n try {\n a = JSON.parse(dataA)\n } catch {\n return 'Error: data_a is not valid JSON.'\n }\n if (!Array.isArray(a)) return 'Error: data_a must be a JSON array.'\n\n if (dataB !== undefined) {\n try {\n b = JSON.parse(dataB)\n } catch {\n return 'Error: data_b is not valid JSON.'\n }\n if (!Array.isArray(b)) return 'Error: data_b must be a JSON array.'\n }\n\n const toKey = (val: unknown): string =>\n compareKey && isObject(val)\n ? String((val as Record<string, unknown>)[compareKey])\n : JSON.stringify(val)\n\n if (operation === 'is_member') {\n const needle = JSON.stringify(item)\n const found = a.some((entry) => JSON.stringify(entry) === needle)\n return found ? `Found: item is in the array.` : `Not found: item is not in the array.`\n }\n\n const setA = new Set(a.map(toKey))\n const setB = new Set(b.map(toKey))\n const indexA = new Map(a.map((entry) => [toKey(entry), entry]))\n\n switch (operation) {\n case 'intersection': {\n const result = [...setA].filter((k) => setB.has(k)).map((k) => indexA.get(k))\n return JSON.stringify(result, null, 2)\n }\n case 'union': {\n const result = [...a, ...b.filter((entry) => !setA.has(toKey(entry)))]\n return JSON.stringify(result, null, 2)\n }\n case 'difference': {\n const result = a.filter((entry) => !setB.has(toKey(entry)))\n return JSON.stringify(result, null, 2)\n }\n case 'symmetric_difference': {\n const result = [\n ...a.filter((entry) => !setB.has(toKey(entry))),\n ...b.filter((entry) => !setA.has(toKey(entry))),\n ]\n return JSON.stringify(result, null, 2)\n }\n case 'is_subset':\n return [...setA].every((k) => setB.has(k))\n ? `Yes: A is a subset of B (all ${a.length} elements of A are in B).`\n : `No: A is not a subset of B.`\n case 'is_superset':\n return [...setB].every((k) => setA.has(k))\n ? `Yes: A is a superset of B (A contains all ${b.length} elements of B).`\n : `No: A is not a superset of B.`\n default:\n return `Error: Unknown operation \"${operation}\".`\n }\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data_structure.mjs","names":[],"sources":["../../../src/batteries/tools/data_structure/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for querying, filtering, grouping, and reshaping structured values.\n *\n * @module @nhtio/adk/batteries/tools/data_structure\n *\n * @remarks\n * Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { validator } from '@nhtio/validation'\nimport { isError, isObject } from '@nhtio/adk/guards'\nimport { bigSum, bigMean, formatBig, bigToNumber } from '@nhtio/adk/lib/helpers/bignum'\nimport type { BigNumber } from 'mathjs'\n\n/**\n * Render a {@link BigNumber} aggregate as a JSON-friendly value: a plain `number` when the result\n * is exactly representable as a float64 (|x| ≤ Number.MAX_SAFE_INTEGER, so existing consumers and\n * tests see a number with no precision loss), or a full-precision string otherwise — covering both\n * overflow (which `JSON.stringify` would turn into `null`) and the gap above 2^53 where float64\n * silently rounds (e.g. 3 × MAX_SAFE_INTEGER).\n */\nfunction aggregateValue(big: BigNumber): number | string {\n const asNum = bigToNumber(big)\n if (Number.isFinite(asNum) && Math.abs(asNum) <= Number.MAX_SAFE_INTEGER) return asNum\n return formatBig(big, 16)\n}\n\nfunction getPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current = obj\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\ntype FilterOperator =\n | 'eq'\n | 'ne'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains'\n | 'starts_with'\n | 'ends_with'\n | 'exists'\n\nfunction matchesFilter(\n item: unknown,\n key: string,\n operator: FilterOperator,\n value: unknown\n): boolean {\n const actual = getPath(item, key)\n switch (operator) {\n case 'eq':\n return actual === value\n case 'ne':\n return actual !== value\n case 'gt':\n return typeof actual === 'number' && actual > (value as number)\n case 'gte':\n return typeof actual === 'number' && actual >= (value as number)\n case 'lt':\n return typeof actual === 'number' && actual < (value as number)\n case 'lte':\n return typeof actual === 'number' && actual <= (value as number)\n case 'contains':\n return typeof actual === 'string' && actual.includes(String(value))\n case 'starts_with':\n return typeof actual === 'string' && actual.startsWith(String(value))\n case 'ends_with':\n return typeof actual === 'string' && actual.endsWith(String(value))\n case 'exists':\n return actual !== undefined && actual !== null\n default:\n return false\n }\n}\n\nfunction medianOf(nums: number[]): number {\n const sorted = [...nums].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]\n}\n\nfunction applyTemplate(template: string, item: unknown): string {\n if (typeof item !== 'object' || item === null) return String(item)\n return template.replace(/\\{\\{([^}]+)\\}\\}/g, (_, key) => {\n const val = getPath(item, key.trim())\n return val === undefined || val === null ? '' : String(val)\n })\n}\n\ntype Operation =\n | { op: 'filter'; key: string; operator: FilterOperator; value?: unknown }\n | { op: 'sort'; key: string; direction?: 'asc' | 'desc' }\n | { op: 'select_keys'; keys: string[] }\n | { op: 'pluck'; key: string }\n | { op: 'slice'; start: number; end?: number }\n | { op: 'unique' }\n | { op: 'unique_by'; key: string }\n | { op: 'group_by'; key: string }\n | { op: 'flatten'; depth?: number }\n | { op: 'reverse' }\n | { op: 'count' }\n | { op: 'sum'; key?: string }\n | { op: 'avg'; key?: string }\n | { op: 'median'; key?: string }\n | { op: 'min'; key?: string }\n | { op: 'max'; key?: string }\n | { op: 'first'; n?: number }\n | { op: 'last'; n?: number }\n | { op: 'chunk'; size: number }\n | { op: 'frequency_count'; key?: string }\n | { op: 'top_n'; n: number; key: string; direction?: 'asc' | 'desc' }\n | { op: 'map_template'; template: string }\n\nfunction applyOperation(data: unknown, op: Operation): unknown {\n // Guard malformed pipeline entries (null, non-object, or missing `op`) so they produce a clear\n // error string rather than a TypeError from dereferencing `op.op`.\n if (op === null || typeof op !== 'object' || typeof (op as { op?: unknown }).op !== 'string') {\n throw new Error('Each operation must be an object with a string \"op\" field.')\n }\n\n if (op.op === 'count') {\n if (Array.isArray(data)) return data.length\n if (isObject(data)) return Object.keys(data).length\n return 0\n }\n\n if (!Array.isArray(data)) {\n throw new Error(`Operation \"${op.op}\" requires an array input.`)\n }\n\n const arr = data as unknown[]\n\n switch (op.op) {\n case 'filter':\n return arr.filter((item) => matchesFilter(item, op.key, op.operator, op.value))\n\n case 'sort': {\n const dir = op.direction === 'desc' ? -1 : 1\n return [...arr].sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (av === bv) return 0\n if (av === undefined || av === null) return 1\n if (bv === undefined || bv === null) return -1\n if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * dir\n return String(av).localeCompare(String(bv)) * dir\n })\n }\n\n case 'select_keys':\n return arr.map((item) => {\n if (typeof item !== 'object' || item === null) return item\n const result: Record<string, unknown> = {}\n for (const key of op.keys) result[key] = (item as Record<string, unknown>)[key]\n return result\n })\n\n case 'pluck':\n return arr.map((item) => getPath(item, op.key))\n\n case 'slice':\n return arr.slice(op.start, op.end)\n\n case 'unique': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = typeof item === 'object' ? JSON.stringify(item) : String(item)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'unique_by': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const raw = getPath(item, op.key)\n // Serialise the key value so deep-equal objects/arrays dedupe by VALUE, not reference —\n // JSON.parse produces a distinct reference per row, so a raw Set never matched them. This\n // must catch BOTH plain objects and arrays, so a raw `typeof === 'object'` is intended here\n // rather than the plain-object-only `isObject` guard.\n // eslint-disable-next-line adk/prefer-is-object\n const isObjectOrArray = typeof raw === 'object' && raw !== null\n const key = isObjectOrArray ? JSON.stringify(raw) : `${typeof raw}:${String(raw)}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'group_by': {\n const groups: Record<string, unknown[]> = {}\n for (const item of arr) {\n const key = String(getPath(item, op.key) ?? '__undefined__')\n if (!groups[key]) groups[key] = []\n groups[key].push(item)\n }\n return groups\n }\n\n case 'flatten':\n return arr.flat(op.depth ?? 1)\n\n case 'reverse':\n return [...arr].reverse()\n\n case 'sum': {\n // The total is accumulated in BigNumber so a sum exceeding float64 stays exact (returned as\n // a precise string) instead of silently becoming Infinity → JSON null.\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n // A non-empty input with no numeric values is almost always a mistake (e.g. an array of\n // objects summed without a `key`). Returning 0 would be silently wrong, so error instead.\n if (nums.length === 0 && arr.length > 0) {\n throw new Error(\n op.key\n ? `No numeric values found at key \"${op.key}\".`\n : 'No numeric values to sum. For an array of objects, pass a \"key\".'\n )\n }\n return aggregateValue(bigSum(nums))\n }\n\n case 'avg': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n // null (not 0) signals \"no numeric data\" — unlike sum, an average has no neutral element,\n // so null is an honest \"no result\" rather than a misleading number.\n if (nums.length === 0) return null\n return aggregateValue(bigMean(nums))\n }\n\n case 'median': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n if (nums.length === 0) return null\n return medianOf(nums)\n }\n\n case 'min': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.min(...nums)\n }\n\n case 'max': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.max(...nums)\n }\n\n case 'first':\n return op.n !== undefined ? arr.slice(0, op.n) : arr[0]\n\n case 'last':\n return op.n !== undefined ? arr.slice(-op.n) : arr[arr.length - 1]\n\n case 'chunk': {\n const size = Math.max(1, Math.floor(op.size))\n const chunks: unknown[][] = []\n for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size))\n return chunks\n }\n\n case 'frequency_count': {\n const freq: Record<string, number> = {}\n for (const item of arr) {\n const key = op.key ? String(getPath(item, op.key) ?? '__undefined__') : String(item)\n freq[key] = (freq[key] ?? 0) + 1\n }\n return freq\n }\n\n case 'top_n': {\n // desc (default) ranks largest-first; asc ranks smallest-first. The base comparator\n // `(bv - av)` / `localeCompare(bv, av)` is descending, so asc flips it.\n const dir = op.direction === 'asc' ? -1 : 1\n return [...arr]\n .sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (typeof av === 'number' && typeof bv === 'number') return (bv - av) * dir\n return String(bv).localeCompare(String(av)) * dir\n })\n .slice(0, op.n)\n }\n\n case 'map_template':\n return arr.map((item) => applyTemplate(op.template, item))\n\n default:\n throw new Error(`Unknown operation: ${(op as { op: string }).op}`)\n }\n}\n\n/**\n * Apply a pipeline of operations to a JSON array or object.\n *\n * @remarks\n * Operations are applied in order; each step transforms the output of the previous. Supported\n * operations: `filter`, `sort`, `select_keys`, `pluck`, `slice`, `unique`, `unique_by`,\n * `group_by`, `flatten`, `reverse`, `count`, `sum`, `avg`, `median`, `min`, `max`, `first`,\n * `last`, `chunk`, `frequency_count`, `top_n`, `map_template`. Dot-notation paths are supported\n * for nested key access in every operation that takes a `key` field.\n */\nexport const jsonTransformTool = new Tool({\n name: 'json_transform',\n description:\n 'Apply a pipeline of operations to a JSON array or object: filter, sort, group, aggregate (sum/avg/median/min/max), pluck fields, deduplicate, flatten, chunk, frequency count, top-N, and more.',\n inputSchema: validator.object({\n data: validator.string().required().description('JSON data as a string (array or object)'),\n operations: validator\n .array()\n .items(validator.object().unknown(true))\n .required()\n .description(\n 'Pipeline of operations to apply in order. Each step transforms the output of the previous.'\n ),\n }),\n handler: async (args) => {\n const { data: dataStr, operations } = args as {\n data: string\n operations: Operation[]\n }\n\n let data: unknown\n try {\n data = JSON.parse(dataStr)\n } catch {\n return 'Error: Invalid JSON input.'\n }\n\n let current: unknown = data\n\n for (const [i, operation] of operations.entries()) {\n try {\n current = applyOperation(current, operation)\n } catch (err) {\n const opName =\n operation && typeof operation === 'object' && 'op' in operation\n ? String((operation as { op: unknown }).op)\n : String(operation)\n return `Error in operation ${i + 1} (\"${opName}\"): ${isError(err) ? err.message : String(err)}`\n }\n }\n\n if (typeof current === 'string') return current\n return JSON.stringify(current, null, 2)\n },\n})\n\n/**\n * Perform set operations on two JSON arrays.\n *\n * @remarks\n * Supported operations: `intersection`, `union`, `difference`, `symmetric_difference`,\n * `is_member`, `is_subset`, `is_superset`. For arrays of objects, an optional `compare_key`\n * narrows equality to a single property rather than deep structural comparison.\n */\nexport const setOperationsTool = new Tool({\n name: 'set_operations',\n description:\n 'Perform set operations on two JSON arrays: intersection (common elements), union (all elements), difference (in A but not B), symmetric difference, or membership check.',\n inputSchema: validator.object({\n data_a: validator.string().required().description('First JSON array'),\n data_b: validator.string().optional().description('Second JSON array'),\n operation: validator\n .string()\n .valid(\n 'intersection',\n 'union',\n 'difference',\n 'symmetric_difference',\n 'is_member',\n 'is_subset',\n 'is_superset'\n )\n .required()\n .description('Set operation to perform'),\n item: validator.any().optional().description('For is_member: the value to look up in data_a.'),\n compare_key: validator\n .string()\n .optional()\n .description(\n 'For arrays of objects: use this key for equality comparison instead of deep equality.'\n ),\n }),\n handler: async (args) => {\n const {\n data_a: dataA,\n data_b: dataB,\n operation,\n item,\n compare_key: compareKey,\n } = args as {\n data_a: string\n data_b?: string\n operation: string\n item?: unknown\n compare_key?: string\n }\n\n let a: unknown[]\n let b: unknown[] = []\n\n try {\n a = JSON.parse(dataA)\n } catch {\n return 'Error: data_a is not valid JSON.'\n }\n if (!Array.isArray(a)) return 'Error: data_a must be a JSON array.'\n\n if (dataB !== undefined) {\n try {\n b = JSON.parse(dataB)\n } catch {\n return 'Error: data_b is not valid JSON.'\n }\n if (!Array.isArray(b)) return 'Error: data_b must be a JSON array.'\n }\n\n const toKey = (val: unknown): string =>\n compareKey && isObject(val)\n ? String((val as Record<string, unknown>)[compareKey])\n : JSON.stringify(val)\n\n if (operation === 'is_member') {\n const needle = JSON.stringify(item)\n const found = a.some((entry) => JSON.stringify(entry) === needle)\n return found ? `Found: item is in the array.` : `Not found: item is not in the array.`\n }\n\n const setA = new Set(a.map(toKey))\n const setB = new Set(b.map(toKey))\n const indexA = new Map(a.map((entry) => [toKey(entry), entry]))\n\n switch (operation) {\n case 'intersection': {\n const result = [...setA].filter((k) => setB.has(k)).map((k) => indexA.get(k))\n return JSON.stringify(result, null, 2)\n }\n case 'union': {\n const result = [...a, ...b.filter((entry) => !setA.has(toKey(entry)))]\n return JSON.stringify(result, null, 2)\n }\n case 'difference': {\n const result = a.filter((entry) => !setB.has(toKey(entry)))\n return JSON.stringify(result, null, 2)\n }\n case 'symmetric_difference': {\n const result = [\n ...a.filter((entry) => !setB.has(toKey(entry))),\n ...b.filter((entry) => !setA.has(toKey(entry))),\n ]\n return JSON.stringify(result, null, 2)\n }\n case 'is_subset':\n return [...setA].every((k) => setB.has(k))\n ? `Yes: A is a subset of B (all ${a.length} elements of A are in B).`\n : `No: A is not a subset of B.`\n case 'is_superset':\n return [...setB].every((k) => setA.has(k))\n ? `Yes: A is a superset of B (A contains all ${b.length} elements of B).`\n : `No: A is not a superset of B.`\n default:\n return `Error: Unknown operation \"${operation}\".`\n }\n },\n})\n"],"mappings":"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"}
|