@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
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { t as createException } from "./exceptions-BDhN0Xzr.mjs";
|
|
2
|
+
import { o as isError } from "./tool_registry-791Vrjtf.mjs";
|
|
3
|
+
import { t as Tool } from "./tool-wMYMVl60.mjs";
|
|
4
|
+
import { n as SpooledJsonArtifact } from "./spooled_markdown_artifact-wkrBF3oX.mjs";
|
|
5
|
+
import "./factories.mjs";
|
|
6
|
+
import "./forge.mjs";
|
|
7
|
+
import "./guards.mjs";
|
|
8
|
+
import "./spooled_artifact.mjs";
|
|
9
|
+
import { isShortCircuit, makeShortCircuit, resolveArtifact, resolveArtifactSync, resolveHeaders, runInputPipeline, runOutputPipeline } from "./batteries/tools/_shared.mjs";
|
|
10
|
+
import { validator } from "@nhtio/validation";
|
|
11
|
+
import { Middleware } from "@nhtio/middleware";
|
|
12
|
+
//#region src/batteries/tools/searxng/exceptions.ts
|
|
13
|
+
/**
|
|
14
|
+
* Battery-scoped exception constructors for the SearXNG search tool.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* Battery-scoped exception classes owned by the SearXNG tool battery (not the ADK core). Minted
|
|
18
|
+
* via `createException` from `@nhtio/adk/factories` and re-exported from the battery's barrel
|
|
19
|
+
* (`@nhtio/adk/batteries/tools/searxng`). This file intentionally carries **no** `@module` tag:
|
|
20
|
+
* it is an internal sibling relative-imported by `index.ts`, so it does not mint its own
|
|
21
|
+
* `…/searxng/exceptions` entrypoint (whose `exceptions` leaf basename would collide with sibling
|
|
22
|
+
* batteries under the `vite-plugin-dts` rolled-up `.d.ts` rule).
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Thrown when {@link createSearxngSearchTool} receives invalid configuration.
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* Fatal: config bugs (missing or unparseable `instanceUrl`) fail loud at factory-call time
|
|
29
|
+
* rather than at the first search.
|
|
30
|
+
*/
|
|
31
|
+
var E_INVALID_SEARXNG_CONFIG = createException("E_INVALID_SEARXNG_CONFIG", "Invalid SearXNG tool config: %s", "E_INVALID_SEARXNG_CONFIG", 529, true);
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/batteries/tools/searxng/index.ts
|
|
34
|
+
/**
|
|
35
|
+
* Factory for a configured SearXNG metasearch tool.
|
|
36
|
+
*
|
|
37
|
+
* @module @nhtio/adk/batteries/tools/searxng
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Unlike the other bundled tool categories — every one of which exports a ready-made,
|
|
41
|
+
* stateless `Tool` constant — the SearXNG battery exports **factories**,
|
|
42
|
+
* {@link createSearxngSearchTool} (async) and {@link createSearxngSearchToolSync}. A search tool
|
|
43
|
+
* has to talk to a *specific* SearXNG instance, usually behind custom authentication, so it needs
|
|
44
|
+
* per-deployment configuration (a base URL and headers) that cannot be baked in at module load.
|
|
45
|
+
*
|
|
46
|
+
* Because this module exports factories rather than `Tool` instances, they MUST NOT be
|
|
47
|
+
* bulk-registered via `Object.values(batteries)`. Call a factory first, then register the
|
|
48
|
+
* returned tool: `new ToolRegistry([await createSearxngSearchTool({ instanceUrl })])`.
|
|
49
|
+
*
|
|
50
|
+
* @see https://docs.searxng.org/dev/search_api.html
|
|
51
|
+
*/
|
|
52
|
+
var DEFAULT_NAME = "searxng_search";
|
|
53
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
54
|
+
var DEFAULT_DESCRIPTION = "Search the web via a SearXNG metasearch instance. Returns aggregated results (title, url, snippet, source engine) plus any answers, infoboxes, and suggestions.";
|
|
55
|
+
/** Normalise a loose SearXNG result item into a {@link SearxngResult}. */
|
|
56
|
+
var normaliseResult = (raw) => {
|
|
57
|
+
const r = raw ?? {};
|
|
58
|
+
const out = {};
|
|
59
|
+
if (typeof r.title === "string") out.title = r.title;
|
|
60
|
+
if (typeof r.url === "string") out.url = r.url;
|
|
61
|
+
if (typeof r.content === "string") out.content = r.content;
|
|
62
|
+
if (typeof r.engine === "string") out.engine = r.engine;
|
|
63
|
+
if (typeof r.score === "number") out.score = r.score;
|
|
64
|
+
if (typeof r.publishedDate === "string") out.publishedDate = r.publishedDate;
|
|
65
|
+
return out;
|
|
66
|
+
};
|
|
67
|
+
var fail = (reason) => {
|
|
68
|
+
throw new E_INVALID_SEARXNG_CONFIG([reason]);
|
|
69
|
+
};
|
|
70
|
+
/** Validate `instanceUrl` and return the trailing-slash-normalised base. */
|
|
71
|
+
var validateInstanceUrl = (config) => {
|
|
72
|
+
if (typeof config?.instanceUrl !== "string" || config.instanceUrl.trim() === "") fail("instanceUrl is required");
|
|
73
|
+
try {
|
|
74
|
+
new URL(config.instanceUrl);
|
|
75
|
+
} catch {
|
|
76
|
+
fail(`instanceUrl is not a valid URL: ${config.instanceUrl}`);
|
|
77
|
+
}
|
|
78
|
+
return config.instanceUrl.replace(/\/+$/, "");
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Assemble the `Tool` from validated config + an already-resolved sync artifact constructor.
|
|
82
|
+
* Shared by both the async and sync factories — they differ only in how `artifact` is resolved.
|
|
83
|
+
*/
|
|
84
|
+
var assembleTool = (config, instanceUrl, artifactConstructor) => {
|
|
85
|
+
const timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
86
|
+
const resultFormat = config.resultFormat ?? "either";
|
|
87
|
+
const toolName = config.name ?? DEFAULT_NAME;
|
|
88
|
+
const inputMw = new Middleware();
|
|
89
|
+
for (const fn of config.inputPipeline ?? []) inputMw.add(fn);
|
|
90
|
+
const outputMw = new Middleware();
|
|
91
|
+
for (const fn of config.outputPipeline ?? []) outputMw.add(fn);
|
|
92
|
+
const hasInput = (config.inputPipeline ?? []).length > 0;
|
|
93
|
+
const hasOutput = (config.outputPipeline ?? []).length > 0;
|
|
94
|
+
const schemaShape = {
|
|
95
|
+
query: validator.string().required().description("The search query."),
|
|
96
|
+
categories: validator.string().optional().description("Comma-separated SearXNG categories (e.g. \"general,news\")."),
|
|
97
|
+
engines: validator.string().optional().description("Comma-separated SearXNG engines (e.g. \"google,duckduckgo\")."),
|
|
98
|
+
language: validator.string().optional().description("Language code (e.g. \"en\", \"de\")."),
|
|
99
|
+
pageno: validator.number().min(1).default(1).description("Result page number (1-based)."),
|
|
100
|
+
time_range: validator.string().valid("day", "month", "year").optional().description("Restrict results to a time range."),
|
|
101
|
+
safesearch: validator.number().valid(0, 1, 2).optional().description("Safe-search level: 0 (off), 1 (moderate), 2 (strict).")
|
|
102
|
+
};
|
|
103
|
+
if (resultFormat === "either") schemaShape.format = validator.string().valid("normalized", "raw").default("normalized").description("Output shape: \"normalized\" (trimmed) or \"raw\" (full SearXNG JSON).");
|
|
104
|
+
const inputSchema = validator.object(schemaShape);
|
|
105
|
+
return new Tool({
|
|
106
|
+
name: toolName,
|
|
107
|
+
description: config.description ?? DEFAULT_DESCRIPTION,
|
|
108
|
+
inputSchema,
|
|
109
|
+
artifactConstructor,
|
|
110
|
+
handler: async (args) => {
|
|
111
|
+
const a = args;
|
|
112
|
+
try {
|
|
113
|
+
const format = resultFormat === "either" ? a.format ?? "normalized" : resultFormat;
|
|
114
|
+
const headers = {
|
|
115
|
+
"Accept": "application/json",
|
|
116
|
+
"User-Agent": "adk-searxng-tool",
|
|
117
|
+
...await resolveHeaders(config.headers)
|
|
118
|
+
};
|
|
119
|
+
const params = {};
|
|
120
|
+
if (a.categories) params.categories = a.categories;
|
|
121
|
+
if (a.engines) params.engines = a.engines;
|
|
122
|
+
if (a.language) params.language = a.language;
|
|
123
|
+
if (a.pageno && a.pageno !== 1) params.pageno = String(a.pageno);
|
|
124
|
+
if (a.time_range) params.time_range = a.time_range;
|
|
125
|
+
if (typeof a.safesearch === "number") params.safesearch = String(a.safesearch);
|
|
126
|
+
const stash = /* @__PURE__ */ new Map();
|
|
127
|
+
const requestCtx = {
|
|
128
|
+
toolName,
|
|
129
|
+
query: a.query,
|
|
130
|
+
params,
|
|
131
|
+
headers,
|
|
132
|
+
instanceUrl,
|
|
133
|
+
stash,
|
|
134
|
+
shortCircuit: makeShortCircuit()
|
|
135
|
+
};
|
|
136
|
+
if (hasInput) {
|
|
137
|
+
const short = await runInputPipeline(inputMw, requestCtx, "SearXNG");
|
|
138
|
+
if (short !== void 0) return short;
|
|
139
|
+
}
|
|
140
|
+
const url = new URL("/search", instanceUrl + "/");
|
|
141
|
+
url.searchParams.set("q", requestCtx.query);
|
|
142
|
+
for (const [k, v] of Object.entries(requestCtx.params)) url.searchParams.set(k, v);
|
|
143
|
+
url.searchParams.set("format", "json");
|
|
144
|
+
const controller = new AbortController();
|
|
145
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
146
|
+
let response;
|
|
147
|
+
try {
|
|
148
|
+
response = await fetch(url, {
|
|
149
|
+
method: "GET",
|
|
150
|
+
headers: requestCtx.headers,
|
|
151
|
+
signal: controller.signal
|
|
152
|
+
});
|
|
153
|
+
} finally {
|
|
154
|
+
clearTimeout(timer);
|
|
155
|
+
}
|
|
156
|
+
if (!response.ok) {
|
|
157
|
+
if (response.status === 403) return "Error: SearXNG returned 403 Forbidden. The instance likely has the JSON output format disabled — enable it under \"search.formats: [json]\" in its settings.yml.";
|
|
158
|
+
return `Error: SearXNG returned HTTP ${response.status} ${response.statusText}.`;
|
|
159
|
+
}
|
|
160
|
+
const body = await response.json();
|
|
161
|
+
const responseCtx = {
|
|
162
|
+
toolName,
|
|
163
|
+
request: requestCtx,
|
|
164
|
+
raw: body,
|
|
165
|
+
results: Array.isArray(body.results) ? body.results.map(normaliseResult) : [],
|
|
166
|
+
format,
|
|
167
|
+
stash
|
|
168
|
+
};
|
|
169
|
+
if (hasOutput) await runOutputPipeline(outputMw, responseCtx, "SearXNG");
|
|
170
|
+
if (typeof responseCtx.output === "string") return responseCtx.output;
|
|
171
|
+
if (responseCtx.format === "raw") return JSON.stringify(responseCtx.raw, null, 2);
|
|
172
|
+
return JSON.stringify(buildNormalisedPayload(responseCtx), null, 2);
|
|
173
|
+
} catch (err) {
|
|
174
|
+
if (isShortCircuit(err)) return err.result;
|
|
175
|
+
return `Error: ${isError(err) ? err.message : String(err)}`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Create a configured SearXNG search {@link Tool} (async — accepts a dynamic-import `artifact`).
|
|
182
|
+
*
|
|
183
|
+
* @remarks
|
|
184
|
+
* Async because `artifact` may be an async / dynamic-import resolver, which must be resolved to the
|
|
185
|
+
* sync `() => Ctor` that `Tool.artifactConstructor` requires before the tool is built (the
|
|
186
|
+
* wrap-site invokes it synchronously). For the common case where you reference the artifact class
|
|
187
|
+
* directly, use {@link createSearxngSearchToolSync} and skip the `await`.
|
|
188
|
+
*
|
|
189
|
+
* The handler always requests `format=json`. Note that SearXNG ships with JSON output
|
|
190
|
+
* **disabled** by default (it is abused by bots); an instance that has not enabled
|
|
191
|
+
* `search.formats: [json]` in its `settings.yml` answers with HTTP 403, which the tool returns
|
|
192
|
+
* as a graceful `Error:` string naming the setting.
|
|
193
|
+
*
|
|
194
|
+
* @warning
|
|
195
|
+
* Do not trust the `number_of_results` field for a result count — SearXNG frequently reports `0`
|
|
196
|
+
* in JSON output even when `results` is non-empty. This is a long-standing upstream quirk, not a
|
|
197
|
+
* tool defect (see {@link https://github.com/searxng/searxng/issues/2987 | searxng#2987} and
|
|
198
|
+
* {@link https://github.com/searxng/searxng/issues/2457 | searxng#2457}). The tool passes the
|
|
199
|
+
* field through verbatim; use `results.length` as the authoritative count.
|
|
200
|
+
*
|
|
201
|
+
* @param config - The instance URL, optional custom headers, output-format policy, `artifact`
|
|
202
|
+
* resolver, and input/output middleware pipelines. See {@link SearxngToolConfig}.
|
|
203
|
+
* @returns A promise of a `Tool` ready to register in a `ToolRegistry`.
|
|
204
|
+
* @throws {@link E_INVALID_SEARXNG_CONFIG} when `instanceUrl` or `artifact` is invalid.
|
|
205
|
+
*/
|
|
206
|
+
var createSearxngSearchTool = async (config) => {
|
|
207
|
+
return assembleTool(config, validateInstanceUrl(config), await resolveArtifact(config.artifact ?? (() => SpooledJsonArtifact), fail));
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Synchronous {@link createSearxngSearchTool} — the ergonomic common path.
|
|
211
|
+
*
|
|
212
|
+
* @remarks
|
|
213
|
+
* `artifact` is narrowed to the sync subset (a constructor or a sync resolver). Passing an async
|
|
214
|
+
* resolver is a compile-time type error and a runtime {@link E_INVALID_SEARXNG_CONFIG}; for
|
|
215
|
+
* dynamic-import resolvers use the async {@link createSearxngSearchTool}. See its docs for the
|
|
216
|
+
* `number_of_results` caveat and 403/JSON-disabled behaviour.
|
|
217
|
+
*
|
|
218
|
+
* @param config - Same as {@link SearxngToolConfig}, with `artifact` restricted to the sync subset.
|
|
219
|
+
* @returns A `Tool` ready to register in a `ToolRegistry`.
|
|
220
|
+
* @throws {@link E_INVALID_SEARXNG_CONFIG} when `instanceUrl` or `artifact` is invalid (incl. an async resolver).
|
|
221
|
+
*/
|
|
222
|
+
var createSearxngSearchToolSync = (config) => {
|
|
223
|
+
return assembleTool(config, validateInstanceUrl(config), resolveArtifactSync(config.artifact ?? (() => SpooledJsonArtifact), fail));
|
|
224
|
+
};
|
|
225
|
+
/** Assemble the trimmed normalised payload, dropping empty aggregate arrays. */
|
|
226
|
+
var buildNormalisedPayload = (ctx) => {
|
|
227
|
+
const raw = ctx.raw ?? {};
|
|
228
|
+
const payload = {
|
|
229
|
+
query: typeof raw.query === "string" ? raw.query : ctx.request.query,
|
|
230
|
+
results: ctx.results
|
|
231
|
+
};
|
|
232
|
+
if (typeof raw.number_of_results === "number") payload.number_of_results = raw.number_of_results;
|
|
233
|
+
for (const key of [
|
|
234
|
+
"answers",
|
|
235
|
+
"infoboxes",
|
|
236
|
+
"suggestions",
|
|
237
|
+
"corrections"
|
|
238
|
+
]) {
|
|
239
|
+
const value = raw[key];
|
|
240
|
+
if (Array.isArray(value) && value.length > 0) payload[key] = value;
|
|
241
|
+
}
|
|
242
|
+
return payload;
|
|
243
|
+
};
|
|
244
|
+
//#endregion
|
|
245
|
+
export { createSearxngSearchToolSync as n, E_INVALID_SEARXNG_CONFIG as r, createSearxngSearchTool as t };
|
|
246
|
+
|
|
247
|
+
//# sourceMappingURL=searxng-BJFulNcK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searxng-BJFulNcK.mjs","names":[],"sources":["../src/batteries/tools/searxng/exceptions.ts","../src/batteries/tools/searxng/index.ts"],"sourcesContent":["/**\n * Battery-scoped exception constructors for the SearXNG search tool.\n *\n * @remarks\n * Battery-scoped exception classes owned by the SearXNG tool battery (not the ADK core). Minted\n * via `createException` from `@nhtio/adk/factories` and re-exported from the battery's barrel\n * (`@nhtio/adk/batteries/tools/searxng`). This file intentionally carries **no** `@module` tag:\n * it is an internal sibling relative-imported by `index.ts`, so it does not mint its own\n * `…/searxng/exceptions` entrypoint (whose `exceptions` leaf basename would collide with sibling\n * batteries under the `vite-plugin-dts` rolled-up `.d.ts` rule).\n */\n\nimport { createException } from '@nhtio/adk/factories'\n\n/**\n * Thrown when {@link createSearxngSearchTool} receives invalid configuration.\n *\n * @remarks\n * Fatal: config bugs (missing or unparseable `instanceUrl`) fail loud at factory-call time\n * rather than at the first search.\n */\nexport const E_INVALID_SEARXNG_CONFIG = createException<[string]>(\n 'E_INVALID_SEARXNG_CONFIG',\n 'Invalid SearXNG tool config: %s',\n 'E_INVALID_SEARXNG_CONFIG',\n 529,\n true\n)\n","/**\n * Factory for a configured SearXNG metasearch tool.\n *\n * @module @nhtio/adk/batteries/tools/searxng\n *\n * @remarks\n * Unlike the other bundled tool categories — every one of which exports a ready-made,\n * stateless `Tool` constant — the SearXNG battery exports **factories**,\n * {@link createSearxngSearchTool} (async) and {@link createSearxngSearchToolSync}. A search tool\n * has to talk to a *specific* SearXNG instance, usually behind custom authentication, so it needs\n * per-deployment configuration (a base URL and headers) that cannot be baked in at module load.\n *\n * Because this module exports factories rather than `Tool` instances, they MUST NOT be\n * bulk-registered via `Object.values(batteries)`. Call a factory first, then register the\n * returned tool: `new ToolRegistry([await createSearxngSearchTool({ instanceUrl })])`.\n *\n * @see https://docs.searxng.org/dev/search_api.html\n */\n\nimport { Tool } from '@nhtio/adk/forge'\nimport { isError } from '@nhtio/adk/guards'\nimport { validator } from '@nhtio/validation'\nimport { Middleware } from '@nhtio/middleware'\nimport { E_INVALID_SEARXNG_CONFIG } from './exceptions'\nimport { SpooledJsonArtifact } from '@nhtio/adk/spooled_artifact'\nimport {\n resolveHeaders,\n resolveArtifact,\n resolveArtifactSync,\n makeShortCircuit,\n isShortCircuit,\n runInputPipeline,\n runOutputPipeline,\n type ArtifactResolver,\n type SyncArtifactResolver,\n type SpooledArtifactCtor,\n type MiddlewareFn,\n} from '../_shared'\nimport type { Schema } from '@nhtio/validation'\nimport type { NextFn } from '@nhtio/middleware'\n\nexport { E_INVALID_SEARXNG_CONFIG } from './exceptions'\n\n/** A static set of request headers (used for custom authentication). */\nexport type SearxngHeaders = Record<string, string>\n\n/**\n * A resolver returning request headers, sync or async. Use this form when the auth token is\n * refreshable — the resolver runs on every search, so a fresh token can be minted per call.\n */\nexport type SearxngHeadersResolver = () => SearxngHeaders | Promise<SearxngHeaders>\n\n/** The output shape the tool serialises. `either` lets the model pick per call. */\nexport type SearxngResultFormat = 'normalized' | 'raw' | 'either'\n\n/**\n * A single normalised SearXNG result. SearXNG result items are deliberately untyped upstream,\n * so every field except a best-effort `title`/`url` is optional.\n */\nexport interface SearxngResult {\n /** Result title, when the source engine provided one. */\n title?: string\n /** Result URL, when the source engine provided one. */\n url?: string\n /** Snippet / summary text for the result. */\n content?: string\n /** The SearXNG engine that produced this result (e.g. `google`, `duckduckgo`). */\n engine?: string\n /** Relevance score as reported by SearXNG (higher is more relevant). */\n score?: number\n /** Publication date, when the source engine exposed one (ISO-ish string, engine-dependent). */\n publishedDate?: string\n}\n\n/**\n * Mutable context handed to each input-pipeline stage **before** the HTTP request is sent.\n *\n * @remarks\n * Stages mutate this in place (onion `(ctx, next)` style) to adjust the outgoing request —\n * inject or rotate auth headers, force a language, rewrite the query — or call\n * {@link SearxngRequestContext.shortCircuit} to skip the fetch entirely (e.g. a cache hit).\n */\nexport interface SearxngRequestContext {\n /** The tool's name (read-only). */\n readonly toolName: string\n /** The search query. Mutable. */\n query: string\n /** Extra SearXNG query parameters (`categories`, `engines`, `language`, …). Mutable. */\n params: Record<string, string>\n /** Resolved request headers. Mutable — inject, redact, or rotate auth here. */\n headers: SearxngHeaders\n /** The target instance base URL (read-only). */\n readonly instanceUrl: string\n /** Cross-stage scratch space; also carried onto the response context. */\n readonly stash: Map<string, unknown>\n /** Skip the fetch and return `result` verbatim as the tool's output. */\n shortCircuit(result: string): void\n}\n\n/**\n * Mutable context handed to each output-pipeline stage **after** the response JSON is parsed.\n *\n * @remarks\n * Stages reshape, redact, enrich, or re-rank {@link SearxngResponseContext.results}, mutate the\n * raw body, or set {@link SearxngResponseContext.output} to override the serialised string\n * verbatim (e.g. to render markdown that matches a markdown `artifact` resolver).\n */\nexport interface SearxngResponseContext {\n /** The tool's name (read-only). */\n readonly toolName: string\n /** The request context as it was sent (post-input-pipeline). */\n readonly request: SearxngRequestContext\n /** The parsed SearXNG JSON body. Mutable (used when `format` is `raw`). */\n raw: unknown\n /** The normalised result list. Mutable — filter, redact, or re-rank. */\n results: SearxngResult[]\n /** The effective payload shape for this call. */\n format: 'normalized' | 'raw'\n /** When set, used verbatim as the tool's output (overrides serialisation). */\n output?: string\n /** Cross-stage scratch space; carried over from the request context. */\n readonly stash: Map<string, unknown>\n}\n\n/** An input-pipeline stage. Onion middleware over {@link SearxngRequestContext}. */\nexport type SearxngInputMiddlewareFn = (\n ctx: SearxngRequestContext,\n next: NextFn\n) => void | Promise<void>\n\n/** An output-pipeline stage. Onion middleware over {@link SearxngResponseContext}. */\nexport type SearxngOutputMiddlewareFn = (\n ctx: SearxngResponseContext,\n next: NextFn\n) => void | Promise<void>\n\n/**\n * Configuration for {@link createSearxngSearchTool} (async) and\n * {@link createSearxngSearchToolSync} (sync — `artifact` narrowed to the sync subset).\n *\n * @typeParam A - The {@link ArtifactResolver} variant accepted: the full resolver (async factory)\n * or the sync subset ({@link createSearxngSearchToolSync}).\n */\nexport interface SearxngToolConfig<A = ArtifactResolver> {\n /** Base URL of the SearXNG instance, e.g. `https://searx.example.org`. Required. */\n instanceUrl: string\n /** Custom request headers — a static object or a (sync/async) resolver for refreshable auth. */\n headers?: SearxngHeaders | SearxngHeadersResolver\n /** Request timeout in milliseconds. Default `10_000`. */\n timeout?: number\n /**\n * Output shape. `normalized`/`raw` pin the shape (the model cannot change it); `either`\n * (default) exposes a `format` argument so the model chooses per call.\n */\n resultFormat?: SearxngResultFormat\n /** Tool name. Default `searxng_search`. */\n name?: string\n /** Tool description override. */\n description?: string\n /**\n * Spool-artifact resolver for the tool's output. Default `() => SpooledJsonArtifact`. Accepts a\n * constructor, a sync resolver, or — via {@link createSearxngSearchTool} — an async /\n * dynamic-import resolver. Pass `() => SpooledMarkdownArtifact` (paired with an output stage that\n * renders markdown into `ctx.output`) or `() => SpooledArtifact` for plain text.\n */\n artifact?: A\n /** Stages run before the HTTP request. See {@link SearxngRequestContext}. */\n inputPipeline?: SearxngInputMiddlewareFn[]\n /** Stages run after the response is parsed. See {@link SearxngResponseContext}. */\n outputPipeline?: SearxngOutputMiddlewareFn[]\n}\n\nconst DEFAULT_NAME = 'searxng_search'\nconst DEFAULT_TIMEOUT = 10_000\nconst DEFAULT_DESCRIPTION =\n 'Search the web via a SearXNG metasearch instance. Returns aggregated results (title, url, ' +\n 'snippet, source engine) plus any answers, infoboxes, and suggestions.'\n\n/** Normalise a loose SearXNG result item into a {@link SearxngResult}. */\nconst normaliseResult = (raw: unknown): SearxngResult => {\n const r = (raw ?? {}) as Record<string, unknown>\n const out: SearxngResult = {}\n if (typeof r.title === 'string') out.title = r.title\n if (typeof r.url === 'string') out.url = r.url\n if (typeof r.content === 'string') out.content = r.content\n if (typeof r.engine === 'string') out.engine = r.engine\n if (typeof r.score === 'number') out.score = r.score\n if (typeof r.publishedDate === 'string') out.publishedDate = r.publishedDate\n return out\n}\n\nconst fail = (reason: string): never => {\n throw new E_INVALID_SEARXNG_CONFIG([reason])\n}\n\n/** Validate `instanceUrl` and return the trailing-slash-normalised base. */\nconst validateInstanceUrl = (config: { instanceUrl?: string }): string => {\n if (typeof config?.instanceUrl !== 'string' || config.instanceUrl.trim() === '') {\n fail('instanceUrl is required')\n }\n try {\n new URL(config.instanceUrl as string)\n } catch {\n fail(`instanceUrl is not a valid URL: ${config.instanceUrl}`)\n }\n return (config.instanceUrl as string).replace(/\\/+$/, '')\n}\n\n/**\n * Assemble the `Tool` from validated config + an already-resolved sync artifact constructor.\n * Shared by both the async and sync factories — they differ only in how `artifact` is resolved.\n */\nconst assembleTool = (\n config: SearxngToolConfig<unknown>,\n instanceUrl: string,\n artifactConstructor: () => SpooledArtifactCtor\n): Tool => {\n const timeout = config.timeout ?? DEFAULT_TIMEOUT\n const resultFormat: SearxngResultFormat = config.resultFormat ?? 'either'\n const toolName = config.name ?? DEFAULT_NAME\n\n // Stages are fixed at factory time; build the Middleware shells once. A fresh `.runner()` is\n // minted per invocation inside the handler (runners are single-use).\n const inputMw = new Middleware<MiddlewareFn<SearxngRequestContext>>()\n for (const fn of config.inputPipeline ?? []) inputMw.add(fn)\n const outputMw = new Middleware<MiddlewareFn<SearxngResponseContext>>()\n for (const fn of config.outputPipeline ?? []) outputMw.add(fn)\n const hasInput = (config.inputPipeline ?? []).length > 0\n const hasOutput = (config.outputPipeline ?? []).length > 0\n\n // Build the input schema, conditionally exposing `format` only when the factory is neutral.\n const schemaShape: Record<string, Schema> = {\n query: validator.string().required().description('The search query.'),\n categories: validator\n .string()\n .optional()\n .description('Comma-separated SearXNG categories (e.g. \"general,news\").'),\n engines: validator\n .string()\n .optional()\n .description('Comma-separated SearXNG engines (e.g. \"google,duckduckgo\").'),\n language: validator.string().optional().description('Language code (e.g. \"en\", \"de\").'),\n pageno: validator.number().min(1).default(1).description('Result page number (1-based).'),\n time_range: validator\n .string()\n .valid('day', 'month', 'year')\n .optional()\n .description('Restrict results to a time range.'),\n safesearch: validator\n .number()\n .valid(0, 1, 2)\n .optional()\n .description('Safe-search level: 0 (off), 1 (moderate), 2 (strict).'),\n }\n if (resultFormat === 'either') {\n schemaShape.format = validator\n .string()\n .valid('normalized', 'raw')\n .default('normalized')\n .description('Output shape: \"normalized\" (trimmed) or \"raw\" (full SearXNG JSON).')\n }\n const inputSchema = validator.object(schemaShape)\n\n return new Tool({\n name: toolName,\n description: config.description ?? DEFAULT_DESCRIPTION,\n inputSchema,\n artifactConstructor,\n handler: async (args) => {\n const a = args as {\n query: string\n categories?: string\n engines?: string\n language?: string\n pageno?: number\n time_range?: string\n safesearch?: number\n format?: 'normalized' | 'raw'\n }\n\n try {\n // 1. Effective output format: a pinned factory format wins; else the model's choice.\n const format: 'normalized' | 'raw' =\n resultFormat === 'either' ? (a.format ?? 'normalized') : resultFormat\n\n // 2. Resolve headers, merged over portable defaults (caller headers win).\n const headers: SearxngHeaders = {\n 'Accept': 'application/json',\n 'User-Agent': 'adk-searxng-tool',\n ...(await resolveHeaders(config.headers)),\n }\n\n // 3. Assemble the SearXNG query params from validated args.\n const params: Record<string, string> = {}\n if (a.categories) params.categories = a.categories\n if (a.engines) params.engines = a.engines\n if (a.language) params.language = a.language\n if (a.pageno && a.pageno !== 1) params.pageno = String(a.pageno)\n if (a.time_range) params.time_range = a.time_range\n if (typeof a.safesearch === 'number') params.safesearch = String(a.safesearch)\n\n const stash = new Map<string, unknown>()\n\n // 4. Run the input pipeline (fresh runner) over a mutable request context.\n const requestCtx: SearxngRequestContext = {\n toolName,\n query: a.query,\n params,\n headers,\n instanceUrl,\n stash,\n shortCircuit: makeShortCircuit(),\n }\n\n if (hasInput) {\n const short = await runInputPipeline(inputMw, requestCtx, 'SearXNG')\n if (short !== undefined) return short\n }\n\n // 5. Build the request URL from the (possibly mutated) query + params.\n const url = new URL('/search', instanceUrl + '/')\n url.searchParams.set('q', requestCtx.query)\n for (const [k, v] of Object.entries(requestCtx.params)) url.searchParams.set(k, v)\n url.searchParams.set('format', 'json')\n\n // 6. Fetch with an AbortController timeout.\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeout)\n let response: Response\n try {\n response = await fetch(url, {\n method: 'GET',\n headers: requestCtx.headers,\n signal: controller.signal,\n })\n } finally {\n clearTimeout(timer)\n }\n\n if (!response.ok) {\n if (response.status === 403) {\n return (\n `Error: SearXNG returned 403 Forbidden. The instance likely has the JSON output ` +\n `format disabled — enable it under \"search.formats: [json]\" in its settings.yml.`\n )\n }\n return `Error: SearXNG returned HTTP ${response.status} ${response.statusText}.`\n }\n\n const body = (await response.json()) as Record<string, unknown>\n\n // 7. Run the output pipeline (fresh runner) over a mutable response context.\n const responseCtx: SearxngResponseContext = {\n toolName,\n request: requestCtx,\n raw: body,\n results: Array.isArray(body.results) ? body.results.map(normaliseResult) : [],\n format,\n stash,\n }\n\n if (hasOutput) await runOutputPipeline(outputMw, responseCtx, 'SearXNG')\n\n // 8. Serialise and return.\n if (typeof responseCtx.output === 'string') return responseCtx.output\n if (responseCtx.format === 'raw') return JSON.stringify(responseCtx.raw, null, 2)\n return JSON.stringify(buildNormalisedPayload(responseCtx), null, 2)\n } catch (err) {\n if (isShortCircuit(err)) return err.result\n return `Error: ${isError(err) ? err.message : String(err)}`\n }\n },\n })\n}\n\n/**\n * Create a configured SearXNG search {@link Tool} (async — accepts a dynamic-import `artifact`).\n *\n * @remarks\n * Async because `artifact` may be an async / dynamic-import resolver, which must be resolved to the\n * sync `() => Ctor` that `Tool.artifactConstructor` requires before the tool is built (the\n * wrap-site invokes it synchronously). For the common case where you reference the artifact class\n * directly, use {@link createSearxngSearchToolSync} and skip the `await`.\n *\n * The handler always requests `format=json`. Note that SearXNG ships with JSON output\n * **disabled** by default (it is abused by bots); an instance that has not enabled\n * `search.formats: [json]` in its `settings.yml` answers with HTTP 403, which the tool returns\n * as a graceful `Error:` string naming the setting.\n *\n * @warning\n * Do not trust the `number_of_results` field for a result count — SearXNG frequently reports `0`\n * in JSON output even when `results` is non-empty. This is a long-standing upstream quirk, not a\n * tool defect (see {@link https://github.com/searxng/searxng/issues/2987 | searxng#2987} and\n * {@link https://github.com/searxng/searxng/issues/2457 | searxng#2457}). The tool passes the\n * field through verbatim; use `results.length` as the authoritative count.\n *\n * @param config - The instance URL, optional custom headers, output-format policy, `artifact`\n * resolver, and input/output middleware pipelines. See {@link SearxngToolConfig}.\n * @returns A promise of a `Tool` ready to register in a `ToolRegistry`.\n * @throws {@link E_INVALID_SEARXNG_CONFIG} when `instanceUrl` or `artifact` is invalid.\n */\nexport const createSearxngSearchTool = async (\n config: SearxngToolConfig<ArtifactResolver>\n): Promise<Tool> => {\n const instanceUrl = validateInstanceUrl(config)\n const artifactConstructor = await resolveArtifact(\n config.artifact ?? (() => SpooledJsonArtifact),\n fail\n )\n return assembleTool(config, instanceUrl, artifactConstructor)\n}\n\n/**\n * Synchronous {@link createSearxngSearchTool} — the ergonomic common path.\n *\n * @remarks\n * `artifact` is narrowed to the sync subset (a constructor or a sync resolver). Passing an async\n * resolver is a compile-time type error and a runtime {@link E_INVALID_SEARXNG_CONFIG}; for\n * dynamic-import resolvers use the async {@link createSearxngSearchTool}. See its docs for the\n * `number_of_results` caveat and 403/JSON-disabled behaviour.\n *\n * @param config - Same as {@link SearxngToolConfig}, with `artifact` restricted to the sync subset.\n * @returns A `Tool` ready to register in a `ToolRegistry`.\n * @throws {@link E_INVALID_SEARXNG_CONFIG} when `instanceUrl` or `artifact` is invalid (incl. an async resolver).\n */\nexport const createSearxngSearchToolSync = (\n config: SearxngToolConfig<SyncArtifactResolver>\n): Tool => {\n const instanceUrl = validateInstanceUrl(config)\n const artifactConstructor = resolveArtifactSync(\n config.artifact ?? (() => SpooledJsonArtifact),\n fail\n )\n return assembleTool(config, instanceUrl, artifactConstructor)\n}\n\n/** Assemble the trimmed normalised payload, dropping empty aggregate arrays. */\nconst buildNormalisedPayload = (ctx: SearxngResponseContext): Record<string, unknown> => {\n const raw = (ctx.raw ?? {}) as Record<string, unknown>\n const payload: Record<string, unknown> = {\n query: typeof raw.query === 'string' ? raw.query : ctx.request.query,\n results: ctx.results,\n }\n // NOTE: SearXNG's `number_of_results` is frequently `0` in JSON output even when `results`\n // is non-empty — a long-standing upstream quirk, not a tool bug (see\n // https://github.com/searxng/searxng/issues/2987 and\n // https://github.com/searxng/searxng/issues/2457). We pass through whatever the instance\n // reports; treat `results.length` as the authoritative count, not this field.\n if (typeof raw.number_of_results === 'number') payload.number_of_results = raw.number_of_results\n for (const key of ['answers', 'infoboxes', 'suggestions', 'corrections'] as const) {\n const value = raw[key]\n if (Array.isArray(value) && value.length > 0) payload[key] = value\n }\n return payload\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
require("./chunk-Ble4zEEl.js");
|
|
2
|
+
const require_exceptions = require("./exceptions-BRXrUKiW.js");
|
|
3
|
+
const require_tool_registry = require("./tool_registry-CKJPze3j.js");
|
|
4
|
+
const require_tool = require("./tool-D5WGVIcI.js");
|
|
5
|
+
const require_spooled_markdown_artifact = require("./spooled_markdown_artifact-ClX72lek.js");
|
|
6
|
+
require("./factories.cjs");
|
|
7
|
+
require("./forge.cjs");
|
|
8
|
+
require("./guards.cjs");
|
|
9
|
+
require("./spooled_artifact.cjs");
|
|
10
|
+
const require_batteries_tools__shared = require("./batteries/tools/_shared.cjs");
|
|
11
|
+
let _nhtio_validation = require("@nhtio/validation");
|
|
12
|
+
let _nhtio_middleware = require("@nhtio/middleware");
|
|
13
|
+
//#region src/batteries/tools/searxng/exceptions.ts
|
|
14
|
+
/**
|
|
15
|
+
* Battery-scoped exception constructors for the SearXNG search tool.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* Battery-scoped exception classes owned by the SearXNG tool battery (not the ADK core). Minted
|
|
19
|
+
* via `createException` from `@nhtio/adk/factories` and re-exported from the battery's barrel
|
|
20
|
+
* (`@nhtio/adk/batteries/tools/searxng`). This file intentionally carries **no** `@module` tag:
|
|
21
|
+
* it is an internal sibling relative-imported by `index.ts`, so it does not mint its own
|
|
22
|
+
* `…/searxng/exceptions` entrypoint (whose `exceptions` leaf basename would collide with sibling
|
|
23
|
+
* batteries under the `vite-plugin-dts` rolled-up `.d.ts` rule).
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Thrown when {@link createSearxngSearchTool} receives invalid configuration.
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* Fatal: config bugs (missing or unparseable `instanceUrl`) fail loud at factory-call time
|
|
30
|
+
* rather than at the first search.
|
|
31
|
+
*/
|
|
32
|
+
var E_INVALID_SEARXNG_CONFIG = require_exceptions.createException("E_INVALID_SEARXNG_CONFIG", "Invalid SearXNG tool config: %s", "E_INVALID_SEARXNG_CONFIG", 529, true);
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/batteries/tools/searxng/index.ts
|
|
35
|
+
/**
|
|
36
|
+
* Factory for a configured SearXNG metasearch tool.
|
|
37
|
+
*
|
|
38
|
+
* @module @nhtio/adk/batteries/tools/searxng
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* Unlike the other bundled tool categories — every one of which exports a ready-made,
|
|
42
|
+
* stateless `Tool` constant — the SearXNG battery exports **factories**,
|
|
43
|
+
* {@link createSearxngSearchTool} (async) and {@link createSearxngSearchToolSync}. A search tool
|
|
44
|
+
* has to talk to a *specific* SearXNG instance, usually behind custom authentication, so it needs
|
|
45
|
+
* per-deployment configuration (a base URL and headers) that cannot be baked in at module load.
|
|
46
|
+
*
|
|
47
|
+
* Because this module exports factories rather than `Tool` instances, they MUST NOT be
|
|
48
|
+
* bulk-registered via `Object.values(batteries)`. Call a factory first, then register the
|
|
49
|
+
* returned tool: `new ToolRegistry([await createSearxngSearchTool({ instanceUrl })])`.
|
|
50
|
+
*
|
|
51
|
+
* @see https://docs.searxng.org/dev/search_api.html
|
|
52
|
+
*/
|
|
53
|
+
var DEFAULT_NAME = "searxng_search";
|
|
54
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
55
|
+
var DEFAULT_DESCRIPTION = "Search the web via a SearXNG metasearch instance. Returns aggregated results (title, url, snippet, source engine) plus any answers, infoboxes, and suggestions.";
|
|
56
|
+
/** Normalise a loose SearXNG result item into a {@link SearxngResult}. */
|
|
57
|
+
var normaliseResult = (raw) => {
|
|
58
|
+
const r = raw ?? {};
|
|
59
|
+
const out = {};
|
|
60
|
+
if (typeof r.title === "string") out.title = r.title;
|
|
61
|
+
if (typeof r.url === "string") out.url = r.url;
|
|
62
|
+
if (typeof r.content === "string") out.content = r.content;
|
|
63
|
+
if (typeof r.engine === "string") out.engine = r.engine;
|
|
64
|
+
if (typeof r.score === "number") out.score = r.score;
|
|
65
|
+
if (typeof r.publishedDate === "string") out.publishedDate = r.publishedDate;
|
|
66
|
+
return out;
|
|
67
|
+
};
|
|
68
|
+
var fail = (reason) => {
|
|
69
|
+
throw new E_INVALID_SEARXNG_CONFIG([reason]);
|
|
70
|
+
};
|
|
71
|
+
/** Validate `instanceUrl` and return the trailing-slash-normalised base. */
|
|
72
|
+
var validateInstanceUrl = (config) => {
|
|
73
|
+
if (typeof config?.instanceUrl !== "string" || config.instanceUrl.trim() === "") fail("instanceUrl is required");
|
|
74
|
+
try {
|
|
75
|
+
new URL(config.instanceUrl);
|
|
76
|
+
} catch {
|
|
77
|
+
fail(`instanceUrl is not a valid URL: ${config.instanceUrl}`);
|
|
78
|
+
}
|
|
79
|
+
return config.instanceUrl.replace(/\/+$/, "");
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Assemble the `Tool` from validated config + an already-resolved sync artifact constructor.
|
|
83
|
+
* Shared by both the async and sync factories — they differ only in how `artifact` is resolved.
|
|
84
|
+
*/
|
|
85
|
+
var assembleTool = (config, instanceUrl, artifactConstructor) => {
|
|
86
|
+
const timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
87
|
+
const resultFormat = config.resultFormat ?? "either";
|
|
88
|
+
const toolName = config.name ?? DEFAULT_NAME;
|
|
89
|
+
const inputMw = new _nhtio_middleware.Middleware();
|
|
90
|
+
for (const fn of config.inputPipeline ?? []) inputMw.add(fn);
|
|
91
|
+
const outputMw = new _nhtio_middleware.Middleware();
|
|
92
|
+
for (const fn of config.outputPipeline ?? []) outputMw.add(fn);
|
|
93
|
+
const hasInput = (config.inputPipeline ?? []).length > 0;
|
|
94
|
+
const hasOutput = (config.outputPipeline ?? []).length > 0;
|
|
95
|
+
const schemaShape = {
|
|
96
|
+
query: _nhtio_validation.validator.string().required().description("The search query."),
|
|
97
|
+
categories: _nhtio_validation.validator.string().optional().description("Comma-separated SearXNG categories (e.g. \"general,news\")."),
|
|
98
|
+
engines: _nhtio_validation.validator.string().optional().description("Comma-separated SearXNG engines (e.g. \"google,duckduckgo\")."),
|
|
99
|
+
language: _nhtio_validation.validator.string().optional().description("Language code (e.g. \"en\", \"de\")."),
|
|
100
|
+
pageno: _nhtio_validation.validator.number().min(1).default(1).description("Result page number (1-based)."),
|
|
101
|
+
time_range: _nhtio_validation.validator.string().valid("day", "month", "year").optional().description("Restrict results to a time range."),
|
|
102
|
+
safesearch: _nhtio_validation.validator.number().valid(0, 1, 2).optional().description("Safe-search level: 0 (off), 1 (moderate), 2 (strict).")
|
|
103
|
+
};
|
|
104
|
+
if (resultFormat === "either") schemaShape.format = _nhtio_validation.validator.string().valid("normalized", "raw").default("normalized").description("Output shape: \"normalized\" (trimmed) or \"raw\" (full SearXNG JSON).");
|
|
105
|
+
const inputSchema = _nhtio_validation.validator.object(schemaShape);
|
|
106
|
+
return new require_tool.Tool({
|
|
107
|
+
name: toolName,
|
|
108
|
+
description: config.description ?? DEFAULT_DESCRIPTION,
|
|
109
|
+
inputSchema,
|
|
110
|
+
artifactConstructor,
|
|
111
|
+
handler: async (args) => {
|
|
112
|
+
const a = args;
|
|
113
|
+
try {
|
|
114
|
+
const format = resultFormat === "either" ? a.format ?? "normalized" : resultFormat;
|
|
115
|
+
const headers = {
|
|
116
|
+
"Accept": "application/json",
|
|
117
|
+
"User-Agent": "adk-searxng-tool",
|
|
118
|
+
...await require_batteries_tools__shared.resolveHeaders(config.headers)
|
|
119
|
+
};
|
|
120
|
+
const params = {};
|
|
121
|
+
if (a.categories) params.categories = a.categories;
|
|
122
|
+
if (a.engines) params.engines = a.engines;
|
|
123
|
+
if (a.language) params.language = a.language;
|
|
124
|
+
if (a.pageno && a.pageno !== 1) params.pageno = String(a.pageno);
|
|
125
|
+
if (a.time_range) params.time_range = a.time_range;
|
|
126
|
+
if (typeof a.safesearch === "number") params.safesearch = String(a.safesearch);
|
|
127
|
+
const stash = /* @__PURE__ */ new Map();
|
|
128
|
+
const requestCtx = {
|
|
129
|
+
toolName,
|
|
130
|
+
query: a.query,
|
|
131
|
+
params,
|
|
132
|
+
headers,
|
|
133
|
+
instanceUrl,
|
|
134
|
+
stash,
|
|
135
|
+
shortCircuit: require_batteries_tools__shared.makeShortCircuit()
|
|
136
|
+
};
|
|
137
|
+
if (hasInput) {
|
|
138
|
+
const short = await require_batteries_tools__shared.runInputPipeline(inputMw, requestCtx, "SearXNG");
|
|
139
|
+
if (short !== void 0) return short;
|
|
140
|
+
}
|
|
141
|
+
const url = new URL("/search", instanceUrl + "/");
|
|
142
|
+
url.searchParams.set("q", requestCtx.query);
|
|
143
|
+
for (const [k, v] of Object.entries(requestCtx.params)) url.searchParams.set(k, v);
|
|
144
|
+
url.searchParams.set("format", "json");
|
|
145
|
+
const controller = new AbortController();
|
|
146
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
147
|
+
let response;
|
|
148
|
+
try {
|
|
149
|
+
response = await fetch(url, {
|
|
150
|
+
method: "GET",
|
|
151
|
+
headers: requestCtx.headers,
|
|
152
|
+
signal: controller.signal
|
|
153
|
+
});
|
|
154
|
+
} finally {
|
|
155
|
+
clearTimeout(timer);
|
|
156
|
+
}
|
|
157
|
+
if (!response.ok) {
|
|
158
|
+
if (response.status === 403) return "Error: SearXNG returned 403 Forbidden. The instance likely has the JSON output format disabled — enable it under \"search.formats: [json]\" in its settings.yml.";
|
|
159
|
+
return `Error: SearXNG returned HTTP ${response.status} ${response.statusText}.`;
|
|
160
|
+
}
|
|
161
|
+
const body = await response.json();
|
|
162
|
+
const responseCtx = {
|
|
163
|
+
toolName,
|
|
164
|
+
request: requestCtx,
|
|
165
|
+
raw: body,
|
|
166
|
+
results: Array.isArray(body.results) ? body.results.map(normaliseResult) : [],
|
|
167
|
+
format,
|
|
168
|
+
stash
|
|
169
|
+
};
|
|
170
|
+
if (hasOutput) await require_batteries_tools__shared.runOutputPipeline(outputMw, responseCtx, "SearXNG");
|
|
171
|
+
if (typeof responseCtx.output === "string") return responseCtx.output;
|
|
172
|
+
if (responseCtx.format === "raw") return JSON.stringify(responseCtx.raw, null, 2);
|
|
173
|
+
return JSON.stringify(buildNormalisedPayload(responseCtx), null, 2);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
if (require_batteries_tools__shared.isShortCircuit(err)) return err.result;
|
|
176
|
+
return `Error: ${require_tool_registry.isError(err) ? err.message : String(err)}`;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Create a configured SearXNG search {@link Tool} (async — accepts a dynamic-import `artifact`).
|
|
183
|
+
*
|
|
184
|
+
* @remarks
|
|
185
|
+
* Async because `artifact` may be an async / dynamic-import resolver, which must be resolved to the
|
|
186
|
+
* sync `() => Ctor` that `Tool.artifactConstructor` requires before the tool is built (the
|
|
187
|
+
* wrap-site invokes it synchronously). For the common case where you reference the artifact class
|
|
188
|
+
* directly, use {@link createSearxngSearchToolSync} and skip the `await`.
|
|
189
|
+
*
|
|
190
|
+
* The handler always requests `format=json`. Note that SearXNG ships with JSON output
|
|
191
|
+
* **disabled** by default (it is abused by bots); an instance that has not enabled
|
|
192
|
+
* `search.formats: [json]` in its `settings.yml` answers with HTTP 403, which the tool returns
|
|
193
|
+
* as a graceful `Error:` string naming the setting.
|
|
194
|
+
*
|
|
195
|
+
* @warning
|
|
196
|
+
* Do not trust the `number_of_results` field for a result count — SearXNG frequently reports `0`
|
|
197
|
+
* in JSON output even when `results` is non-empty. This is a long-standing upstream quirk, not a
|
|
198
|
+
* tool defect (see {@link https://github.com/searxng/searxng/issues/2987 | searxng#2987} and
|
|
199
|
+
* {@link https://github.com/searxng/searxng/issues/2457 | searxng#2457}). The tool passes the
|
|
200
|
+
* field through verbatim; use `results.length` as the authoritative count.
|
|
201
|
+
*
|
|
202
|
+
* @param config - The instance URL, optional custom headers, output-format policy, `artifact`
|
|
203
|
+
* resolver, and input/output middleware pipelines. See {@link SearxngToolConfig}.
|
|
204
|
+
* @returns A promise of a `Tool` ready to register in a `ToolRegistry`.
|
|
205
|
+
* @throws {@link E_INVALID_SEARXNG_CONFIG} when `instanceUrl` or `artifact` is invalid.
|
|
206
|
+
*/
|
|
207
|
+
var createSearxngSearchTool = async (config) => {
|
|
208
|
+
return assembleTool(config, validateInstanceUrl(config), await require_batteries_tools__shared.resolveArtifact(config.artifact ?? (() => require_spooled_markdown_artifact.SpooledJsonArtifact), fail));
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Synchronous {@link createSearxngSearchTool} — the ergonomic common path.
|
|
212
|
+
*
|
|
213
|
+
* @remarks
|
|
214
|
+
* `artifact` is narrowed to the sync subset (a constructor or a sync resolver). Passing an async
|
|
215
|
+
* resolver is a compile-time type error and a runtime {@link E_INVALID_SEARXNG_CONFIG}; for
|
|
216
|
+
* dynamic-import resolvers use the async {@link createSearxngSearchTool}. See its docs for the
|
|
217
|
+
* `number_of_results` caveat and 403/JSON-disabled behaviour.
|
|
218
|
+
*
|
|
219
|
+
* @param config - Same as {@link SearxngToolConfig}, with `artifact` restricted to the sync subset.
|
|
220
|
+
* @returns A `Tool` ready to register in a `ToolRegistry`.
|
|
221
|
+
* @throws {@link E_INVALID_SEARXNG_CONFIG} when `instanceUrl` or `artifact` is invalid (incl. an async resolver).
|
|
222
|
+
*/
|
|
223
|
+
var createSearxngSearchToolSync = (config) => {
|
|
224
|
+
return assembleTool(config, validateInstanceUrl(config), require_batteries_tools__shared.resolveArtifactSync(config.artifact ?? (() => require_spooled_markdown_artifact.SpooledJsonArtifact), fail));
|
|
225
|
+
};
|
|
226
|
+
/** Assemble the trimmed normalised payload, dropping empty aggregate arrays. */
|
|
227
|
+
var buildNormalisedPayload = (ctx) => {
|
|
228
|
+
const raw = ctx.raw ?? {};
|
|
229
|
+
const payload = {
|
|
230
|
+
query: typeof raw.query === "string" ? raw.query : ctx.request.query,
|
|
231
|
+
results: ctx.results
|
|
232
|
+
};
|
|
233
|
+
if (typeof raw.number_of_results === "number") payload.number_of_results = raw.number_of_results;
|
|
234
|
+
for (const key of [
|
|
235
|
+
"answers",
|
|
236
|
+
"infoboxes",
|
|
237
|
+
"suggestions",
|
|
238
|
+
"corrections"
|
|
239
|
+
]) {
|
|
240
|
+
const value = raw[key];
|
|
241
|
+
if (Array.isArray(value) && value.length > 0) payload[key] = value;
|
|
242
|
+
}
|
|
243
|
+
return payload;
|
|
244
|
+
};
|
|
245
|
+
//#endregion
|
|
246
|
+
Object.defineProperty(exports, "E_INVALID_SEARXNG_CONFIG", {
|
|
247
|
+
enumerable: true,
|
|
248
|
+
get: function() {
|
|
249
|
+
return E_INVALID_SEARXNG_CONFIG;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
Object.defineProperty(exports, "createSearxngSearchTool", {
|
|
253
|
+
enumerable: true,
|
|
254
|
+
get: function() {
|
|
255
|
+
return createSearxngSearchTool;
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
Object.defineProperty(exports, "createSearxngSearchToolSync", {
|
|
259
|
+
enumerable: true,
|
|
260
|
+
get: function() {
|
|
261
|
+
return createSearxngSearchToolSync;
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
//# sourceMappingURL=searxng-B_D--V5q.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searxng-B_D--V5q.js","names":[],"sources":["../src/batteries/tools/searxng/exceptions.ts","../src/batteries/tools/searxng/index.ts"],"sourcesContent":["/**\n * Battery-scoped exception constructors for the SearXNG search tool.\n *\n * @remarks\n * Battery-scoped exception classes owned by the SearXNG tool battery (not the ADK core). Minted\n * via `createException` from `@nhtio/adk/factories` and re-exported from the battery's barrel\n * (`@nhtio/adk/batteries/tools/searxng`). This file intentionally carries **no** `@module` tag:\n * it is an internal sibling relative-imported by `index.ts`, so it does not mint its own\n * `…/searxng/exceptions` entrypoint (whose `exceptions` leaf basename would collide with sibling\n * batteries under the `vite-plugin-dts` rolled-up `.d.ts` rule).\n */\n\nimport { createException } from '@nhtio/adk/factories'\n\n/**\n * Thrown when {@link createSearxngSearchTool} receives invalid configuration.\n *\n * @remarks\n * Fatal: config bugs (missing or unparseable `instanceUrl`) fail loud at factory-call time\n * rather than at the first search.\n */\nexport const E_INVALID_SEARXNG_CONFIG = createException<[string]>(\n 'E_INVALID_SEARXNG_CONFIG',\n 'Invalid SearXNG tool config: %s',\n 'E_INVALID_SEARXNG_CONFIG',\n 529,\n true\n)\n","/**\n * Factory for a configured SearXNG metasearch tool.\n *\n * @module @nhtio/adk/batteries/tools/searxng\n *\n * @remarks\n * Unlike the other bundled tool categories — every one of which exports a ready-made,\n * stateless `Tool` constant — the SearXNG battery exports **factories**,\n * {@link createSearxngSearchTool} (async) and {@link createSearxngSearchToolSync}. A search tool\n * has to talk to a *specific* SearXNG instance, usually behind custom authentication, so it needs\n * per-deployment configuration (a base URL and headers) that cannot be baked in at module load.\n *\n * Because this module exports factories rather than `Tool` instances, they MUST NOT be\n * bulk-registered via `Object.values(batteries)`. Call a factory first, then register the\n * returned tool: `new ToolRegistry([await createSearxngSearchTool({ instanceUrl })])`.\n *\n * @see https://docs.searxng.org/dev/search_api.html\n */\n\nimport { Tool } from '@nhtio/adk/forge'\nimport { isError } from '@nhtio/adk/guards'\nimport { validator } from '@nhtio/validation'\nimport { Middleware } from '@nhtio/middleware'\nimport { E_INVALID_SEARXNG_CONFIG } from './exceptions'\nimport { SpooledJsonArtifact } from '@nhtio/adk/spooled_artifact'\nimport {\n resolveHeaders,\n resolveArtifact,\n resolveArtifactSync,\n makeShortCircuit,\n isShortCircuit,\n runInputPipeline,\n runOutputPipeline,\n type ArtifactResolver,\n type SyncArtifactResolver,\n type SpooledArtifactCtor,\n type MiddlewareFn,\n} from '../_shared'\nimport type { Schema } from '@nhtio/validation'\nimport type { NextFn } from '@nhtio/middleware'\n\nexport { E_INVALID_SEARXNG_CONFIG } from './exceptions'\n\n/** A static set of request headers (used for custom authentication). */\nexport type SearxngHeaders = Record<string, string>\n\n/**\n * A resolver returning request headers, sync or async. Use this form when the auth token is\n * refreshable — the resolver runs on every search, so a fresh token can be minted per call.\n */\nexport type SearxngHeadersResolver = () => SearxngHeaders | Promise<SearxngHeaders>\n\n/** The output shape the tool serialises. `either` lets the model pick per call. */\nexport type SearxngResultFormat = 'normalized' | 'raw' | 'either'\n\n/**\n * A single normalised SearXNG result. SearXNG result items are deliberately untyped upstream,\n * so every field except a best-effort `title`/`url` is optional.\n */\nexport interface SearxngResult {\n /** Result title, when the source engine provided one. */\n title?: string\n /** Result URL, when the source engine provided one. */\n url?: string\n /** Snippet / summary text for the result. */\n content?: string\n /** The SearXNG engine that produced this result (e.g. `google`, `duckduckgo`). */\n engine?: string\n /** Relevance score as reported by SearXNG (higher is more relevant). */\n score?: number\n /** Publication date, when the source engine exposed one (ISO-ish string, engine-dependent). */\n publishedDate?: string\n}\n\n/**\n * Mutable context handed to each input-pipeline stage **before** the HTTP request is sent.\n *\n * @remarks\n * Stages mutate this in place (onion `(ctx, next)` style) to adjust the outgoing request —\n * inject or rotate auth headers, force a language, rewrite the query — or call\n * {@link SearxngRequestContext.shortCircuit} to skip the fetch entirely (e.g. a cache hit).\n */\nexport interface SearxngRequestContext {\n /** The tool's name (read-only). */\n readonly toolName: string\n /** The search query. Mutable. */\n query: string\n /** Extra SearXNG query parameters (`categories`, `engines`, `language`, …). Mutable. */\n params: Record<string, string>\n /** Resolved request headers. Mutable — inject, redact, or rotate auth here. */\n headers: SearxngHeaders\n /** The target instance base URL (read-only). */\n readonly instanceUrl: string\n /** Cross-stage scratch space; also carried onto the response context. */\n readonly stash: Map<string, unknown>\n /** Skip the fetch and return `result` verbatim as the tool's output. */\n shortCircuit(result: string): void\n}\n\n/**\n * Mutable context handed to each output-pipeline stage **after** the response JSON is parsed.\n *\n * @remarks\n * Stages reshape, redact, enrich, or re-rank {@link SearxngResponseContext.results}, mutate the\n * raw body, or set {@link SearxngResponseContext.output} to override the serialised string\n * verbatim (e.g. to render markdown that matches a markdown `artifact` resolver).\n */\nexport interface SearxngResponseContext {\n /** The tool's name (read-only). */\n readonly toolName: string\n /** The request context as it was sent (post-input-pipeline). */\n readonly request: SearxngRequestContext\n /** The parsed SearXNG JSON body. Mutable (used when `format` is `raw`). */\n raw: unknown\n /** The normalised result list. Mutable — filter, redact, or re-rank. */\n results: SearxngResult[]\n /** The effective payload shape for this call. */\n format: 'normalized' | 'raw'\n /** When set, used verbatim as the tool's output (overrides serialisation). */\n output?: string\n /** Cross-stage scratch space; carried over from the request context. */\n readonly stash: Map<string, unknown>\n}\n\n/** An input-pipeline stage. Onion middleware over {@link SearxngRequestContext}. */\nexport type SearxngInputMiddlewareFn = (\n ctx: SearxngRequestContext,\n next: NextFn\n) => void | Promise<void>\n\n/** An output-pipeline stage. Onion middleware over {@link SearxngResponseContext}. */\nexport type SearxngOutputMiddlewareFn = (\n ctx: SearxngResponseContext,\n next: NextFn\n) => void | Promise<void>\n\n/**\n * Configuration for {@link createSearxngSearchTool} (async) and\n * {@link createSearxngSearchToolSync} (sync — `artifact` narrowed to the sync subset).\n *\n * @typeParam A - The {@link ArtifactResolver} variant accepted: the full resolver (async factory)\n * or the sync subset ({@link createSearxngSearchToolSync}).\n */\nexport interface SearxngToolConfig<A = ArtifactResolver> {\n /** Base URL of the SearXNG instance, e.g. `https://searx.example.org`. Required. */\n instanceUrl: string\n /** Custom request headers — a static object or a (sync/async) resolver for refreshable auth. */\n headers?: SearxngHeaders | SearxngHeadersResolver\n /** Request timeout in milliseconds. Default `10_000`. */\n timeout?: number\n /**\n * Output shape. `normalized`/`raw` pin the shape (the model cannot change it); `either`\n * (default) exposes a `format` argument so the model chooses per call.\n */\n resultFormat?: SearxngResultFormat\n /** Tool name. Default `searxng_search`. */\n name?: string\n /** Tool description override. */\n description?: string\n /**\n * Spool-artifact resolver for the tool's output. Default `() => SpooledJsonArtifact`. Accepts a\n * constructor, a sync resolver, or — via {@link createSearxngSearchTool} — an async /\n * dynamic-import resolver. Pass `() => SpooledMarkdownArtifact` (paired with an output stage that\n * renders markdown into `ctx.output`) or `() => SpooledArtifact` for plain text.\n */\n artifact?: A\n /** Stages run before the HTTP request. See {@link SearxngRequestContext}. */\n inputPipeline?: SearxngInputMiddlewareFn[]\n /** Stages run after the response is parsed. See {@link SearxngResponseContext}. */\n outputPipeline?: SearxngOutputMiddlewareFn[]\n}\n\nconst DEFAULT_NAME = 'searxng_search'\nconst DEFAULT_TIMEOUT = 10_000\nconst DEFAULT_DESCRIPTION =\n 'Search the web via a SearXNG metasearch instance. Returns aggregated results (title, url, ' +\n 'snippet, source engine) plus any answers, infoboxes, and suggestions.'\n\n/** Normalise a loose SearXNG result item into a {@link SearxngResult}. */\nconst normaliseResult = (raw: unknown): SearxngResult => {\n const r = (raw ?? {}) as Record<string, unknown>\n const out: SearxngResult = {}\n if (typeof r.title === 'string') out.title = r.title\n if (typeof r.url === 'string') out.url = r.url\n if (typeof r.content === 'string') out.content = r.content\n if (typeof r.engine === 'string') out.engine = r.engine\n if (typeof r.score === 'number') out.score = r.score\n if (typeof r.publishedDate === 'string') out.publishedDate = r.publishedDate\n return out\n}\n\nconst fail = (reason: string): never => {\n throw new E_INVALID_SEARXNG_CONFIG([reason])\n}\n\n/** Validate `instanceUrl` and return the trailing-slash-normalised base. */\nconst validateInstanceUrl = (config: { instanceUrl?: string }): string => {\n if (typeof config?.instanceUrl !== 'string' || config.instanceUrl.trim() === '') {\n fail('instanceUrl is required')\n }\n try {\n new URL(config.instanceUrl as string)\n } catch {\n fail(`instanceUrl is not a valid URL: ${config.instanceUrl}`)\n }\n return (config.instanceUrl as string).replace(/\\/+$/, '')\n}\n\n/**\n * Assemble the `Tool` from validated config + an already-resolved sync artifact constructor.\n * Shared by both the async and sync factories — they differ only in how `artifact` is resolved.\n */\nconst assembleTool = (\n config: SearxngToolConfig<unknown>,\n instanceUrl: string,\n artifactConstructor: () => SpooledArtifactCtor\n): Tool => {\n const timeout = config.timeout ?? DEFAULT_TIMEOUT\n const resultFormat: SearxngResultFormat = config.resultFormat ?? 'either'\n const toolName = config.name ?? DEFAULT_NAME\n\n // Stages are fixed at factory time; build the Middleware shells once. A fresh `.runner()` is\n // minted per invocation inside the handler (runners are single-use).\n const inputMw = new Middleware<MiddlewareFn<SearxngRequestContext>>()\n for (const fn of config.inputPipeline ?? []) inputMw.add(fn)\n const outputMw = new Middleware<MiddlewareFn<SearxngResponseContext>>()\n for (const fn of config.outputPipeline ?? []) outputMw.add(fn)\n const hasInput = (config.inputPipeline ?? []).length > 0\n const hasOutput = (config.outputPipeline ?? []).length > 0\n\n // Build the input schema, conditionally exposing `format` only when the factory is neutral.\n const schemaShape: Record<string, Schema> = {\n query: validator.string().required().description('The search query.'),\n categories: validator\n .string()\n .optional()\n .description('Comma-separated SearXNG categories (e.g. \"general,news\").'),\n engines: validator\n .string()\n .optional()\n .description('Comma-separated SearXNG engines (e.g. \"google,duckduckgo\").'),\n language: validator.string().optional().description('Language code (e.g. \"en\", \"de\").'),\n pageno: validator.number().min(1).default(1).description('Result page number (1-based).'),\n time_range: validator\n .string()\n .valid('day', 'month', 'year')\n .optional()\n .description('Restrict results to a time range.'),\n safesearch: validator\n .number()\n .valid(0, 1, 2)\n .optional()\n .description('Safe-search level: 0 (off), 1 (moderate), 2 (strict).'),\n }\n if (resultFormat === 'either') {\n schemaShape.format = validator\n .string()\n .valid('normalized', 'raw')\n .default('normalized')\n .description('Output shape: \"normalized\" (trimmed) or \"raw\" (full SearXNG JSON).')\n }\n const inputSchema = validator.object(schemaShape)\n\n return new Tool({\n name: toolName,\n description: config.description ?? DEFAULT_DESCRIPTION,\n inputSchema,\n artifactConstructor,\n handler: async (args) => {\n const a = args as {\n query: string\n categories?: string\n engines?: string\n language?: string\n pageno?: number\n time_range?: string\n safesearch?: number\n format?: 'normalized' | 'raw'\n }\n\n try {\n // 1. Effective output format: a pinned factory format wins; else the model's choice.\n const format: 'normalized' | 'raw' =\n resultFormat === 'either' ? (a.format ?? 'normalized') : resultFormat\n\n // 2. Resolve headers, merged over portable defaults (caller headers win).\n const headers: SearxngHeaders = {\n 'Accept': 'application/json',\n 'User-Agent': 'adk-searxng-tool',\n ...(await resolveHeaders(config.headers)),\n }\n\n // 3. Assemble the SearXNG query params from validated args.\n const params: Record<string, string> = {}\n if (a.categories) params.categories = a.categories\n if (a.engines) params.engines = a.engines\n if (a.language) params.language = a.language\n if (a.pageno && a.pageno !== 1) params.pageno = String(a.pageno)\n if (a.time_range) params.time_range = a.time_range\n if (typeof a.safesearch === 'number') params.safesearch = String(a.safesearch)\n\n const stash = new Map<string, unknown>()\n\n // 4. Run the input pipeline (fresh runner) over a mutable request context.\n const requestCtx: SearxngRequestContext = {\n toolName,\n query: a.query,\n params,\n headers,\n instanceUrl,\n stash,\n shortCircuit: makeShortCircuit(),\n }\n\n if (hasInput) {\n const short = await runInputPipeline(inputMw, requestCtx, 'SearXNG')\n if (short !== undefined) return short\n }\n\n // 5. Build the request URL from the (possibly mutated) query + params.\n const url = new URL('/search', instanceUrl + '/')\n url.searchParams.set('q', requestCtx.query)\n for (const [k, v] of Object.entries(requestCtx.params)) url.searchParams.set(k, v)\n url.searchParams.set('format', 'json')\n\n // 6. Fetch with an AbortController timeout.\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), timeout)\n let response: Response\n try {\n response = await fetch(url, {\n method: 'GET',\n headers: requestCtx.headers,\n signal: controller.signal,\n })\n } finally {\n clearTimeout(timer)\n }\n\n if (!response.ok) {\n if (response.status === 403) {\n return (\n `Error: SearXNG returned 403 Forbidden. The instance likely has the JSON output ` +\n `format disabled — enable it under \"search.formats: [json]\" in its settings.yml.`\n )\n }\n return `Error: SearXNG returned HTTP ${response.status} ${response.statusText}.`\n }\n\n const body = (await response.json()) as Record<string, unknown>\n\n // 7. Run the output pipeline (fresh runner) over a mutable response context.\n const responseCtx: SearxngResponseContext = {\n toolName,\n request: requestCtx,\n raw: body,\n results: Array.isArray(body.results) ? body.results.map(normaliseResult) : [],\n format,\n stash,\n }\n\n if (hasOutput) await runOutputPipeline(outputMw, responseCtx, 'SearXNG')\n\n // 8. Serialise and return.\n if (typeof responseCtx.output === 'string') return responseCtx.output\n if (responseCtx.format === 'raw') return JSON.stringify(responseCtx.raw, null, 2)\n return JSON.stringify(buildNormalisedPayload(responseCtx), null, 2)\n } catch (err) {\n if (isShortCircuit(err)) return err.result\n return `Error: ${isError(err) ? err.message : String(err)}`\n }\n },\n })\n}\n\n/**\n * Create a configured SearXNG search {@link Tool} (async — accepts a dynamic-import `artifact`).\n *\n * @remarks\n * Async because `artifact` may be an async / dynamic-import resolver, which must be resolved to the\n * sync `() => Ctor` that `Tool.artifactConstructor` requires before the tool is built (the\n * wrap-site invokes it synchronously). For the common case where you reference the artifact class\n * directly, use {@link createSearxngSearchToolSync} and skip the `await`.\n *\n * The handler always requests `format=json`. Note that SearXNG ships with JSON output\n * **disabled** by default (it is abused by bots); an instance that has not enabled\n * `search.formats: [json]` in its `settings.yml` answers with HTTP 403, which the tool returns\n * as a graceful `Error:` string naming the setting.\n *\n * @warning\n * Do not trust the `number_of_results` field for a result count — SearXNG frequently reports `0`\n * in JSON output even when `results` is non-empty. This is a long-standing upstream quirk, not a\n * tool defect (see {@link https://github.com/searxng/searxng/issues/2987 | searxng#2987} and\n * {@link https://github.com/searxng/searxng/issues/2457 | searxng#2457}). The tool passes the\n * field through verbatim; use `results.length` as the authoritative count.\n *\n * @param config - The instance URL, optional custom headers, output-format policy, `artifact`\n * resolver, and input/output middleware pipelines. See {@link SearxngToolConfig}.\n * @returns A promise of a `Tool` ready to register in a `ToolRegistry`.\n * @throws {@link E_INVALID_SEARXNG_CONFIG} when `instanceUrl` or `artifact` is invalid.\n */\nexport const createSearxngSearchTool = async (\n config: SearxngToolConfig<ArtifactResolver>\n): Promise<Tool> => {\n const instanceUrl = validateInstanceUrl(config)\n const artifactConstructor = await resolveArtifact(\n config.artifact ?? (() => SpooledJsonArtifact),\n fail\n )\n return assembleTool(config, instanceUrl, artifactConstructor)\n}\n\n/**\n * Synchronous {@link createSearxngSearchTool} — the ergonomic common path.\n *\n * @remarks\n * `artifact` is narrowed to the sync subset (a constructor or a sync resolver). Passing an async\n * resolver is a compile-time type error and a runtime {@link E_INVALID_SEARXNG_CONFIG}; for\n * dynamic-import resolvers use the async {@link createSearxngSearchTool}. See its docs for the\n * `number_of_results` caveat and 403/JSON-disabled behaviour.\n *\n * @param config - Same as {@link SearxngToolConfig}, with `artifact` restricted to the sync subset.\n * @returns A `Tool` ready to register in a `ToolRegistry`.\n * @throws {@link E_INVALID_SEARXNG_CONFIG} when `instanceUrl` or `artifact` is invalid (incl. an async resolver).\n */\nexport const createSearxngSearchToolSync = (\n config: SearxngToolConfig<SyncArtifactResolver>\n): Tool => {\n const instanceUrl = validateInstanceUrl(config)\n const artifactConstructor = resolveArtifactSync(\n config.artifact ?? (() => SpooledJsonArtifact),\n fail\n )\n return assembleTool(config, instanceUrl, artifactConstructor)\n}\n\n/** Assemble the trimmed normalised payload, dropping empty aggregate arrays. */\nconst buildNormalisedPayload = (ctx: SearxngResponseContext): Record<string, unknown> => {\n const raw = (ctx.raw ?? {}) as Record<string, unknown>\n const payload: Record<string, unknown> = {\n query: typeof raw.query === 'string' ? raw.query : ctx.request.query,\n results: ctx.results,\n }\n // NOTE: SearXNG's `number_of_results` is frequently `0` in JSON output even when `results`\n // is non-empty — a long-standing upstream quirk, not a tool bug (see\n // https://github.com/searxng/searxng/issues/2987 and\n // https://github.com/searxng/searxng/issues/2457). We pass through whatever the instance\n // reports; treat `results.length` as the authoritative count, not this field.\n if (typeof raw.number_of_results === 'number') payload.number_of_results = raw.number_of_results\n for (const key of ['answers', 'infoboxes', 'suggestions', 'corrections'] as const) {\n const value = raw[key]\n if (Array.isArray(value) && value.length > 0) payload[key] = value\n }\n return payload\n}\n"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ license: MIT
|
|
|
5
5
|
compatibility: "Requires TypeScript/JavaScript project using @nhtio/adk; examples assume Node 20+ or compatible browser/runtime."
|
|
6
6
|
metadata:
|
|
7
7
|
package: "@nhtio/adk"
|
|
8
|
-
version: "1.
|
|
8
|
+
version: "1.20260609.1"
|
|
9
9
|
author: "Jak Giveon <jak@nht.io>"
|
|
10
10
|
copyright: "© 2025-present New Horizon Technology LTD"
|
|
11
11
|
---
|
|
@@ -17,7 +17,7 @@ Use this skill to help users build or review an `@nhtio/adk` assembly: the appli
|
|
|
17
17
|
## Package Metadata
|
|
18
18
|
|
|
19
19
|
- Package: `@nhtio/adk`
|
|
20
|
-
- Version: `1.
|
|
20
|
+
- Version: `1.20260609.1`
|
|
21
21
|
- License: MIT
|
|
22
22
|
- Author: Jak Giveon <jak@nht.io>
|
|
23
23
|
- Copyright: © 2025-present New Horizon Technology LTD
|