@nhtio/adk 1.20260607.2 → 1.20260609.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +185 -0
- package/batteries/embeddings/openai/adapter.cjs +1 -1
- package/batteries/embeddings/openai/adapter.mjs +1 -1
- package/batteries/embeddings/openai/exceptions.cjs +1 -1
- package/batteries/embeddings/openai/exceptions.mjs +1 -1
- package/batteries/embeddings/openai/types.d.ts +7 -0
- package/batteries/embeddings/webllm/adapter.cjs +1 -1
- package/batteries/embeddings/webllm/adapter.mjs +1 -1
- package/batteries/embeddings/webllm/exceptions.cjs +1 -1
- package/batteries/embeddings/webllm/exceptions.mjs +1 -1
- package/batteries/llm/chat_common/helpers.d.ts +165 -0
- package/batteries/llm/chat_common/types.d.ts +309 -0
- package/batteries/llm/index.d.ts +5 -0
- package/batteries/llm/ollama/adapter.cjs +736 -0
- package/batteries/llm/ollama/adapter.cjs.map +1 -0
- package/batteries/llm/ollama/adapter.d.ts +64 -0
- package/batteries/llm/ollama/adapter.mjs +734 -0
- package/batteries/llm/ollama/adapter.mjs.map +1 -0
- package/batteries/llm/ollama/exceptions.cjs +105 -0
- package/batteries/llm/ollama/exceptions.cjs.map +1 -0
- package/batteries/llm/ollama/exceptions.d.ts +112 -0
- package/batteries/llm/ollama/exceptions.mjs +96 -0
- package/batteries/llm/ollama/exceptions.mjs.map +1 -0
- package/batteries/llm/ollama/helpers.cjs +487 -0
- package/batteries/llm/ollama/helpers.cjs.map +1 -0
- package/batteries/llm/ollama/helpers.d.ts +158 -0
- package/batteries/llm/ollama/helpers.mjs +450 -0
- package/batteries/llm/ollama/helpers.mjs.map +1 -0
- package/batteries/llm/ollama/index.d.ts +29 -0
- package/batteries/llm/ollama/types.cjs +2 -0
- package/batteries/llm/ollama/types.d.ts +334 -0
- package/batteries/llm/ollama/types.mjs +0 -0
- package/batteries/llm/ollama/validation.cjs +130 -0
- package/batteries/llm/ollama/validation.cjs.map +1 -0
- package/batteries/llm/ollama/validation.d.ts +31 -0
- package/batteries/llm/ollama/validation.mjs +127 -0
- package/batteries/llm/ollama/validation.mjs.map +1 -0
- package/batteries/llm/ollama.cjs +54 -0
- package/batteries/llm/ollama.mjs +6 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs +36 -19
- package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/adapter.mjs +23 -6
- package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/exceptions.cjs +1 -1
- package/batteries/llm/openai_chat_completions/exceptions.mjs +1 -1
- package/batteries/llm/openai_chat_completions/helpers.cjs +80 -320
- package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/helpers.d.ts +68 -144
- package/batteries/llm/openai_chat_completions/helpers.mjs +40 -280
- package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/types.d.ts +273 -181
- package/batteries/llm/openai_chat_completions/validation.cjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/validation.mjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions.cjs +29 -28
- package/batteries/llm/openai_chat_completions.mjs +2 -1
- package/batteries/llm/webllm_chat_completions/adapter.cjs +38 -19
- package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.d.ts +18 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs +25 -6
- package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/exceptions.cjs +1 -1
- package/batteries/llm/webllm_chat_completions/exceptions.mjs +1 -1
- package/batteries/llm/webllm_chat_completions/helpers.cjs +29 -28
- package/batteries/llm/webllm_chat_completions/helpers.mjs +2 -1
- package/batteries/llm/webllm_chat_completions/types.d.ts +21 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs +13 -1
- package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/validation.d.ts +12 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs +13 -1
- package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions.cjs +29 -28
- package/batteries/llm/webllm_chat_completions.mjs +2 -1
- package/batteries/llm.cjs +44 -28
- package/batteries/llm.mjs +9 -4
- package/batteries/storage/flydrive.cjs +1 -1
- package/batteries/storage/flydrive.mjs +1 -1
- package/batteries/storage/in_memory/index.d.ts +1 -1
- package/batteries/storage/in_memory.cjs +2 -2
- package/batteries/storage/in_memory.cjs.map +1 -1
- package/batteries/storage/in_memory.mjs +2 -2
- package/batteries/storage/in_memory.mjs.map +1 -1
- package/batteries/storage/opfs/index.d.ts +19 -0
- package/batteries/storage/opfs.cjs +1 -1
- package/batteries/storage/opfs.cjs.map +1 -1
- package/batteries/storage/opfs.mjs +1 -1
- package/batteries/storage/opfs.mjs.map +1 -1
- package/batteries/tools/color.cjs +3 -2
- package/batteries/tools/color.cjs.map +1 -1
- package/batteries/tools/color.mjs +3 -2
- package/batteries/tools/color.mjs.map +1 -1
- package/batteries/tools/comparison.cjs +4 -3
- package/batteries/tools/comparison.cjs.map +1 -1
- package/batteries/tools/comparison.mjs +4 -3
- package/batteries/tools/comparison.mjs.map +1 -1
- package/batteries/tools/data_structure.cjs +30 -10
- package/batteries/tools/data_structure.cjs.map +1 -1
- package/batteries/tools/data_structure.mjs +30 -10
- package/batteries/tools/data_structure.mjs.map +1 -1
- package/batteries/tools/datetime_extended.cjs +5 -10
- package/batteries/tools/datetime_extended.cjs.map +1 -1
- package/batteries/tools/datetime_extended.mjs +5 -10
- package/batteries/tools/datetime_extended.mjs.map +1 -1
- package/batteries/tools/datetime_math.cjs +2 -2
- package/batteries/tools/datetime_math.mjs +2 -2
- package/batteries/tools/encoding.cjs +13 -4
- package/batteries/tools/encoding.cjs.map +1 -1
- package/batteries/tools/encoding.mjs +13 -4
- package/batteries/tools/encoding.mjs.map +1 -1
- package/batteries/tools/formatting.cjs +4 -4
- package/batteries/tools/formatting.cjs.map +1 -1
- package/batteries/tools/formatting.mjs +4 -4
- package/batteries/tools/formatting.mjs.map +1 -1
- package/batteries/tools/geo_basics.cjs +2 -2
- package/batteries/tools/geo_basics.mjs +2 -2
- package/batteries/tools/index.d.ts +1 -0
- package/batteries/tools/math.cjs +10 -8
- package/batteries/tools/math.cjs.map +1 -1
- package/batteries/tools/math.mjs +10 -8
- package/batteries/tools/math.mjs.map +1 -1
- package/batteries/tools/memory.cjs +5 -5
- package/batteries/tools/memory.mjs +5 -5
- package/batteries/tools/parsing.cjs +9 -5
- package/batteries/tools/parsing.cjs.map +1 -1
- package/batteries/tools/parsing.mjs +9 -5
- package/batteries/tools/parsing.mjs.map +1 -1
- package/batteries/tools/retrievables.cjs +4 -4
- package/batteries/tools/retrievables.mjs +4 -4
- package/batteries/tools/searxng/exceptions.d.ts +21 -0
- package/batteries/tools/searxng/index.d.ts +150 -0
- package/batteries/tools/searxng.cjs +5 -0
- package/batteries/tools/searxng.mjs +2 -0
- package/batteries/tools/standing_instructions.cjs +4 -4
- package/batteries/tools/standing_instructions.mjs +4 -4
- package/batteries/tools/statistics.cjs +54 -43
- package/batteries/tools/statistics.cjs.map +1 -1
- package/batteries/tools/statistics.mjs +54 -43
- package/batteries/tools/statistics.mjs.map +1 -1
- package/batteries/tools/string_processing.cjs +5 -5
- package/batteries/tools/string_processing.cjs.map +1 -1
- package/batteries/tools/string_processing.mjs +5 -5
- package/batteries/tools/string_processing.mjs.map +1 -1
- package/batteries/tools/structured_data.cjs +8 -13
- package/batteries/tools/structured_data.cjs.map +1 -1
- package/batteries/tools/structured_data.mjs +8 -13
- package/batteries/tools/structured_data.mjs.map +1 -1
- package/batteries/tools/text_analysis.cjs +3 -3
- package/batteries/tools/text_analysis.mjs +3 -3
- package/batteries/tools/text_comparison.cjs +2 -2
- package/batteries/tools/text_comparison.mjs +2 -2
- package/batteries/tools/time.cjs +2 -2
- package/batteries/tools/time.mjs +2 -2
- package/batteries/tools/unit_conversion.cjs +10 -8
- package/batteries/tools/unit_conversion.cjs.map +1 -1
- package/batteries/tools/unit_conversion.mjs +10 -8
- package/batteries/tools/unit_conversion.mjs.map +1 -1
- package/batteries/tools.cjs +3 -0
- package/batteries/tools.mjs +2 -1
- package/batteries/vector/arangodb/index.d.ts +2 -0
- package/batteries/vector/arangodb.cjs +2 -1
- package/batteries/vector/arangodb.cjs.map +1 -1
- package/batteries/vector/arangodb.mjs +2 -1
- package/batteries/vector/arangodb.mjs.map +1 -1
- package/batteries/vector/builder.cjs +31 -0
- package/batteries/vector/builder.cjs.map +1 -1
- package/batteries/vector/builder.d.ts +58 -0
- package/batteries/vector/builder.mjs +31 -0
- package/batteries/vector/builder.mjs.map +1 -1
- package/batteries/vector/chroma/index.d.ts +4 -0
- package/batteries/vector/chroma.cjs +3 -0
- package/batteries/vector/chroma.cjs.map +1 -1
- package/batteries/vector/chroma.mjs +3 -0
- package/batteries/vector/chroma.mjs.map +1 -1
- package/batteries/vector/clickhouse/index.d.ts +2 -0
- package/batteries/vector/clickhouse.cjs +2 -1
- package/batteries/vector/clickhouse.cjs.map +1 -1
- package/batteries/vector/clickhouse.mjs +2 -1
- package/batteries/vector/clickhouse.mjs.map +1 -1
- package/batteries/vector/cloudflare/index.d.ts +2 -0
- package/batteries/vector/cloudflare.cjs +2 -1
- package/batteries/vector/cloudflare.cjs.map +1 -1
- package/batteries/vector/cloudflare.mjs +2 -1
- package/batteries/vector/cloudflare.mjs.map +1 -1
- package/batteries/vector/conformance/index.d.ts +22 -0
- package/batteries/vector/conformance.cjs +22 -0
- package/batteries/vector/conformance.cjs.map +1 -1
- package/batteries/vector/conformance.mjs +22 -0
- package/batteries/vector/conformance.mjs.map +1 -1
- package/batteries/vector/contract.cjs +22 -0
- package/batteries/vector/contract.cjs.map +1 -1
- package/batteries/vector/contract.d.ts +51 -0
- package/batteries/vector/contract.mjs +22 -0
- package/batteries/vector/contract.mjs.map +1 -1
- package/batteries/vector/couchbase/index.d.ts +2 -0
- package/batteries/vector/couchbase.cjs +2 -1
- package/batteries/vector/couchbase.cjs.map +1 -1
- package/batteries/vector/couchbase.mjs +2 -1
- package/batteries/vector/couchbase.mjs.map +1 -1
- package/batteries/vector/duckdb/index.d.ts +2 -0
- package/batteries/vector/duckdb.cjs +2 -1
- package/batteries/vector/duckdb.cjs.map +1 -1
- package/batteries/vector/duckdb.mjs +2 -1
- package/batteries/vector/duckdb.mjs.map +1 -1
- package/batteries/vector/elasticsearch/index.d.ts +2 -0
- package/batteries/vector/elasticsearch.cjs +2 -1
- package/batteries/vector/elasticsearch.cjs.map +1 -1
- package/batteries/vector/elasticsearch.mjs +2 -1
- package/batteries/vector/elasticsearch.mjs.map +1 -1
- package/batteries/vector/exceptions.cjs +1 -1
- package/batteries/vector/exceptions.mjs +1 -1
- package/batteries/vector/factory.cjs +6 -0
- package/batteries/vector/factory.cjs.map +1 -1
- package/batteries/vector/factory.d.ts +14 -0
- package/batteries/vector/factory.mjs +6 -0
- package/batteries/vector/factory.mjs.map +1 -1
- package/batteries/vector/filters.cjs +22 -1
- package/batteries/vector/filters.cjs.map +1 -1
- package/batteries/vector/filters.d.ts +38 -0
- package/batteries/vector/filters.mjs +22 -1
- package/batteries/vector/filters.mjs.map +1 -1
- package/batteries/vector/helpers.cjs +13 -0
- package/batteries/vector/helpers.cjs.map +1 -1
- package/batteries/vector/helpers.d.ts +14 -0
- package/batteries/vector/helpers.mjs +13 -0
- package/batteries/vector/helpers.mjs.map +1 -1
- package/batteries/vector/hnswlib/index.d.ts +2 -0
- package/batteries/vector/hnswlib.cjs +2 -1
- package/batteries/vector/hnswlib.cjs.map +1 -1
- package/batteries/vector/hnswlib.mjs +2 -1
- package/batteries/vector/hnswlib.mjs.map +1 -1
- package/batteries/vector/in_memory/index.d.ts +1 -0
- package/batteries/vector/in_memory.cjs +1 -0
- package/batteries/vector/in_memory.cjs.map +1 -1
- package/batteries/vector/in_memory.mjs +1 -0
- package/batteries/vector/in_memory.mjs.map +1 -1
- package/batteries/vector/lancedb/index.d.ts +2 -0
- package/batteries/vector/lancedb.cjs +2 -1
- package/batteries/vector/lancedb.cjs.map +1 -1
- package/batteries/vector/lancedb.mjs +2 -1
- package/batteries/vector/lancedb.mjs.map +1 -1
- package/batteries/vector/mariadb/index.d.ts +2 -0
- package/batteries/vector/mariadb.cjs +2 -1
- package/batteries/vector/mariadb.cjs.map +1 -1
- package/batteries/vector/mariadb.mjs +2 -1
- package/batteries/vector/mariadb.mjs.map +1 -1
- package/batteries/vector/meilisearch/index.d.ts +2 -0
- package/batteries/vector/meilisearch.cjs +2 -1
- package/batteries/vector/meilisearch.cjs.map +1 -1
- package/batteries/vector/meilisearch.mjs +2 -1
- package/batteries/vector/meilisearch.mjs.map +1 -1
- package/batteries/vector/migrate.cjs +18 -1
- package/batteries/vector/migrate.cjs.map +1 -1
- package/batteries/vector/migrate.d.ts +31 -0
- package/batteries/vector/migrate.mjs +18 -1
- package/batteries/vector/migrate.mjs.map +1 -1
- package/batteries/vector/milvus/index.d.ts +5 -0
- package/batteries/vector/milvus.cjs +4 -0
- package/batteries/vector/milvus.cjs.map +1 -1
- package/batteries/vector/milvus.mjs +4 -0
- package/batteries/vector/milvus.mjs.map +1 -1
- package/batteries/vector/mongodb/index.d.ts +2 -0
- package/batteries/vector/mongodb.cjs +2 -1
- package/batteries/vector/mongodb.cjs.map +1 -1
- package/batteries/vector/mongodb.mjs +2 -1
- package/batteries/vector/mongodb.mjs.map +1 -1
- package/batteries/vector/neo4j/index.d.ts +2 -0
- package/batteries/vector/neo4j.cjs +2 -1
- package/batteries/vector/neo4j.cjs.map +1 -1
- package/batteries/vector/neo4j.mjs +2 -1
- package/batteries/vector/neo4j.mjs.map +1 -1
- package/batteries/vector/opensearch/index.d.ts +2 -0
- package/batteries/vector/opensearch.cjs +2 -1
- package/batteries/vector/opensearch.cjs.map +1 -1
- package/batteries/vector/opensearch.mjs +2 -1
- package/batteries/vector/opensearch.mjs.map +1 -1
- package/batteries/vector/oracle23ai/index.d.ts +2 -0
- package/batteries/vector/oracle23ai.cjs +2 -1
- package/batteries/vector/oracle23ai.cjs.map +1 -1
- package/batteries/vector/oracle23ai.mjs +2 -1
- package/batteries/vector/oracle23ai.mjs.map +1 -1
- package/batteries/vector/orama/index.d.ts +1 -0
- package/batteries/vector/orama.cjs +1 -0
- package/batteries/vector/orama.cjs.map +1 -1
- package/batteries/vector/orama.mjs +1 -0
- package/batteries/vector/orama.mjs.map +1 -1
- package/batteries/vector/pgvector/index.d.ts +9 -2
- package/batteries/vector/pgvector.cjs +4 -0
- package/batteries/vector/pgvector.cjs.map +1 -1
- package/batteries/vector/pgvector.mjs +4 -0
- package/batteries/vector/pgvector.mjs.map +1 -1
- package/batteries/vector/pinecone/index.d.ts +5 -0
- package/batteries/vector/pinecone.cjs +3 -1
- package/batteries/vector/pinecone.cjs.map +1 -1
- package/batteries/vector/pinecone.mjs +3 -1
- package/batteries/vector/pinecone.mjs.map +1 -1
- package/batteries/vector/plan.d.ts +27 -0
- package/batteries/vector/qdrant/index.d.ts +5 -0
- package/batteries/vector/qdrant.cjs +4 -0
- package/batteries/vector/qdrant.cjs.map +1 -1
- package/batteries/vector/qdrant.mjs +4 -0
- package/batteries/vector/qdrant.mjs.map +1 -1
- package/batteries/vector/redis/index.d.ts +2 -0
- package/batteries/vector/redis.cjs +2 -1
- package/batteries/vector/redis.cjs.map +1 -1
- package/batteries/vector/redis.mjs +2 -1
- package/batteries/vector/redis.mjs.map +1 -1
- package/batteries/vector/retrievable.cjs +9 -1
- package/batteries/vector/retrievable.cjs.map +1 -1
- package/batteries/vector/retrievable.mjs +9 -1
- package/batteries/vector/retrievable.mjs.map +1 -1
- package/batteries/vector/retrievable_glue.d.ts +21 -0
- package/batteries/vector/s3vectors/index.d.ts +2 -0
- package/batteries/vector/s3vectors.cjs +2 -1
- package/batteries/vector/s3vectors.cjs.map +1 -1
- package/batteries/vector/s3vectors.mjs +2 -1
- package/batteries/vector/s3vectors.mjs.map +1 -1
- package/batteries/vector/schema.cjs +28 -0
- package/batteries/vector/schema.cjs.map +1 -1
- package/batteries/vector/schema.d.ts +39 -0
- package/batteries/vector/schema.mjs +28 -0
- package/batteries/vector/schema.mjs.map +1 -1
- package/batteries/vector/solr/index.d.ts +2 -0
- package/batteries/vector/solr.cjs +2 -1
- package/batteries/vector/solr.cjs.map +1 -1
- package/batteries/vector/solr.mjs +2 -1
- package/batteries/vector/solr.mjs.map +1 -1
- package/batteries/vector/sqlite_vec/index.d.ts +6 -3
- package/batteries/vector/sqlite_vec.cjs +2 -0
- package/batteries/vector/sqlite_vec.cjs.map +1 -1
- package/batteries/vector/sqlite_vec.mjs +2 -0
- package/batteries/vector/sqlite_vec.mjs.map +1 -1
- package/batteries/vector/surrealdb/index.d.ts +2 -0
- package/batteries/vector/surrealdb.cjs +2 -1
- package/batteries/vector/surrealdb.cjs.map +1 -1
- package/batteries/vector/surrealdb.mjs +2 -1
- package/batteries/vector/surrealdb.mjs.map +1 -1
- package/batteries/vector/types.d.ts +27 -0
- package/batteries/vector/typesense/index.d.ts +2 -0
- package/batteries/vector/typesense.cjs +2 -1
- package/batteries/vector/typesense.cjs.map +1 -1
- package/batteries/vector/typesense.mjs +2 -1
- package/batteries/vector/typesense.mjs.map +1 -1
- package/batteries/vector/validation.cjs +14 -0
- package/batteries/vector/validation.cjs.map +1 -1
- package/batteries/vector/validation.d.ts +14 -0
- package/batteries/vector/validation.mjs +14 -0
- package/batteries/vector/validation.mjs.map +1 -1
- package/batteries/vector/vector_store_constructor.cjs +1 -1
- package/batteries/vector/vector_store_constructor.cjs.map +1 -1
- package/batteries/vector/vector_store_constructor.d.ts +1 -1
- package/batteries/vector/vector_store_constructor.mjs +1 -1
- package/batteries/vector/vector_store_constructor.mjs.map +1 -1
- package/batteries/vector/vespa/index.d.ts +2 -0
- package/batteries/vector/vespa.cjs +2 -1
- package/batteries/vector/vespa.cjs.map +1 -1
- package/batteries/vector/vespa.mjs +2 -1
- package/batteries/vector/vespa.mjs.map +1 -1
- package/batteries/vector/weaviate/index.d.ts +2 -0
- package/batteries/vector/weaviate.cjs +2 -1
- package/batteries/vector/weaviate.cjs.map +1 -1
- package/batteries/vector/weaviate.mjs +2 -1
- package/batteries/vector/weaviate.mjs.map +1 -1
- package/batteries.cjs +46 -28
- package/batteries.mjs +10 -5
- package/{common-BT0nfCi9.mjs → common-DYDUi99O.mjs} +9 -9
- package/common-DYDUi99O.mjs.map +1 -0
- package/{common-Cj8TaQ9U.js → common-DZl3ADJs.js} +9 -9
- package/common-DZl3ADJs.js.map +1 -0
- package/common.cjs +7 -7
- package/common.d.ts +1 -1
- package/common.mjs +7 -7
- package/{dispatch_runner-DPcS7Y_M.mjs → dispatch_runner--ZhdDWRZ.mjs} +27 -5
- package/{dispatch_runner-DPcS7Y_M.mjs.map → dispatch_runner--ZhdDWRZ.mjs.map} +1 -1
- package/{dispatch_runner-BHBNupqp.js → dispatch_runner-nHDKkxye.js} +27 -5
- package/{dispatch_runner-BHBNupqp.js.map → dispatch_runner-nHDKkxye.js.map} +1 -1
- package/dispatch_runner.cjs +1 -1
- package/dispatch_runner.d.ts +1 -1
- package/dispatch_runner.mjs +1 -1
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs.map +1 -1
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.d.ts +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.mjs +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.mjs.map +1 -1
- package/eslint/rules/no_model_in_tool_handler.cjs +1 -0
- package/eslint/rules/no_model_in_tool_handler.cjs.map +1 -1
- package/eslint/rules/no_model_in_tool_handler.d.ts +1 -0
- package/eslint/rules/no_model_in_tool_handler.mjs +1 -0
- package/eslint/rules/no_model_in_tool_handler.mjs.map +1 -1
- package/eslint/rules/require_validator_any_required.cjs +1 -0
- package/eslint/rules/require_validator_any_required.cjs.map +1 -1
- package/eslint/rules/require_validator_any_required.d.ts +1 -0
- package/eslint/rules/require_validator_any_required.mjs +1 -0
- package/eslint/rules/require_validator_any_required.mjs.map +1 -1
- package/eslint/rules/thought_payload_requires_replay_tag.cjs +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.cjs.map +1 -1
- package/eslint/rules/thought_payload_requires_replay_tag.d.ts +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.mjs +1 -0
- package/eslint/rules/thought_payload_requires_replay_tag.mjs.map +1 -1
- package/eslint/rules/token_encoding_requires_context_window.cjs +1 -0
- package/eslint/rules/token_encoding_requires_context_window.cjs.map +1 -1
- package/eslint/rules/token_encoding_requires_context_window.d.ts +1 -0
- package/eslint/rules/token_encoding_requires_context_window.mjs +1 -0
- package/eslint/rules/token_encoding_requires_context_window.mjs.map +1 -1
- package/eslint.cjs +1 -1
- package/eslint.mjs +1 -1
- package/{exceptions-BeWH2FwP.mjs → exceptions-BDhN0Xzr.mjs} +3 -2
- package/exceptions-BDhN0Xzr.mjs.map +1 -0
- package/{exceptions-CitH5wZI.js → exceptions-BRXrUKiW.js} +3 -2
- package/exceptions-BRXrUKiW.js.map +1 -0
- package/exceptions.cjs +2 -2
- package/exceptions.mjs +2 -2
- package/factories.cjs +1 -1
- package/factories.mjs +1 -1
- package/forge.cjs +4 -4
- package/forge.d.ts +1 -1
- package/forge.mjs +4 -4
- package/guards.cjs +9 -9
- package/guards.mjs +9 -9
- package/helpers-DSTFxTiC.js +497 -0
- package/helpers-DSTFxTiC.js.map +1 -0
- package/helpers-xhrQbMAG.mjs +306 -0
- package/helpers-xhrQbMAG.mjs.map +1 -0
- package/index.cjs +13 -13
- package/index.mjs +13 -13
- package/lib/classes/base_exception.d.ts +1 -0
- package/lib/classes/media.d.ts +10 -0
- package/lib/classes/retrievable.d.ts +1 -1
- package/lib/classes/spooled_json_artifact.d.ts +1 -1
- package/lib/classes/spooled_markdown_artifact.d.ts +1 -0
- package/lib/classes/tokenizable.d.ts +3 -0
- package/lib/classes/tool.d.ts +8 -0
- package/lib/classes/turn_gate.d.ts +6 -0
- package/lib/dispatch_runner.d.ts +4 -32
- package/lib/helpers/bignum.cjs +82 -0
- package/lib/helpers/bignum.cjs.map +1 -0
- package/lib/helpers/bignum.d.ts +52 -0
- package/lib/helpers/bignum.mjs +74 -0
- package/lib/helpers/bignum.mjs.map +1 -0
- package/lib/turn_runner.d.ts +1 -1
- package/lib/types/dispatch_runner.d.ts +83 -0
- package/lib/utils/exceptions.d.ts +1 -1
- package/lib/utils/retry.cjs.map +1 -1
- package/lib/utils/retry.d.ts +2 -0
- package/lib/utils/retry.mjs.map +1 -1
- package/mcp/adk-docs-corpus.json +1 -1
- package/package.json +264 -224
- package/{runtime-j92CNi5z.mjs → runtime-Bz5zA8wc.mjs} +2 -2
- package/{runtime-j92CNi5z.mjs.map → runtime-Bz5zA8wc.mjs.map} +1 -1
- package/{runtime-MFFcJrRv.js → runtime-DslE1aBw.js} +2 -2
- package/{runtime-MFFcJrRv.js.map → runtime-DslE1aBw.js.map} +1 -1
- package/searxng-Bkrwhwhw.js +269 -0
- package/searxng-Bkrwhwhw.js.map +1 -0
- package/searxng-CyA-nEu5.mjs +257 -0
- package/searxng-CyA-nEu5.mjs.map +1 -0
- package/skills/adk-assembly/SKILL.md +2 -2
- package/{spooled_artifact-CHoZgWwI.mjs → spooled_artifact-7eePq7JA.mjs} +5 -5
- package/{spooled_artifact-CHoZgWwI.mjs.map → spooled_artifact-7eePq7JA.mjs.map} +1 -1
- package/{spooled_artifact-BTq6Nzfy.js → spooled_artifact-DX8LLyUX.js} +5 -5
- package/{spooled_artifact-BTq6Nzfy.js.map → spooled_artifact-DX8LLyUX.js.map} +1 -1
- package/spooled_artifact.cjs +2 -2
- package/spooled_artifact.mjs +2 -2
- package/{spooled_markdown_artifact-CALSDxIx.js → spooled_markdown_artifact-ClX72lek.js} +4 -4
- package/spooled_markdown_artifact-ClX72lek.js.map +1 -0
- package/{spooled_markdown_artifact-Ci5UL7l4.mjs → spooled_markdown_artifact-wkrBF3oX.mjs} +4 -4
- package/spooled_markdown_artifact-wkrBF3oX.mjs.map +1 -0
- package/{thought-D34QQZZ9.mjs → thought-B_vxAiKU.mjs} +5 -5
- package/{thought-D34QQZZ9.mjs.map → thought-B_vxAiKU.mjs.map} +1 -1
- package/{thought-BbwhJ1wb.js → thought-DLwpF7MI.js} +5 -5
- package/{thought-BbwhJ1wb.js.map → thought-DLwpF7MI.js.map} +1 -1
- package/{tool-CVyZkFC7.js → tool-D5WGVIcI.js} +4 -4
- package/{tool-CVyZkFC7.js.map → tool-D5WGVIcI.js.map} +1 -1
- package/{tool-CMhaDRNd.mjs → tool-wMYMVl60.mjs} +4 -4
- package/{tool-CMhaDRNd.mjs.map → tool-wMYMVl60.mjs.map} +1 -1
- package/{tool_call-CV5qVNlb.mjs → tool_call-B4-_-vjG.mjs} +5 -5
- package/tool_call-B4-_-vjG.mjs.map +1 -0
- package/{tool_call-Db68hB7y.js → tool_call-DixVlW40.js} +5 -5
- package/tool_call-DixVlW40.js.map +1 -0
- package/{tool_registry-D1pSSlsd.mjs → tool_registry-791Vrjtf.mjs} +4 -3
- package/tool_registry-791Vrjtf.mjs.map +1 -0
- package/{tool_registry-DYUYqXvo.js → tool_registry-CKJPze3j.js} +4 -3
- package/tool_registry-CKJPze3j.js.map +1 -0
- package/{turn_runner-DqWHNP80.js → turn_runner-HXImLGIn.js} +7 -7
- package/turn_runner-HXImLGIn.js.map +1 -0
- package/{turn_runner-fg1Wc3dK.mjs → turn_runner-ZyYO-Kti.mjs} +7 -7
- package/turn_runner-ZyYO-Kti.mjs.map +1 -0
- package/turn_runner.cjs +1 -1
- package/turn_runner.mjs +1 -1
- package/types.d.ts +1 -1
- package/common-BT0nfCi9.mjs.map +0 -1
- package/common-Cj8TaQ9U.js.map +0 -1
- package/exceptions-BeWH2FwP.mjs.map +0 -1
- package/exceptions-CitH5wZI.js.map +0 -1
- package/spooled_markdown_artifact-CALSDxIx.js.map +0 -1
- package/spooled_markdown_artifact-Ci5UL7l4.mjs.map +0 -1
- package/tool_call-CV5qVNlb.mjs.map +0 -1
- package/tool_call-Db68hB7y.js.map +0 -1
- package/tool_registry-D1pSSlsd.mjs.map +0 -1
- package/tool_registry-DYUYqXvo.js.map +0 -1
- package/turn_runner-DqWHNP80.js.map +0 -1
- package/turn_runner-fg1Wc3dK.mjs.map +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { c as isObject, o as isError } from "../../tool_registry-
|
|
2
|
-
import { t as Tool } from "../../tool-
|
|
3
|
-
import "../../common-
|
|
1
|
+
import { c as isObject, o as isError } from "../../tool_registry-791Vrjtf.mjs";
|
|
2
|
+
import { t as Tool } from "../../tool-wMYMVl60.mjs";
|
|
3
|
+
import "../../common-DYDUi99O.mjs";
|
|
4
4
|
import "../../guards.mjs";
|
|
5
|
+
import { bigMean, bigSum, bigToNumber, formatBig } from "../../lib/helpers/bignum.mjs";
|
|
5
6
|
import { validator } from "@nhtio/validation";
|
|
6
7
|
//#region src/batteries/tools/data_structure/index.ts
|
|
7
8
|
/**
|
|
@@ -13,6 +14,18 @@ import { validator } from "@nhtio/validation";
|
|
|
13
14
|
* Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole
|
|
14
15
|
* category, or import every tool via `@nhtio/adk/batteries`.
|
|
15
16
|
*/
|
|
17
|
+
/**
|
|
18
|
+
* Render a {@link BigNumber} aggregate as a JSON-friendly value: a plain `number` when the result
|
|
19
|
+
* is exactly representable as a float64 (|x| ≤ Number.MAX_SAFE_INTEGER, so existing consumers and
|
|
20
|
+
* tests see a number with no precision loss), or a full-precision string otherwise — covering both
|
|
21
|
+
* overflow (which `JSON.stringify` would turn into `null`) and the gap above 2^53 where float64
|
|
22
|
+
* silently rounds (e.g. 3 × MAX_SAFE_INTEGER).
|
|
23
|
+
*/
|
|
24
|
+
function aggregateValue(big) {
|
|
25
|
+
const asNum = bigToNumber(big);
|
|
26
|
+
if (Number.isFinite(asNum) && Math.abs(asNum) <= Number.MAX_SAFE_INTEGER) return asNum;
|
|
27
|
+
return formatBig(big, 16);
|
|
28
|
+
}
|
|
16
29
|
function getPath(obj, path) {
|
|
17
30
|
const parts = path.split(".");
|
|
18
31
|
let current = obj;
|
|
@@ -51,6 +64,7 @@ function applyTemplate(template, item) {
|
|
|
51
64
|
});
|
|
52
65
|
}
|
|
53
66
|
function applyOperation(data, op) {
|
|
67
|
+
if (op === null || typeof op !== "object" || typeof op.op !== "string") throw new Error("Each operation must be an object with a string \"op\" field.");
|
|
54
68
|
if (op.op === "count") {
|
|
55
69
|
if (Array.isArray(data)) return data.length;
|
|
56
70
|
if (isObject(data)) return Object.keys(data).length;
|
|
@@ -92,7 +106,8 @@ function applyOperation(data, op) {
|
|
|
92
106
|
case "unique_by": {
|
|
93
107
|
const seen = /* @__PURE__ */ new Set();
|
|
94
108
|
return arr.filter((item) => {
|
|
95
|
-
const
|
|
109
|
+
const raw = getPath(item, op.key);
|
|
110
|
+
const key = typeof raw === "object" && raw !== null ? JSON.stringify(raw) : `${typeof raw}:${String(raw)}`;
|
|
96
111
|
if (seen.has(key)) return false;
|
|
97
112
|
seen.add(key);
|
|
98
113
|
return true;
|
|
@@ -109,14 +124,18 @@ function applyOperation(data, op) {
|
|
|
109
124
|
}
|
|
110
125
|
case "flatten": return arr.flat(op.depth ?? 1);
|
|
111
126
|
case "reverse": return [...arr].reverse();
|
|
112
|
-
case "sum":
|
|
127
|
+
case "sum": {
|
|
128
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
129
|
+
if (nums.length === 0 && arr.length > 0) throw new Error(op.key ? `No numeric values found at key "${op.key}".` : "No numeric values to sum. For an array of objects, pass a \"key\".");
|
|
130
|
+
return aggregateValue(bigSum(nums));
|
|
131
|
+
}
|
|
113
132
|
case "avg": {
|
|
114
|
-
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number");
|
|
133
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
115
134
|
if (nums.length === 0) return null;
|
|
116
|
-
return
|
|
135
|
+
return aggregateValue(bigMean(nums));
|
|
117
136
|
}
|
|
118
137
|
case "median": {
|
|
119
|
-
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number");
|
|
138
|
+
const nums = (op.key ? arr.map((i) => getPath(i, op.key)) : arr).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
120
139
|
if (nums.length === 0) return null;
|
|
121
140
|
return medianOf(nums);
|
|
122
141
|
}
|
|
@@ -147,7 +166,7 @@ function applyOperation(data, op) {
|
|
|
147
166
|
return freq;
|
|
148
167
|
}
|
|
149
168
|
case "top_n": {
|
|
150
|
-
const dir = op.direction === "asc" ? 1 :
|
|
169
|
+
const dir = op.direction === "asc" ? -1 : 1;
|
|
151
170
|
return [...arr].sort((a, b) => {
|
|
152
171
|
const av = getPath(a, op.key);
|
|
153
172
|
const bv = getPath(b, op.key);
|
|
@@ -188,7 +207,8 @@ var jsonTransformTool = new Tool({
|
|
|
188
207
|
for (const [i, operation] of operations.entries()) try {
|
|
189
208
|
current = applyOperation(current, operation);
|
|
190
209
|
} catch (err) {
|
|
191
|
-
|
|
210
|
+
const opName = operation && typeof operation === "object" && "op" in operation ? String(operation.op) : String(operation);
|
|
211
|
+
return `Error in operation ${i + 1} ("${opName}"): ${isError(err) ? err.message : String(err)}`;
|
|
192
212
|
}
|
|
193
213
|
if (typeof current === "string") return current;
|
|
194
214
|
return JSON.stringify(current, null, 2);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data_structure.mjs","names":[],"sources":["../../../src/batteries/tools/data_structure/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for querying, filtering, grouping, and reshaping structured values.\n *\n * @module @nhtio/adk/batteries/tools/data_structure\n *\n * @remarks\n * Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { validator } from '@nhtio/validation'\nimport { isError, isObject } from '@nhtio/adk/guards'\n\nfunction getPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current = obj\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\ntype FilterOperator =\n | 'eq'\n | 'ne'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains'\n | 'starts_with'\n | 'ends_with'\n | 'exists'\n\nfunction matchesFilter(\n item: unknown,\n key: string,\n operator: FilterOperator,\n value: unknown\n): boolean {\n const actual = getPath(item, key)\n switch (operator) {\n case 'eq':\n return actual === value\n case 'ne':\n return actual !== value\n case 'gt':\n return typeof actual === 'number' && actual > (value as number)\n case 'gte':\n return typeof actual === 'number' && actual >= (value as number)\n case 'lt':\n return typeof actual === 'number' && actual < (value as number)\n case 'lte':\n return typeof actual === 'number' && actual <= (value as number)\n case 'contains':\n return typeof actual === 'string' && actual.includes(String(value))\n case 'starts_with':\n return typeof actual === 'string' && actual.startsWith(String(value))\n case 'ends_with':\n return typeof actual === 'string' && actual.endsWith(String(value))\n case 'exists':\n return actual !== undefined && actual !== null\n default:\n return false\n }\n}\n\nfunction medianOf(nums: number[]): number {\n const sorted = [...nums].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]\n}\n\nfunction applyTemplate(template: string, item: unknown): string {\n if (typeof item !== 'object' || item === null) return String(item)\n return template.replace(/\\{\\{([^}]+)\\}\\}/g, (_, key) => {\n const val = getPath(item, key.trim())\n return val === undefined || val === null ? '' : String(val)\n })\n}\n\ntype Operation =\n | { op: 'filter'; key: string; operator: FilterOperator; value?: unknown }\n | { op: 'sort'; key: string; direction?: 'asc' | 'desc' }\n | { op: 'select_keys'; keys: string[] }\n | { op: 'pluck'; key: string }\n | { op: 'slice'; start: number; end?: number }\n | { op: 'unique' }\n | { op: 'unique_by'; key: string }\n | { op: 'group_by'; key: string }\n | { op: 'flatten'; depth?: number }\n | { op: 'reverse' }\n | { op: 'count' }\n | { op: 'sum'; key?: string }\n | { op: 'avg'; key?: string }\n | { op: 'median'; key?: string }\n | { op: 'min'; key?: string }\n | { op: 'max'; key?: string }\n | { op: 'first'; n?: number }\n | { op: 'last'; n?: number }\n | { op: 'chunk'; size: number }\n | { op: 'frequency_count'; key?: string }\n | { op: 'top_n'; n: number; key: string; direction?: 'asc' | 'desc' }\n | { op: 'map_template'; template: string }\n\nfunction applyOperation(data: unknown, op: Operation): unknown {\n if (op.op === 'count') {\n if (Array.isArray(data)) return data.length\n if (isObject(data)) return Object.keys(data).length\n return 0\n }\n\n if (!Array.isArray(data)) {\n throw new Error(`Operation \"${op.op}\" requires an array input.`)\n }\n\n const arr = data as unknown[]\n\n switch (op.op) {\n case 'filter':\n return arr.filter((item) => matchesFilter(item, op.key, op.operator, op.value))\n\n case 'sort': {\n const dir = op.direction === 'desc' ? -1 : 1\n return [...arr].sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (av === bv) return 0\n if (av === undefined || av === null) return 1\n if (bv === undefined || bv === null) return -1\n if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * dir\n return String(av).localeCompare(String(bv)) * dir\n })\n }\n\n case 'select_keys':\n return arr.map((item) => {\n if (typeof item !== 'object' || item === null) return item\n const result: Record<string, unknown> = {}\n for (const key of op.keys) result[key] = (item as Record<string, unknown>)[key]\n return result\n })\n\n case 'pluck':\n return arr.map((item) => getPath(item, op.key))\n\n case 'slice':\n return arr.slice(op.start, op.end)\n\n case 'unique': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = typeof item === 'object' ? JSON.stringify(item) : String(item)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'unique_by': {\n const seen = new Set<unknown>()\n return arr.filter((item) => {\n const key = getPath(item, op.key)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'group_by': {\n const groups: Record<string, unknown[]> = {}\n for (const item of arr) {\n const key = String(getPath(item, op.key) ?? '__undefined__')\n if (!groups[key]) groups[key] = []\n groups[key].push(item)\n }\n return groups\n }\n\n case 'flatten':\n return arr.flat(op.depth ?? 1)\n\n case 'reverse':\n return [...arr].reverse()\n\n case 'sum': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n return values.reduce<number>((acc, v) => acc + (typeof v === 'number' ? v : 0), 0)\n }\n\n case 'avg': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return nums.reduce((a, b) => a + b, 0) / nums.length\n }\n\n case 'median': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return medianOf(nums)\n }\n\n case 'min': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.min(...nums)\n }\n\n case 'max': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.max(...nums)\n }\n\n case 'first':\n return op.n !== undefined ? arr.slice(0, op.n) : arr[0]\n\n case 'last':\n return op.n !== undefined ? arr.slice(-op.n) : arr[arr.length - 1]\n\n case 'chunk': {\n const size = Math.max(1, Math.floor(op.size))\n const chunks: unknown[][] = []\n for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size))\n return chunks\n }\n\n case 'frequency_count': {\n const freq: Record<string, number> = {}\n for (const item of arr) {\n const key = op.key ? String(getPath(item, op.key) ?? '__undefined__') : String(item)\n freq[key] = (freq[key] ?? 0) + 1\n }\n return freq\n }\n\n case 'top_n': {\n const dir = op.direction === 'asc' ? 1 : -1\n return [...arr]\n .sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (typeof av === 'number' && typeof bv === 'number') return (bv - av) * dir\n return String(bv).localeCompare(String(av)) * dir\n })\n .slice(0, op.n)\n }\n\n case 'map_template':\n return arr.map((item) => applyTemplate(op.template, item))\n\n default:\n throw new Error(`Unknown operation: ${(op as { op: string }).op}`)\n }\n}\n\n/**\n * Apply a pipeline of operations to a JSON array or object.\n *\n * @remarks\n * Operations are applied in order; each step transforms the output of the previous. Supported\n * operations: `filter`, `sort`, `select_keys`, `pluck`, `slice`, `unique`, `unique_by`,\n * `group_by`, `flatten`, `reverse`, `count`, `sum`, `avg`, `median`, `min`, `max`, `first`,\n * `last`, `chunk`, `frequency_count`, `top_n`, `map_template`. Dot-notation paths are supported\n * for nested key access in every operation that takes a `key` field.\n */\nexport const jsonTransformTool = new Tool({\n name: 'json_transform',\n description:\n 'Apply a pipeline of operations to a JSON array or object: filter, sort, group, aggregate (sum/avg/median/min/max), pluck fields, deduplicate, flatten, chunk, frequency count, top-N, and more.',\n inputSchema: validator.object({\n data: validator.string().required().description('JSON data as a string (array or object)'),\n operations: validator\n .array()\n .items(validator.object().unknown(true))\n .required()\n .description(\n 'Pipeline of operations to apply in order. Each step transforms the output of the previous.'\n ),\n }),\n handler: async (args) => {\n const { data: dataStr, operations } = args as {\n data: string\n operations: Operation[]\n }\n\n let data: unknown\n try {\n data = JSON.parse(dataStr)\n } catch {\n return 'Error: Invalid JSON input.'\n }\n\n let current: unknown = data\n\n for (const [i, operation] of operations.entries()) {\n try {\n current = applyOperation(current, operation)\n } catch (err) {\n return `Error in operation ${i + 1} (\"${operation.op}\"): ${isError(err) ? err.message : String(err)}`\n }\n }\n\n if (typeof current === 'string') return current\n return JSON.stringify(current, null, 2)\n },\n})\n\n/**\n * Perform set operations on two JSON arrays.\n *\n * @remarks\n * Supported operations: `intersection`, `union`, `difference`, `symmetric_difference`,\n * `is_member`, `is_subset`, `is_superset`. For arrays of objects, an optional `compare_key`\n * narrows equality to a single property rather than deep structural comparison.\n */\nexport const setOperationsTool = new Tool({\n name: 'set_operations',\n description:\n 'Perform set operations on two JSON arrays: intersection (common elements), union (all elements), difference (in A but not B), symmetric difference, or membership check.',\n inputSchema: validator.object({\n data_a: validator.string().required().description('First JSON array'),\n data_b: validator.string().optional().description('Second JSON array'),\n operation: validator\n .string()\n .valid(\n 'intersection',\n 'union',\n 'difference',\n 'symmetric_difference',\n 'is_member',\n 'is_subset',\n 'is_superset'\n )\n .required()\n .description('Set operation to perform'),\n item: validator.any().optional().description('For is_member: the value to look up in data_a.'),\n compare_key: validator\n .string()\n .optional()\n .description(\n 'For arrays of objects: use this key for equality comparison instead of deep equality.'\n ),\n }),\n handler: async (args) => {\n const {\n data_a: dataA,\n data_b: dataB,\n operation,\n item,\n compare_key: compareKey,\n } = args as {\n data_a: string\n data_b?: string\n operation: string\n item?: unknown\n compare_key?: string\n }\n\n let a: unknown[]\n let b: unknown[] = []\n\n try {\n a = JSON.parse(dataA)\n } catch {\n return 'Error: data_a is not valid JSON.'\n }\n if (!Array.isArray(a)) return 'Error: data_a must be a JSON array.'\n\n if (dataB !== undefined) {\n try {\n b = JSON.parse(dataB)\n } catch {\n return 'Error: data_b is not valid JSON.'\n }\n if (!Array.isArray(b)) return 'Error: data_b must be a JSON array.'\n }\n\n const toKey = (val: unknown): string =>\n compareKey && isObject(val)\n ? String((val as Record<string, unknown>)[compareKey])\n : JSON.stringify(val)\n\n if (operation === 'is_member') {\n const needle = JSON.stringify(item)\n const found = a.some((entry) => JSON.stringify(entry) === needle)\n return found ? `Found: item is in the array.` : `Not found: item is not in the array.`\n }\n\n const setA = new Set(a.map(toKey))\n const setB = new Set(b.map(toKey))\n const indexA = new Map(a.map((entry) => [toKey(entry), entry]))\n\n switch (operation) {\n case 'intersection': {\n const result = [...setA].filter((k) => setB.has(k)).map((k) => indexA.get(k))\n return JSON.stringify(result, null, 2)\n }\n case 'union': {\n const result = [...a, ...b.filter((entry) => !setA.has(toKey(entry)))]\n return JSON.stringify(result, null, 2)\n }\n case 'difference': {\n const result = a.filter((entry) => !setB.has(toKey(entry)))\n return JSON.stringify(result, null, 2)\n }\n case 'symmetric_difference': {\n const result = [\n ...a.filter((entry) => !setB.has(toKey(entry))),\n ...b.filter((entry) => !setA.has(toKey(entry))),\n ]\n return JSON.stringify(result, null, 2)\n }\n case 'is_subset':\n return [...setA].every((k) => setB.has(k))\n ? `Yes: A is a subset of B (all ${a.length} elements of A are in B).`\n : `No: A is not a subset of B.`\n case 'is_superset':\n return [...setB].every((k) => setA.has(k))\n ? `Yes: A is a superset of B (A contains all ${b.length} elements of B).`\n : `No: A is not a superset of B.`\n default:\n return `Error: Unknown operation \"${operation}\".`\n }\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data_structure.mjs","names":[],"sources":["../../../src/batteries/tools/data_structure/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for querying, filtering, grouping, and reshaping structured values.\n *\n * @module @nhtio/adk/batteries/tools/data_structure\n *\n * @remarks\n * Pre-constructed bundled tools for the `data_structure` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { validator } from '@nhtio/validation'\nimport { isError, isObject } from '@nhtio/adk/guards'\nimport { bigSum, bigMean, formatBig, bigToNumber } from '@nhtio/adk/lib/helpers/bignum'\nimport type { BigNumber } from 'mathjs'\n\n/**\n * Render a {@link BigNumber} aggregate as a JSON-friendly value: a plain `number` when the result\n * is exactly representable as a float64 (|x| ≤ Number.MAX_SAFE_INTEGER, so existing consumers and\n * tests see a number with no precision loss), or a full-precision string otherwise — covering both\n * overflow (which `JSON.stringify` would turn into `null`) and the gap above 2^53 where float64\n * silently rounds (e.g. 3 × MAX_SAFE_INTEGER).\n */\nfunction aggregateValue(big: BigNumber): number | string {\n const asNum = bigToNumber(big)\n if (Number.isFinite(asNum) && Math.abs(asNum) <= Number.MAX_SAFE_INTEGER) return asNum\n return formatBig(big, 16)\n}\n\nfunction getPath(obj: unknown, path: string): unknown {\n const parts = path.split('.')\n let current = obj\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\ntype FilterOperator =\n | 'eq'\n | 'ne'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains'\n | 'starts_with'\n | 'ends_with'\n | 'exists'\n\nfunction matchesFilter(\n item: unknown,\n key: string,\n operator: FilterOperator,\n value: unknown\n): boolean {\n const actual = getPath(item, key)\n switch (operator) {\n case 'eq':\n return actual === value\n case 'ne':\n return actual !== value\n case 'gt':\n return typeof actual === 'number' && actual > (value as number)\n case 'gte':\n return typeof actual === 'number' && actual >= (value as number)\n case 'lt':\n return typeof actual === 'number' && actual < (value as number)\n case 'lte':\n return typeof actual === 'number' && actual <= (value as number)\n case 'contains':\n return typeof actual === 'string' && actual.includes(String(value))\n case 'starts_with':\n return typeof actual === 'string' && actual.startsWith(String(value))\n case 'ends_with':\n return typeof actual === 'string' && actual.endsWith(String(value))\n case 'exists':\n return actual !== undefined && actual !== null\n default:\n return false\n }\n}\n\nfunction medianOf(nums: number[]): number {\n const sorted = [...nums].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]\n}\n\nfunction applyTemplate(template: string, item: unknown): string {\n if (typeof item !== 'object' || item === null) return String(item)\n return template.replace(/\\{\\{([^}]+)\\}\\}/g, (_, key) => {\n const val = getPath(item, key.trim())\n return val === undefined || val === null ? '' : String(val)\n })\n}\n\ntype Operation =\n | { op: 'filter'; key: string; operator: FilterOperator; value?: unknown }\n | { op: 'sort'; key: string; direction?: 'asc' | 'desc' }\n | { op: 'select_keys'; keys: string[] }\n | { op: 'pluck'; key: string }\n | { op: 'slice'; start: number; end?: number }\n | { op: 'unique' }\n | { op: 'unique_by'; key: string }\n | { op: 'group_by'; key: string }\n | { op: 'flatten'; depth?: number }\n | { op: 'reverse' }\n | { op: 'count' }\n | { op: 'sum'; key?: string }\n | { op: 'avg'; key?: string }\n | { op: 'median'; key?: string }\n | { op: 'min'; key?: string }\n | { op: 'max'; key?: string }\n | { op: 'first'; n?: number }\n | { op: 'last'; n?: number }\n | { op: 'chunk'; size: number }\n | { op: 'frequency_count'; key?: string }\n | { op: 'top_n'; n: number; key: string; direction?: 'asc' | 'desc' }\n | { op: 'map_template'; template: string }\n\nfunction applyOperation(data: unknown, op: Operation): unknown {\n // Guard malformed pipeline entries (null, non-object, or missing `op`) so they produce a clear\n // error string rather than a TypeError from dereferencing `op.op`.\n if (op === null || typeof op !== 'object' || typeof (op as { op?: unknown }).op !== 'string') {\n throw new Error('Each operation must be an object with a string \"op\" field.')\n }\n\n if (op.op === 'count') {\n if (Array.isArray(data)) return data.length\n if (isObject(data)) return Object.keys(data).length\n return 0\n }\n\n if (!Array.isArray(data)) {\n throw new Error(`Operation \"${op.op}\" requires an array input.`)\n }\n\n const arr = data as unknown[]\n\n switch (op.op) {\n case 'filter':\n return arr.filter((item) => matchesFilter(item, op.key, op.operator, op.value))\n\n case 'sort': {\n const dir = op.direction === 'desc' ? -1 : 1\n return [...arr].sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (av === bv) return 0\n if (av === undefined || av === null) return 1\n if (bv === undefined || bv === null) return -1\n if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * dir\n return String(av).localeCompare(String(bv)) * dir\n })\n }\n\n case 'select_keys':\n return arr.map((item) => {\n if (typeof item !== 'object' || item === null) return item\n const result: Record<string, unknown> = {}\n for (const key of op.keys) result[key] = (item as Record<string, unknown>)[key]\n return result\n })\n\n case 'pluck':\n return arr.map((item) => getPath(item, op.key))\n\n case 'slice':\n return arr.slice(op.start, op.end)\n\n case 'unique': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const key = typeof item === 'object' ? JSON.stringify(item) : String(item)\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'unique_by': {\n const seen = new Set<string>()\n return arr.filter((item) => {\n const raw = getPath(item, op.key)\n // Serialise the key value so deep-equal objects/arrays dedupe by VALUE, not reference —\n // JSON.parse produces a distinct reference per row, so a raw Set never matched them. This\n // must catch BOTH plain objects and arrays, so a raw `typeof === 'object'` is intended here\n // rather than the plain-object-only `isObject` guard.\n // eslint-disable-next-line adk/prefer-is-object\n const isObjectOrArray = typeof raw === 'object' && raw !== null\n const key = isObjectOrArray ? JSON.stringify(raw) : `${typeof raw}:${String(raw)}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n }\n\n case 'group_by': {\n const groups: Record<string, unknown[]> = {}\n for (const item of arr) {\n const key = String(getPath(item, op.key) ?? '__undefined__')\n if (!groups[key]) groups[key] = []\n groups[key].push(item)\n }\n return groups\n }\n\n case 'flatten':\n return arr.flat(op.depth ?? 1)\n\n case 'reverse':\n return [...arr].reverse()\n\n case 'sum': {\n // The total is accumulated in BigNumber so a sum exceeding float64 stays exact (returned as\n // a precise string) instead of silently becoming Infinity → JSON null.\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n // A non-empty input with no numeric values is almost always a mistake (e.g. an array of\n // objects summed without a `key`). Returning 0 would be silently wrong, so error instead.\n if (nums.length === 0 && arr.length > 0) {\n throw new Error(\n op.key\n ? `No numeric values found at key \"${op.key}\".`\n : 'No numeric values to sum. For an array of objects, pass a \"key\".'\n )\n }\n return aggregateValue(bigSum(nums))\n }\n\n case 'avg': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n // null (not 0) signals \"no numeric data\" — unlike sum, an average has no neutral element,\n // so null is an honest \"no result\" rather than a misleading number.\n if (nums.length === 0) return null\n return aggregateValue(bigMean(nums))\n }\n\n case 'median': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n if (nums.length === 0) return null\n return medianOf(nums)\n }\n\n case 'min': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.min(...nums)\n }\n\n case 'max': {\n const values = op.key ? arr.map((i) => getPath(i, op.key!)) : arr\n const nums = values.filter((v): v is number => typeof v === 'number')\n if (nums.length === 0) return null\n return Math.max(...nums)\n }\n\n case 'first':\n return op.n !== undefined ? arr.slice(0, op.n) : arr[0]\n\n case 'last':\n return op.n !== undefined ? arr.slice(-op.n) : arr[arr.length - 1]\n\n case 'chunk': {\n const size = Math.max(1, Math.floor(op.size))\n const chunks: unknown[][] = []\n for (let i = 0; i < arr.length; i += size) chunks.push(arr.slice(i, i + size))\n return chunks\n }\n\n case 'frequency_count': {\n const freq: Record<string, number> = {}\n for (const item of arr) {\n const key = op.key ? String(getPath(item, op.key) ?? '__undefined__') : String(item)\n freq[key] = (freq[key] ?? 0) + 1\n }\n return freq\n }\n\n case 'top_n': {\n // desc (default) ranks largest-first; asc ranks smallest-first. The base comparator\n // `(bv - av)` / `localeCompare(bv, av)` is descending, so asc flips it.\n const dir = op.direction === 'asc' ? -1 : 1\n return [...arr]\n .sort((a, b) => {\n const av = getPath(a, op.key)\n const bv = getPath(b, op.key)\n if (typeof av === 'number' && typeof bv === 'number') return (bv - av) * dir\n return String(bv).localeCompare(String(av)) * dir\n })\n .slice(0, op.n)\n }\n\n case 'map_template':\n return arr.map((item) => applyTemplate(op.template, item))\n\n default:\n throw new Error(`Unknown operation: ${(op as { op: string }).op}`)\n }\n}\n\n/**\n * Apply a pipeline of operations to a JSON array or object.\n *\n * @remarks\n * Operations are applied in order; each step transforms the output of the previous. Supported\n * operations: `filter`, `sort`, `select_keys`, `pluck`, `slice`, `unique`, `unique_by`,\n * `group_by`, `flatten`, `reverse`, `count`, `sum`, `avg`, `median`, `min`, `max`, `first`,\n * `last`, `chunk`, `frequency_count`, `top_n`, `map_template`. Dot-notation paths are supported\n * for nested key access in every operation that takes a `key` field.\n */\nexport const jsonTransformTool = new Tool({\n name: 'json_transform',\n description:\n 'Apply a pipeline of operations to a JSON array or object: filter, sort, group, aggregate (sum/avg/median/min/max), pluck fields, deduplicate, flatten, chunk, frequency count, top-N, and more.',\n inputSchema: validator.object({\n data: validator.string().required().description('JSON data as a string (array or object)'),\n operations: validator\n .array()\n .items(validator.object().unknown(true))\n .required()\n .description(\n 'Pipeline of operations to apply in order. Each step transforms the output of the previous.'\n ),\n }),\n handler: async (args) => {\n const { data: dataStr, operations } = args as {\n data: string\n operations: Operation[]\n }\n\n let data: unknown\n try {\n data = JSON.parse(dataStr)\n } catch {\n return 'Error: Invalid JSON input.'\n }\n\n let current: unknown = data\n\n for (const [i, operation] of operations.entries()) {\n try {\n current = applyOperation(current, operation)\n } catch (err) {\n const opName =\n operation && typeof operation === 'object' && 'op' in operation\n ? String((operation as { op: unknown }).op)\n : String(operation)\n return `Error in operation ${i + 1} (\"${opName}\"): ${isError(err) ? err.message : String(err)}`\n }\n }\n\n if (typeof current === 'string') return current\n return JSON.stringify(current, null, 2)\n },\n})\n\n/**\n * Perform set operations on two JSON arrays.\n *\n * @remarks\n * Supported operations: `intersection`, `union`, `difference`, `symmetric_difference`,\n * `is_member`, `is_subset`, `is_superset`. For arrays of objects, an optional `compare_key`\n * narrows equality to a single property rather than deep structural comparison.\n */\nexport const setOperationsTool = new Tool({\n name: 'set_operations',\n description:\n 'Perform set operations on two JSON arrays: intersection (common elements), union (all elements), difference (in A but not B), symmetric difference, or membership check.',\n inputSchema: validator.object({\n data_a: validator.string().required().description('First JSON array'),\n data_b: validator.string().optional().description('Second JSON array'),\n operation: validator\n .string()\n .valid(\n 'intersection',\n 'union',\n 'difference',\n 'symmetric_difference',\n 'is_member',\n 'is_subset',\n 'is_superset'\n )\n .required()\n .description('Set operation to perform'),\n item: validator.any().optional().description('For is_member: the value to look up in data_a.'),\n compare_key: validator\n .string()\n .optional()\n .description(\n 'For arrays of objects: use this key for equality comparison instead of deep equality.'\n ),\n }),\n handler: async (args) => {\n const {\n data_a: dataA,\n data_b: dataB,\n operation,\n item,\n compare_key: compareKey,\n } = args as {\n data_a: string\n data_b?: string\n operation: string\n item?: unknown\n compare_key?: string\n }\n\n let a: unknown[]\n let b: unknown[] = []\n\n try {\n a = JSON.parse(dataA)\n } catch {\n return 'Error: data_a is not valid JSON.'\n }\n if (!Array.isArray(a)) return 'Error: data_a must be a JSON array.'\n\n if (dataB !== undefined) {\n try {\n b = JSON.parse(dataB)\n } catch {\n return 'Error: data_b is not valid JSON.'\n }\n if (!Array.isArray(b)) return 'Error: data_b must be a JSON array.'\n }\n\n const toKey = (val: unknown): string =>\n compareKey && isObject(val)\n ? String((val as Record<string, unknown>)[compareKey])\n : JSON.stringify(val)\n\n if (operation === 'is_member') {\n const needle = JSON.stringify(item)\n const found = a.some((entry) => JSON.stringify(entry) === needle)\n return found ? `Found: item is in the array.` : `Not found: item is not in the array.`\n }\n\n const setA = new Set(a.map(toKey))\n const setB = new Set(b.map(toKey))\n const indexA = new Map(a.map((entry) => [toKey(entry), entry]))\n\n switch (operation) {\n case 'intersection': {\n const result = [...setA].filter((k) => setB.has(k)).map((k) => indexA.get(k))\n return JSON.stringify(result, null, 2)\n }\n case 'union': {\n const result = [...a, ...b.filter((entry) => !setA.has(toKey(entry)))]\n return JSON.stringify(result, null, 2)\n }\n case 'difference': {\n const result = a.filter((entry) => !setB.has(toKey(entry)))\n return JSON.stringify(result, null, 2)\n }\n case 'symmetric_difference': {\n const result = [\n ...a.filter((entry) => !setB.has(toKey(entry))),\n ...b.filter((entry) => !setA.has(toKey(entry))),\n ]\n return JSON.stringify(result, null, 2)\n }\n case 'is_subset':\n return [...setA].every((k) => setB.has(k))\n ? `Yes: A is a subset of B (all ${a.length} elements of A are in B).`\n : `No: A is not a subset of B.`\n case 'is_superset':\n return [...setB].every((k) => setA.has(k))\n ? `Yes: A is a superset of B (A contains all ${b.length} elements of B).`\n : `No: A is not a superset of B.`\n default:\n return `Error: Unknown operation \"${operation}\".`\n }\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Ble4zEEl.js");
|
|
3
|
-
const require_tool = require("../../tool-
|
|
4
|
-
require("../../common-
|
|
3
|
+
const require_tool = require("../../tool-D5WGVIcI.js");
|
|
4
|
+
require("../../common-DZl3ADJs.js");
|
|
5
5
|
let _nhtio_validation = require("@nhtio/validation");
|
|
6
6
|
let luxon = require("luxon");
|
|
7
7
|
let chrono_node = require("chrono-node");
|
|
@@ -235,14 +235,9 @@ var datePeriodTool = new require_tool.Tool({
|
|
|
235
235
|
result = boundary === "start" ? dt.startOf("month") : dt.endOf("month");
|
|
236
236
|
break;
|
|
237
237
|
case "quarter": {
|
|
238
|
-
const
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
month: qStartMonth,
|
|
242
|
-
day: 1
|
|
243
|
-
}).startOf("day");
|
|
244
|
-
const adjusted = qStart > dt ? qStart.minus({ months: 3 }) : qStart;
|
|
245
|
-
result = boundary === "start" ? adjusted : adjusted.plus({ months: 3 }).minus({ days: 1 }).endOf("day");
|
|
238
|
+
const monthsIntoQuarter = (dt.month - fyStart + 12) % 12 % 3;
|
|
239
|
+
const qStart = dt.startOf("month").minus({ months: monthsIntoQuarter });
|
|
240
|
+
result = boundary === "start" ? qStart : qStart.plus({ months: 3 }).minus({ days: 1 }).endOf("day");
|
|
246
241
|
break;
|
|
247
242
|
}
|
|
248
243
|
case "year":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datetime_extended.cjs","names":[],"sources":["../../../src/batteries/tools/datetime_extended/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for parsing natural-language dates and business-calendar calculations.\n *\n * @module @nhtio/adk/batteries/tools/datetime_extended\n *\n * @remarks\n * Pre-constructed bundled tools for the `datetime_extended` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport * as chrono from 'chrono-node'\nimport { Tool } from '@nhtio/adk/common'\nimport { DateTime, IANAZone } from 'luxon'\nimport { validator } from '@nhtio/validation'\n\nfunction resolveZone(timezone: string | undefined): { zone: string; error?: string } {\n if (!timezone) return { zone: 'UTC' }\n if (!IANAZone.isValidZone(timezone)) return { zone: '', error: `Invalid timezone \"${timezone}\".` }\n return { zone: timezone }\n}\n\nfunction countBusinessDays(from: DateTime, to: DateTime): number {\n const forward = to >= from\n const start = forward ? from.startOf('day') : to.startOf('day')\n const end = forward ? to.startOf('day') : from.startOf('day')\n\n const totalDays = Math.round(end.diff(start, 'days').days)\n const fullWeeks = Math.floor(totalDays / 7)\n let bdays = fullWeeks * 5\n\n let cursor = start.plus({ days: fullWeeks * 7 })\n while (cursor < end) {\n cursor = cursor.plus({ days: 1 })\n if (cursor.weekday <= 5) bdays++\n }\n\n return forward ? bdays : -bdays\n}\n\n/**\n * Find the Nth occurrence of a weekday in a given month.\n *\n * @remarks\n * Examples: \"2nd Friday of March 2026\", \"last Monday of January 2025\". Accepts 1st–5th and\n * `last`. Returns an error if the month does not contain that many occurrences of the weekday.\n */\nexport const dateNthWeekdayTool = new Tool({\n name: 'date_nth_weekday',\n description:\n 'Find the Nth occurrence of a weekday in a given month (e.g., \"2nd Friday of March 2026\", \"last Monday of next month\"). Supports 1st–5th and \"last\".',\n inputSchema: validator.object({\n nth: validator\n .string()\n .required()\n .description('Which occurrence: \"1st\", \"2nd\", \"3rd\", \"4th\", \"5th\", or \"last\".'),\n weekday: validator\n .string()\n .valid('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday')\n .required()\n .description('Day of the week.'),\n month: validator.number().required().description('Month number (1–12).'),\n year: validator.number().optional().description('Year (defaults to current year).'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n }),\n handler: async (args) => {\n const {\n nth,\n weekday,\n month: rawMonth,\n year: rawYear,\n timezone,\n } = args as {\n nth: string\n weekday: string\n month: number\n year?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const weekdayNames: Record<string, number> = {\n monday: 1,\n tuesday: 2,\n wednesday: 3,\n thursday: 4,\n friday: 5,\n saturday: 6,\n sunday: 7,\n }\n\n const targetWeekday = weekdayNames[weekday.toLowerCase()]\n const month = Math.floor(rawMonth)\n if (month < 1 || month > 12) return `Error: Month must be 1–12, got ${rawMonth}.`\n\n const year = Math.floor(rawYear ?? DateTime.now().setZone(zone).year)\n const nthRaw = nth.toLowerCase().replace(/\\s/g, '')\n\n const firstOfMonth = DateTime.fromObject({ year, month, day: 1 }, { zone })\n if (!firstOfMonth.isValid) return `Error: Invalid date for ${year}-${month}.`\n\n const occurrences: DateTime[] = []\n let cursor = firstOfMonth\n while (cursor.weekday !== targetWeekday) {\n cursor = cursor.plus({ days: 1 })\n }\n while (cursor.month === month) {\n occurrences.push(cursor)\n cursor = cursor.plus({ weeks: 1 })\n }\n\n let result: DateTime | undefined\n\n if (nthRaw === 'last') {\n result = occurrences[occurrences.length - 1]\n } else {\n const nthMap: Record<string, number> = {\n '1st': 1,\n '1': 1,\n 'first': 1,\n '2nd': 2,\n '2': 2,\n 'second': 2,\n '3rd': 3,\n '3': 3,\n 'third': 3,\n '4th': 4,\n '4': 4,\n 'fourth': 4,\n '5th': 5,\n '5': 5,\n 'fifth': 5,\n }\n const n = nthMap[nthRaw]\n if (!n) return `Error: Invalid nth value \"${nth}\". Use 1st–5th or \"last\".`\n if (n > occurrences.length) {\n return `Error: There is no ${nth} ${weekday} in ${firstOfMonth.toFormat('LLLL yyyy')} (only ${occurrences.length} occurrence${occurrences.length !== 1 ? 's' : ''}).`\n }\n result = occurrences[n - 1]\n }\n\n if (!result) return 'Error: Could not compute the date.'\n\n return `${nth} ${weekday} of ${result.toFormat('LLLL yyyy')}: ${result.toISODate()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy')}`\n },\n})\n\n/**\n * Get calendar metadata for a date.\n *\n * @remarks\n * Reports ISO week number, day of year, calendar quarter, fiscal quarter/year (configurable via\n * `fiscal_year_start_month`), week of month, and whether the date is a weekend. Accepts ISO\n * dates, natural-language (\"next Tuesday\"), and `now`.\n */\nexport const dateCalendarInfoTool = new Tool({\n name: 'date_calendar_info',\n description:\n 'Get calendar metadata for a date: ISO week number, day of year, calendar quarter, fiscal quarter/year, week of month, and whether it is a weekend or weekday.',\n inputSchema: validator.object({\n date: validator\n .string()\n .required()\n .description('ISO 8601 date, natural language date, or \"now\".'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description('Month when fiscal year starts (1–12, default: 1 = calendar year).'),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let dt: DateTime\n\n if (dateStr.toLowerCase() === 'now') {\n dt = DateTime.now().setZone(zone)\n } else {\n dt = DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) {\n const parsed = chrono.parseDate(dateStr, new Date())\n if (!parsed) return `Error: Could not parse date \"${dateStr}\".`\n dt = DateTime.fromJSDate(parsed).setZone(zone)\n }\n }\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n const calendarQuarter = Math.ceil(dt.month / 3)\n\n const monthInFY = (dt.month - fyStart + 12) % 12\n const fiscalQuarter = Math.floor(monthInFY / 3) + 1\n const fiscalYear = dt.month >= fyStart ? dt.year : dt.year - 1\n\n const firstOfMonth = dt.startOf('month')\n const weekOfMonth = Math.ceil((dt.day + firstOfMonth.weekday - 1) / 7)\n\n const dayOfYear = Math.floor(dt.diff(dt.startOf('year'), 'days').days) + 1\n\n const isWeekend = dt.weekday >= 6\n\n const lines = [\n `Date: ${dt.toISODate()} (${dt.toFormat('cccc, LLLL d, yyyy')})`,\n '',\n `ISO week number: ${dt.weekNumber} (ISO year: ${dt.weekYear})`,\n `Day of year: ${dayOfYear} / ${dt.daysInYear}`,\n `Day of week: ${dt.weekday} (${dt.toFormat('cccc')})`,\n `Week of month: ${weekOfMonth}`,\n `Weekend: ${isWeekend ? 'Yes' : 'No'}`,\n '',\n `Calendar quarter: Q${calendarQuarter}`,\n `Fiscal quarter: FQ${fiscalQuarter} (FY${fiscalYear}${fyStart !== 1 ? `, starts month ${fyStart}` : ''})`,\n ]\n\n return lines.join('\\n')\n },\n})\n\n/**\n * Parse a date/time expression from natural language or common formats.\n *\n * @remarks\n * Examples: `\"next Monday\"`, `\"March 5th\"`, `\"in 2 weeks\"`, `\"yesterday\"`. Uses chrono-node for\n * relative parsing. `reference_date` overrides the \"now\" anchor.\n */\nexport const dateParseTool = new Tool({\n name: 'date_parse',\n description:\n 'Parse a date/time string from natural language or common formats (\"next Monday\", \"March 5th\", \"in 2 weeks\", \"yesterday\"). Returns an ISO 8601 date.',\n inputSchema: validator.object({\n text: validator\n .string()\n .required()\n .description('Date/time expression to parse (natural language or structured)'),\n reference_date: validator\n .string()\n .optional()\n .description('ISO date to treat as \"now\" for relative expressions (default: current time)'),\n timezone: validator\n .string()\n .optional()\n .description('IANA timezone for the result (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n text,\n reference_date: referenceDate,\n timezone,\n } = args as {\n text: string\n reference_date?: string\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let refDate = new Date()\n if (referenceDate) {\n refDate = new Date(referenceDate)\n if (Number.isNaN(refDate.getTime()))\n return `Error: Invalid reference_date \"${referenceDate}\".`\n }\n\n const parsed = chrono.parseDate(text, refDate)\n if (!parsed) return `Error: Could not parse a date from \"${text}\".`\n\n const dt = DateTime.fromJSDate(parsed).setZone(zone)\n return `ISO: ${dt.toISO()}\\nFormatted: ${dt.toFormat('cccc, LLLL d, yyyy h:mm a ZZZZ')}`\n },\n})\n\n/**\n * Get the start or end of a time period containing a given date.\n *\n * @remarks\n * Periods: `day`, `week`, `isoweek` (Monday-start), `month`, `quarter`, `year`. Quarter and year\n * honour `fiscal_year_start_month` for fiscal calendars (default: 1 = calendar year).\n */\nexport const datePeriodTool = new Tool({\n name: 'date_period',\n description:\n 'Get the start or end of a time period (day, week, month, quarter, year) containing a given date. Supports fiscal year offsets.',\n inputSchema: validator.object({\n date: validator.string().required().description('ISO 8601 date or \"now\"'),\n period: validator\n .string()\n .valid('day', 'week', 'isoweek', 'month', 'quarter', 'year')\n .required()\n .description('Time period (isoweek = Monday-start week)'),\n boundary: validator\n .string()\n .valid('start', 'end')\n .required()\n .description('\"start\" for the first moment, \"end\" for the last moment of the period'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description(\n 'For quarter/year: month number when the fiscal year starts (1–12, default: 1 = calendar year)'\n ),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n period,\n boundary,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n period: 'day' | 'week' | 'isoweek' | 'month' | 'quarter' | 'year'\n boundary: 'start' | 'end'\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const dt =\n dateStr.toLowerCase() === 'now'\n ? DateTime.now().setZone(zone)\n : DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) return `Error: Invalid date \"${dateStr}\".`\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n let result: DateTime\n\n switch (period) {\n case 'day':\n result = boundary === 'start' ? dt.startOf('day') : dt.endOf('day')\n break\n case 'week':\n result = boundary === 'start' ? dt.startOf('week') : dt.endOf('week')\n break\n case 'isoweek':\n result =\n boundary === 'start'\n ? dt.startOf('week').set({ weekday: 1 })\n : dt.startOf('week').set({ weekday: 7 }).endOf('day')\n break\n case 'month':\n result = boundary === 'start' ? dt.startOf('month') : dt.endOf('month')\n break\n case 'quarter': {\n const monthInFY = (dt.month - fyStart + 12) % 12\n const qIndex = Math.floor(monthInFY / 3)\n const qStartMonth = ((qIndex * 3 + fyStart - 1) % 12) + 1\n const qStart = dt.set({ month: qStartMonth, day: 1 }).startOf('day')\n const adjusted = qStart > dt ? qStart.minus({ months: 3 }) : qStart\n result =\n boundary === 'start'\n ? adjusted\n : adjusted.plus({ months: 3 }).minus({ days: 1 }).endOf('day')\n break\n }\n case 'year':\n if (fyStart === 1) {\n result = boundary === 'start' ? dt.startOf('year') : dt.endOf('year')\n } else {\n const fyStartThis = dt.set({ month: fyStart, day: 1 }).startOf('day')\n const fyBase = dt >= fyStartThis ? fyStartThis : fyStartThis.minus({ years: 1 })\n result =\n boundary === 'start'\n ? fyBase\n : fyBase.plus({ years: 1 }).minus({ days: 1 }).endOf('day')\n }\n break\n }\n\n return `${boundary === 'start' ? 'Start' : 'End'} of ${period} containing ${dateStr}: ${result.toISO()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy h:mm:ss a ZZZZ')}`\n },\n})\n\n/**\n * Count business days between two dates, or compute the date N business days away.\n *\n * @remarks\n * Monday–Friday only; no holiday calendar awareness. Provide either `to` (count between) or\n * `add_days` (compute target date). Negative `add_days` walks backwards.\n */\nexport const dateBusinessDaysTool = new Tool({\n name: 'date_business_days',\n description:\n 'Count business days (Mon–Fri, no holiday awareness) between two dates, or calculate the date that is N business days from a start date.',\n inputSchema: validator.object({\n from: validator.string().required().description('Start date (ISO 8601 or \"now\")'),\n to: validator\n .string()\n .optional()\n .description('End date (ISO 8601 or \"now\") — for counting business days between two dates'),\n add_days: validator\n .number()\n .optional()\n .description('Instead of \"to\": number of business days to add (negative to subtract)'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n from: fromStr,\n to: toStr,\n add_days: addDays,\n timezone,\n } = args as {\n from: string\n to?: string\n add_days?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const fromDt = (\n fromStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(fromStr)\n ).setZone(zone)\n if (!fromDt.isValid) return `Error: Invalid from date \"${fromStr}\".`\n\n if (addDays !== undefined) {\n const n = Math.floor(addDays)\n let cursor = fromDt.startOf('day')\n let remaining = Math.abs(n)\n const dir = n >= 0 ? 1 : -1\n while (remaining > 0) {\n cursor = cursor.plus({ days: dir })\n if (cursor.weekday <= 5) remaining--\n }\n return `${n >= 0 ? '+' : ''}${n} business day${Math.abs(n) !== 1 ? 's' : ''} from ${fromStr}: ${cursor.toISODate()}\\nFormatted: ${cursor.toFormat('cccc, LLLL d, yyyy')}`\n }\n\n if (!toStr) return 'Error: Provide either \"to\" date or \"add_days\".'\n\n const toDt = (toStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(toStr)).setZone(\n zone\n )\n if (!toDt.isValid) return `Error: Invalid to date \"${toStr}\".`\n\n const count = countBusinessDays(fromDt, toDt)\n return `Business days from ${fromStr} to ${toStr}: ${count}`\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"datetime_extended.cjs","names":[],"sources":["../../../src/batteries/tools/datetime_extended/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for parsing natural-language dates and business-calendar calculations.\n *\n * @module @nhtio/adk/batteries/tools/datetime_extended\n *\n * @remarks\n * Pre-constructed bundled tools for the `datetime_extended` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport * as chrono from 'chrono-node'\nimport { Tool } from '@nhtio/adk/common'\nimport { DateTime, IANAZone } from 'luxon'\nimport { validator } from '@nhtio/validation'\n\nfunction resolveZone(timezone: string | undefined): { zone: string; error?: string } {\n if (!timezone) return { zone: 'UTC' }\n if (!IANAZone.isValidZone(timezone)) return { zone: '', error: `Invalid timezone \"${timezone}\".` }\n return { zone: timezone }\n}\n\nfunction countBusinessDays(from: DateTime, to: DateTime): number {\n const forward = to >= from\n const start = forward ? from.startOf('day') : to.startOf('day')\n const end = forward ? to.startOf('day') : from.startOf('day')\n\n const totalDays = Math.round(end.diff(start, 'days').days)\n const fullWeeks = Math.floor(totalDays / 7)\n let bdays = fullWeeks * 5\n\n let cursor = start.plus({ days: fullWeeks * 7 })\n while (cursor < end) {\n cursor = cursor.plus({ days: 1 })\n if (cursor.weekday <= 5) bdays++\n }\n\n return forward ? bdays : -bdays\n}\n\n/**\n * Find the Nth occurrence of a weekday in a given month.\n *\n * @remarks\n * Examples: \"2nd Friday of March 2026\", \"last Monday of January 2025\". Accepts 1st–5th and\n * `last`. Returns an error if the month does not contain that many occurrences of the weekday.\n */\nexport const dateNthWeekdayTool = new Tool({\n name: 'date_nth_weekday',\n description:\n 'Find the Nth occurrence of a weekday in a given month (e.g., \"2nd Friday of March 2026\", \"last Monday of next month\"). Supports 1st–5th and \"last\".',\n inputSchema: validator.object({\n nth: validator\n .string()\n .required()\n .description('Which occurrence: \"1st\", \"2nd\", \"3rd\", \"4th\", \"5th\", or \"last\".'),\n weekday: validator\n .string()\n .valid('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday')\n .required()\n .description('Day of the week.'),\n month: validator.number().required().description('Month number (1–12).'),\n year: validator.number().optional().description('Year (defaults to current year).'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n }),\n handler: async (args) => {\n const {\n nth,\n weekday,\n month: rawMonth,\n year: rawYear,\n timezone,\n } = args as {\n nth: string\n weekday: string\n month: number\n year?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const weekdayNames: Record<string, number> = {\n monday: 1,\n tuesday: 2,\n wednesday: 3,\n thursday: 4,\n friday: 5,\n saturday: 6,\n sunday: 7,\n }\n\n const targetWeekday = weekdayNames[weekday.toLowerCase()]\n const month = Math.floor(rawMonth)\n if (month < 1 || month > 12) return `Error: Month must be 1–12, got ${rawMonth}.`\n\n const year = Math.floor(rawYear ?? DateTime.now().setZone(zone).year)\n const nthRaw = nth.toLowerCase().replace(/\\s/g, '')\n\n const firstOfMonth = DateTime.fromObject({ year, month, day: 1 }, { zone })\n if (!firstOfMonth.isValid) return `Error: Invalid date for ${year}-${month}.`\n\n const occurrences: DateTime[] = []\n let cursor = firstOfMonth\n while (cursor.weekday !== targetWeekday) {\n cursor = cursor.plus({ days: 1 })\n }\n while (cursor.month === month) {\n occurrences.push(cursor)\n cursor = cursor.plus({ weeks: 1 })\n }\n\n let result: DateTime | undefined\n\n if (nthRaw === 'last') {\n result = occurrences[occurrences.length - 1]\n } else {\n const nthMap: Record<string, number> = {\n '1st': 1,\n '1': 1,\n 'first': 1,\n '2nd': 2,\n '2': 2,\n 'second': 2,\n '3rd': 3,\n '3': 3,\n 'third': 3,\n '4th': 4,\n '4': 4,\n 'fourth': 4,\n '5th': 5,\n '5': 5,\n 'fifth': 5,\n }\n const n = nthMap[nthRaw]\n if (!n) return `Error: Invalid nth value \"${nth}\". Use 1st–5th or \"last\".`\n if (n > occurrences.length) {\n return `Error: There is no ${nth} ${weekday} in ${firstOfMonth.toFormat('LLLL yyyy')} (only ${occurrences.length} occurrence${occurrences.length !== 1 ? 's' : ''}).`\n }\n result = occurrences[n - 1]\n }\n\n if (!result) return 'Error: Could not compute the date.'\n\n return `${nth} ${weekday} of ${result.toFormat('LLLL yyyy')}: ${result.toISODate()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy')}`\n },\n})\n\n/**\n * Get calendar metadata for a date.\n *\n * @remarks\n * Reports ISO week number, day of year, calendar quarter, fiscal quarter/year (configurable via\n * `fiscal_year_start_month`), week of month, and whether the date is a weekend. Accepts ISO\n * dates, natural-language (\"next Tuesday\"), and `now`.\n */\nexport const dateCalendarInfoTool = new Tool({\n name: 'date_calendar_info',\n description:\n 'Get calendar metadata for a date: ISO week number, day of year, calendar quarter, fiscal quarter/year, week of month, and whether it is a weekend or weekday.',\n inputSchema: validator.object({\n date: validator\n .string()\n .required()\n .description('ISO 8601 date, natural language date, or \"now\".'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description('Month when fiscal year starts (1–12, default: 1 = calendar year).'),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let dt: DateTime\n\n if (dateStr.toLowerCase() === 'now') {\n dt = DateTime.now().setZone(zone)\n } else {\n dt = DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) {\n const parsed = chrono.parseDate(dateStr, new Date())\n if (!parsed) return `Error: Could not parse date \"${dateStr}\".`\n dt = DateTime.fromJSDate(parsed).setZone(zone)\n }\n }\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n const calendarQuarter = Math.ceil(dt.month / 3)\n\n const monthInFY = (dt.month - fyStart + 12) % 12\n const fiscalQuarter = Math.floor(monthInFY / 3) + 1\n const fiscalYear = dt.month >= fyStart ? dt.year : dt.year - 1\n\n const firstOfMonth = dt.startOf('month')\n const weekOfMonth = Math.ceil((dt.day + firstOfMonth.weekday - 1) / 7)\n\n const dayOfYear = Math.floor(dt.diff(dt.startOf('year'), 'days').days) + 1\n\n const isWeekend = dt.weekday >= 6\n\n const lines = [\n `Date: ${dt.toISODate()} (${dt.toFormat('cccc, LLLL d, yyyy')})`,\n '',\n `ISO week number: ${dt.weekNumber} (ISO year: ${dt.weekYear})`,\n `Day of year: ${dayOfYear} / ${dt.daysInYear}`,\n `Day of week: ${dt.weekday} (${dt.toFormat('cccc')})`,\n `Week of month: ${weekOfMonth}`,\n `Weekend: ${isWeekend ? 'Yes' : 'No'}`,\n '',\n `Calendar quarter: Q${calendarQuarter}`,\n `Fiscal quarter: FQ${fiscalQuarter} (FY${fiscalYear}${fyStart !== 1 ? `, starts month ${fyStart}` : ''})`,\n ]\n\n return lines.join('\\n')\n },\n})\n\n/**\n * Parse a date/time expression from natural language or common formats.\n *\n * @remarks\n * Examples: `\"next Monday\"`, `\"March 5th\"`, `\"in 2 weeks\"`, `\"yesterday\"`. Uses chrono-node for\n * relative parsing. `reference_date` overrides the \"now\" anchor.\n */\nexport const dateParseTool = new Tool({\n name: 'date_parse',\n description:\n 'Parse a date/time string from natural language or common formats (\"next Monday\", \"March 5th\", \"in 2 weeks\", \"yesterday\"). Returns an ISO 8601 date.',\n inputSchema: validator.object({\n text: validator\n .string()\n .required()\n .description('Date/time expression to parse (natural language or structured)'),\n reference_date: validator\n .string()\n .optional()\n .description('ISO date to treat as \"now\" for relative expressions (default: current time)'),\n timezone: validator\n .string()\n .optional()\n .description('IANA timezone for the result (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n text,\n reference_date: referenceDate,\n timezone,\n } = args as {\n text: string\n reference_date?: string\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let refDate = new Date()\n if (referenceDate) {\n refDate = new Date(referenceDate)\n if (Number.isNaN(refDate.getTime()))\n return `Error: Invalid reference_date \"${referenceDate}\".`\n }\n\n const parsed = chrono.parseDate(text, refDate)\n if (!parsed) return `Error: Could not parse a date from \"${text}\".`\n\n const dt = DateTime.fromJSDate(parsed).setZone(zone)\n return `ISO: ${dt.toISO()}\\nFormatted: ${dt.toFormat('cccc, LLLL d, yyyy h:mm a ZZZZ')}`\n },\n})\n\n/**\n * Get the start or end of a time period containing a given date.\n *\n * @remarks\n * Periods: `day`, `week`, `isoweek` (Monday-start), `month`, `quarter`, `year`. Quarter and year\n * honour `fiscal_year_start_month` for fiscal calendars (default: 1 = calendar year).\n */\nexport const datePeriodTool = new Tool({\n name: 'date_period',\n description:\n 'Get the start or end of a time period (day, week, month, quarter, year) containing a given date. Supports fiscal year offsets.',\n inputSchema: validator.object({\n date: validator.string().required().description('ISO 8601 date or \"now\"'),\n period: validator\n .string()\n .valid('day', 'week', 'isoweek', 'month', 'quarter', 'year')\n .required()\n .description('Time period (isoweek = Monday-start week)'),\n boundary: validator\n .string()\n .valid('start', 'end')\n .required()\n .description('\"start\" for the first moment, \"end\" for the last moment of the period'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description(\n 'For quarter/year: month number when the fiscal year starts (1–12, default: 1 = calendar year)'\n ),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n period,\n boundary,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n period: 'day' | 'week' | 'isoweek' | 'month' | 'quarter' | 'year'\n boundary: 'start' | 'end'\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const dt =\n dateStr.toLowerCase() === 'now'\n ? DateTime.now().setZone(zone)\n : DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) return `Error: Invalid date \"${dateStr}\".`\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n let result: DateTime\n\n switch (period) {\n case 'day':\n result = boundary === 'start' ? dt.startOf('day') : dt.endOf('day')\n break\n case 'week':\n result = boundary === 'start' ? dt.startOf('week') : dt.endOf('week')\n break\n case 'isoweek':\n result =\n boundary === 'start'\n ? dt.startOf('week').set({ weekday: 1 })\n : dt.startOf('week').set({ weekday: 7 }).endOf('day')\n break\n case 'month':\n result = boundary === 'start' ? dt.startOf('month') : dt.endOf('month')\n break\n case 'quarter': {\n // Months since the fiscal year began (0–11), then the offset into the current quarter.\n // Stepping back that many whole months from the start of `dt`'s month lands on the quarter\n // start — and crucially handles quarters that span the calendar-year boundary (e.g. an\n // FY-Feb Q4 of Nov–Jan): subtracting months rolls the year back correctly, where the old\n // `dt.set({month})` kept the current year and produced a date in the wrong quarter.\n const monthInFY = (dt.month - fyStart + 12) % 12\n const monthsIntoQuarter = monthInFY % 3\n const qStart = dt.startOf('month').minus({ months: monthsIntoQuarter })\n result =\n boundary === 'start' ? qStart : qStart.plus({ months: 3 }).minus({ days: 1 }).endOf('day')\n break\n }\n case 'year':\n if (fyStart === 1) {\n result = boundary === 'start' ? dt.startOf('year') : dt.endOf('year')\n } else {\n const fyStartThis = dt.set({ month: fyStart, day: 1 }).startOf('day')\n const fyBase = dt >= fyStartThis ? fyStartThis : fyStartThis.minus({ years: 1 })\n result =\n boundary === 'start'\n ? fyBase\n : fyBase.plus({ years: 1 }).minus({ days: 1 }).endOf('day')\n }\n break\n }\n\n return `${boundary === 'start' ? 'Start' : 'End'} of ${period} containing ${dateStr}: ${result.toISO()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy h:mm:ss a ZZZZ')}`\n },\n})\n\n/**\n * Count business days between two dates, or compute the date N business days away.\n *\n * @remarks\n * Monday–Friday only; no holiday calendar awareness. Provide either `to` (count between) or\n * `add_days` (compute target date). Negative `add_days` walks backwards.\n */\nexport const dateBusinessDaysTool = new Tool({\n name: 'date_business_days',\n description:\n 'Count business days (Mon–Fri, no holiday awareness) between two dates, or calculate the date that is N business days from a start date.',\n inputSchema: validator.object({\n from: validator.string().required().description('Start date (ISO 8601 or \"now\")'),\n to: validator\n .string()\n .optional()\n .description('End date (ISO 8601 or \"now\") — for counting business days between two dates'),\n add_days: validator\n .number()\n .optional()\n .description('Instead of \"to\": number of business days to add (negative to subtract)'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n from: fromStr,\n to: toStr,\n add_days: addDays,\n timezone,\n } = args as {\n from: string\n to?: string\n add_days?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const fromDt = (\n fromStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(fromStr)\n ).setZone(zone)\n if (!fromDt.isValid) return `Error: Invalid from date \"${fromStr}\".`\n\n if (addDays !== undefined) {\n const n = Math.floor(addDays)\n let cursor = fromDt.startOf('day')\n let remaining = Math.abs(n)\n const dir = n >= 0 ? 1 : -1\n while (remaining > 0) {\n cursor = cursor.plus({ days: dir })\n if (cursor.weekday <= 5) remaining--\n }\n return `${n >= 0 ? '+' : ''}${n} business day${Math.abs(n) !== 1 ? 's' : ''} from ${fromStr}: ${cursor.toISODate()}\\nFormatted: ${cursor.toFormat('cccc, LLLL d, yyyy')}`\n }\n\n if (!toStr) return 'Error: Provide either \"to\" date or \"add_days\".'\n\n const toDt = (toStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(toStr)).setZone(\n zone\n )\n if (!toDt.isValid) return `Error: Invalid to date \"${toStr}\".`\n\n const count = countBusinessDays(fromDt, toDt)\n return `Business days from ${fromStr} to ${toStr}: ${count}`\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as Tool } from "../../tool-
|
|
2
|
-
import "../../common-
|
|
1
|
+
import { t as Tool } from "../../tool-wMYMVl60.mjs";
|
|
2
|
+
import "../../common-DYDUi99O.mjs";
|
|
3
3
|
import { validator } from "@nhtio/validation";
|
|
4
4
|
import { DateTime, IANAZone } from "luxon";
|
|
5
5
|
import * as chrono from "chrono-node";
|
|
@@ -232,14 +232,9 @@ var datePeriodTool = new Tool({
|
|
|
232
232
|
result = boundary === "start" ? dt.startOf("month") : dt.endOf("month");
|
|
233
233
|
break;
|
|
234
234
|
case "quarter": {
|
|
235
|
-
const
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
month: qStartMonth,
|
|
239
|
-
day: 1
|
|
240
|
-
}).startOf("day");
|
|
241
|
-
const adjusted = qStart > dt ? qStart.minus({ months: 3 }) : qStart;
|
|
242
|
-
result = boundary === "start" ? adjusted : adjusted.plus({ months: 3 }).minus({ days: 1 }).endOf("day");
|
|
235
|
+
const monthsIntoQuarter = (dt.month - fyStart + 12) % 12 % 3;
|
|
236
|
+
const qStart = dt.startOf("month").minus({ months: monthsIntoQuarter });
|
|
237
|
+
result = boundary === "start" ? qStart : qStart.plus({ months: 3 }).minus({ days: 1 }).endOf("day");
|
|
243
238
|
break;
|
|
244
239
|
}
|
|
245
240
|
case "year":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datetime_extended.mjs","names":[],"sources":["../../../src/batteries/tools/datetime_extended/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for parsing natural-language dates and business-calendar calculations.\n *\n * @module @nhtio/adk/batteries/tools/datetime_extended\n *\n * @remarks\n * Pre-constructed bundled tools for the `datetime_extended` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport * as chrono from 'chrono-node'\nimport { Tool } from '@nhtio/adk/common'\nimport { DateTime, IANAZone } from 'luxon'\nimport { validator } from '@nhtio/validation'\n\nfunction resolveZone(timezone: string | undefined): { zone: string; error?: string } {\n if (!timezone) return { zone: 'UTC' }\n if (!IANAZone.isValidZone(timezone)) return { zone: '', error: `Invalid timezone \"${timezone}\".` }\n return { zone: timezone }\n}\n\nfunction countBusinessDays(from: DateTime, to: DateTime): number {\n const forward = to >= from\n const start = forward ? from.startOf('day') : to.startOf('day')\n const end = forward ? to.startOf('day') : from.startOf('day')\n\n const totalDays = Math.round(end.diff(start, 'days').days)\n const fullWeeks = Math.floor(totalDays / 7)\n let bdays = fullWeeks * 5\n\n let cursor = start.plus({ days: fullWeeks * 7 })\n while (cursor < end) {\n cursor = cursor.plus({ days: 1 })\n if (cursor.weekday <= 5) bdays++\n }\n\n return forward ? bdays : -bdays\n}\n\n/**\n * Find the Nth occurrence of a weekday in a given month.\n *\n * @remarks\n * Examples: \"2nd Friday of March 2026\", \"last Monday of January 2025\". Accepts 1st–5th and\n * `last`. Returns an error if the month does not contain that many occurrences of the weekday.\n */\nexport const dateNthWeekdayTool = new Tool({\n name: 'date_nth_weekday',\n description:\n 'Find the Nth occurrence of a weekday in a given month (e.g., \"2nd Friday of March 2026\", \"last Monday of next month\"). Supports 1st–5th and \"last\".',\n inputSchema: validator.object({\n nth: validator\n .string()\n .required()\n .description('Which occurrence: \"1st\", \"2nd\", \"3rd\", \"4th\", \"5th\", or \"last\".'),\n weekday: validator\n .string()\n .valid('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday')\n .required()\n .description('Day of the week.'),\n month: validator.number().required().description('Month number (1–12).'),\n year: validator.number().optional().description('Year (defaults to current year).'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n }),\n handler: async (args) => {\n const {\n nth,\n weekday,\n month: rawMonth,\n year: rawYear,\n timezone,\n } = args as {\n nth: string\n weekday: string\n month: number\n year?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const weekdayNames: Record<string, number> = {\n monday: 1,\n tuesday: 2,\n wednesday: 3,\n thursday: 4,\n friday: 5,\n saturday: 6,\n sunday: 7,\n }\n\n const targetWeekday = weekdayNames[weekday.toLowerCase()]\n const month = Math.floor(rawMonth)\n if (month < 1 || month > 12) return `Error: Month must be 1–12, got ${rawMonth}.`\n\n const year = Math.floor(rawYear ?? DateTime.now().setZone(zone).year)\n const nthRaw = nth.toLowerCase().replace(/\\s/g, '')\n\n const firstOfMonth = DateTime.fromObject({ year, month, day: 1 }, { zone })\n if (!firstOfMonth.isValid) return `Error: Invalid date for ${year}-${month}.`\n\n const occurrences: DateTime[] = []\n let cursor = firstOfMonth\n while (cursor.weekday !== targetWeekday) {\n cursor = cursor.plus({ days: 1 })\n }\n while (cursor.month === month) {\n occurrences.push(cursor)\n cursor = cursor.plus({ weeks: 1 })\n }\n\n let result: DateTime | undefined\n\n if (nthRaw === 'last') {\n result = occurrences[occurrences.length - 1]\n } else {\n const nthMap: Record<string, number> = {\n '1st': 1,\n '1': 1,\n 'first': 1,\n '2nd': 2,\n '2': 2,\n 'second': 2,\n '3rd': 3,\n '3': 3,\n 'third': 3,\n '4th': 4,\n '4': 4,\n 'fourth': 4,\n '5th': 5,\n '5': 5,\n 'fifth': 5,\n }\n const n = nthMap[nthRaw]\n if (!n) return `Error: Invalid nth value \"${nth}\". Use 1st–5th or \"last\".`\n if (n > occurrences.length) {\n return `Error: There is no ${nth} ${weekday} in ${firstOfMonth.toFormat('LLLL yyyy')} (only ${occurrences.length} occurrence${occurrences.length !== 1 ? 's' : ''}).`\n }\n result = occurrences[n - 1]\n }\n\n if (!result) return 'Error: Could not compute the date.'\n\n return `${nth} ${weekday} of ${result.toFormat('LLLL yyyy')}: ${result.toISODate()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy')}`\n },\n})\n\n/**\n * Get calendar metadata for a date.\n *\n * @remarks\n * Reports ISO week number, day of year, calendar quarter, fiscal quarter/year (configurable via\n * `fiscal_year_start_month`), week of month, and whether the date is a weekend. Accepts ISO\n * dates, natural-language (\"next Tuesday\"), and `now`.\n */\nexport const dateCalendarInfoTool = new Tool({\n name: 'date_calendar_info',\n description:\n 'Get calendar metadata for a date: ISO week number, day of year, calendar quarter, fiscal quarter/year, week of month, and whether it is a weekend or weekday.',\n inputSchema: validator.object({\n date: validator\n .string()\n .required()\n .description('ISO 8601 date, natural language date, or \"now\".'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description('Month when fiscal year starts (1–12, default: 1 = calendar year).'),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let dt: DateTime\n\n if (dateStr.toLowerCase() === 'now') {\n dt = DateTime.now().setZone(zone)\n } else {\n dt = DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) {\n const parsed = chrono.parseDate(dateStr, new Date())\n if (!parsed) return `Error: Could not parse date \"${dateStr}\".`\n dt = DateTime.fromJSDate(parsed).setZone(zone)\n }\n }\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n const calendarQuarter = Math.ceil(dt.month / 3)\n\n const monthInFY = (dt.month - fyStart + 12) % 12\n const fiscalQuarter = Math.floor(monthInFY / 3) + 1\n const fiscalYear = dt.month >= fyStart ? dt.year : dt.year - 1\n\n const firstOfMonth = dt.startOf('month')\n const weekOfMonth = Math.ceil((dt.day + firstOfMonth.weekday - 1) / 7)\n\n const dayOfYear = Math.floor(dt.diff(dt.startOf('year'), 'days').days) + 1\n\n const isWeekend = dt.weekday >= 6\n\n const lines = [\n `Date: ${dt.toISODate()} (${dt.toFormat('cccc, LLLL d, yyyy')})`,\n '',\n `ISO week number: ${dt.weekNumber} (ISO year: ${dt.weekYear})`,\n `Day of year: ${dayOfYear} / ${dt.daysInYear}`,\n `Day of week: ${dt.weekday} (${dt.toFormat('cccc')})`,\n `Week of month: ${weekOfMonth}`,\n `Weekend: ${isWeekend ? 'Yes' : 'No'}`,\n '',\n `Calendar quarter: Q${calendarQuarter}`,\n `Fiscal quarter: FQ${fiscalQuarter} (FY${fiscalYear}${fyStart !== 1 ? `, starts month ${fyStart}` : ''})`,\n ]\n\n return lines.join('\\n')\n },\n})\n\n/**\n * Parse a date/time expression from natural language or common formats.\n *\n * @remarks\n * Examples: `\"next Monday\"`, `\"March 5th\"`, `\"in 2 weeks\"`, `\"yesterday\"`. Uses chrono-node for\n * relative parsing. `reference_date` overrides the \"now\" anchor.\n */\nexport const dateParseTool = new Tool({\n name: 'date_parse',\n description:\n 'Parse a date/time string from natural language or common formats (\"next Monday\", \"March 5th\", \"in 2 weeks\", \"yesterday\"). Returns an ISO 8601 date.',\n inputSchema: validator.object({\n text: validator\n .string()\n .required()\n .description('Date/time expression to parse (natural language or structured)'),\n reference_date: validator\n .string()\n .optional()\n .description('ISO date to treat as \"now\" for relative expressions (default: current time)'),\n timezone: validator\n .string()\n .optional()\n .description('IANA timezone for the result (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n text,\n reference_date: referenceDate,\n timezone,\n } = args as {\n text: string\n reference_date?: string\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let refDate = new Date()\n if (referenceDate) {\n refDate = new Date(referenceDate)\n if (Number.isNaN(refDate.getTime()))\n return `Error: Invalid reference_date \"${referenceDate}\".`\n }\n\n const parsed = chrono.parseDate(text, refDate)\n if (!parsed) return `Error: Could not parse a date from \"${text}\".`\n\n const dt = DateTime.fromJSDate(parsed).setZone(zone)\n return `ISO: ${dt.toISO()}\\nFormatted: ${dt.toFormat('cccc, LLLL d, yyyy h:mm a ZZZZ')}`\n },\n})\n\n/**\n * Get the start or end of a time period containing a given date.\n *\n * @remarks\n * Periods: `day`, `week`, `isoweek` (Monday-start), `month`, `quarter`, `year`. Quarter and year\n * honour `fiscal_year_start_month` for fiscal calendars (default: 1 = calendar year).\n */\nexport const datePeriodTool = new Tool({\n name: 'date_period',\n description:\n 'Get the start or end of a time period (day, week, month, quarter, year) containing a given date. Supports fiscal year offsets.',\n inputSchema: validator.object({\n date: validator.string().required().description('ISO 8601 date or \"now\"'),\n period: validator\n .string()\n .valid('day', 'week', 'isoweek', 'month', 'quarter', 'year')\n .required()\n .description('Time period (isoweek = Monday-start week)'),\n boundary: validator\n .string()\n .valid('start', 'end')\n .required()\n .description('\"start\" for the first moment, \"end\" for the last moment of the period'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description(\n 'For quarter/year: month number when the fiscal year starts (1–12, default: 1 = calendar year)'\n ),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n period,\n boundary,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n period: 'day' | 'week' | 'isoweek' | 'month' | 'quarter' | 'year'\n boundary: 'start' | 'end'\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const dt =\n dateStr.toLowerCase() === 'now'\n ? DateTime.now().setZone(zone)\n : DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) return `Error: Invalid date \"${dateStr}\".`\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n let result: DateTime\n\n switch (period) {\n case 'day':\n result = boundary === 'start' ? dt.startOf('day') : dt.endOf('day')\n break\n case 'week':\n result = boundary === 'start' ? dt.startOf('week') : dt.endOf('week')\n break\n case 'isoweek':\n result =\n boundary === 'start'\n ? dt.startOf('week').set({ weekday: 1 })\n : dt.startOf('week').set({ weekday: 7 }).endOf('day')\n break\n case 'month':\n result = boundary === 'start' ? dt.startOf('month') : dt.endOf('month')\n break\n case 'quarter': {\n const monthInFY = (dt.month - fyStart + 12) % 12\n const qIndex = Math.floor(monthInFY / 3)\n const qStartMonth = ((qIndex * 3 + fyStart - 1) % 12) + 1\n const qStart = dt.set({ month: qStartMonth, day: 1 }).startOf('day')\n const adjusted = qStart > dt ? qStart.minus({ months: 3 }) : qStart\n result =\n boundary === 'start'\n ? adjusted\n : adjusted.plus({ months: 3 }).minus({ days: 1 }).endOf('day')\n break\n }\n case 'year':\n if (fyStart === 1) {\n result = boundary === 'start' ? dt.startOf('year') : dt.endOf('year')\n } else {\n const fyStartThis = dt.set({ month: fyStart, day: 1 }).startOf('day')\n const fyBase = dt >= fyStartThis ? fyStartThis : fyStartThis.minus({ years: 1 })\n result =\n boundary === 'start'\n ? fyBase\n : fyBase.plus({ years: 1 }).minus({ days: 1 }).endOf('day')\n }\n break\n }\n\n return `${boundary === 'start' ? 'Start' : 'End'} of ${period} containing ${dateStr}: ${result.toISO()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy h:mm:ss a ZZZZ')}`\n },\n})\n\n/**\n * Count business days between two dates, or compute the date N business days away.\n *\n * @remarks\n * Monday–Friday only; no holiday calendar awareness. Provide either `to` (count between) or\n * `add_days` (compute target date). Negative `add_days` walks backwards.\n */\nexport const dateBusinessDaysTool = new Tool({\n name: 'date_business_days',\n description:\n 'Count business days (Mon–Fri, no holiday awareness) between two dates, or calculate the date that is N business days from a start date.',\n inputSchema: validator.object({\n from: validator.string().required().description('Start date (ISO 8601 or \"now\")'),\n to: validator\n .string()\n .optional()\n .description('End date (ISO 8601 or \"now\") — for counting business days between two dates'),\n add_days: validator\n .number()\n .optional()\n .description('Instead of \"to\": number of business days to add (negative to subtract)'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n from: fromStr,\n to: toStr,\n add_days: addDays,\n timezone,\n } = args as {\n from: string\n to?: string\n add_days?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const fromDt = (\n fromStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(fromStr)\n ).setZone(zone)\n if (!fromDt.isValid) return `Error: Invalid from date \"${fromStr}\".`\n\n if (addDays !== undefined) {\n const n = Math.floor(addDays)\n let cursor = fromDt.startOf('day')\n let remaining = Math.abs(n)\n const dir = n >= 0 ? 1 : -1\n while (remaining > 0) {\n cursor = cursor.plus({ days: dir })\n if (cursor.weekday <= 5) remaining--\n }\n return `${n >= 0 ? '+' : ''}${n} business day${Math.abs(n) !== 1 ? 's' : ''} from ${fromStr}: ${cursor.toISODate()}\\nFormatted: ${cursor.toFormat('cccc, LLLL d, yyyy')}`\n }\n\n if (!toStr) return 'Error: Provide either \"to\" date or \"add_days\".'\n\n const toDt = (toStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(toStr)).setZone(\n zone\n )\n if (!toDt.isValid) return `Error: Invalid to date \"${toStr}\".`\n\n const count = countBusinessDays(fromDt, toDt)\n return `Business days from ${fromStr} to ${toStr}: ${count}`\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"datetime_extended.mjs","names":[],"sources":["../../../src/batteries/tools/datetime_extended/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for parsing natural-language dates and business-calendar calculations.\n *\n * @module @nhtio/adk/batteries/tools/datetime_extended\n *\n * @remarks\n * Pre-constructed bundled tools for the `datetime_extended` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport * as chrono from 'chrono-node'\nimport { Tool } from '@nhtio/adk/common'\nimport { DateTime, IANAZone } from 'luxon'\nimport { validator } from '@nhtio/validation'\n\nfunction resolveZone(timezone: string | undefined): { zone: string; error?: string } {\n if (!timezone) return { zone: 'UTC' }\n if (!IANAZone.isValidZone(timezone)) return { zone: '', error: `Invalid timezone \"${timezone}\".` }\n return { zone: timezone }\n}\n\nfunction countBusinessDays(from: DateTime, to: DateTime): number {\n const forward = to >= from\n const start = forward ? from.startOf('day') : to.startOf('day')\n const end = forward ? to.startOf('day') : from.startOf('day')\n\n const totalDays = Math.round(end.diff(start, 'days').days)\n const fullWeeks = Math.floor(totalDays / 7)\n let bdays = fullWeeks * 5\n\n let cursor = start.plus({ days: fullWeeks * 7 })\n while (cursor < end) {\n cursor = cursor.plus({ days: 1 })\n if (cursor.weekday <= 5) bdays++\n }\n\n return forward ? bdays : -bdays\n}\n\n/**\n * Find the Nth occurrence of a weekday in a given month.\n *\n * @remarks\n * Examples: \"2nd Friday of March 2026\", \"last Monday of January 2025\". Accepts 1st–5th and\n * `last`. Returns an error if the month does not contain that many occurrences of the weekday.\n */\nexport const dateNthWeekdayTool = new Tool({\n name: 'date_nth_weekday',\n description:\n 'Find the Nth occurrence of a weekday in a given month (e.g., \"2nd Friday of March 2026\", \"last Monday of next month\"). Supports 1st–5th and \"last\".',\n inputSchema: validator.object({\n nth: validator\n .string()\n .required()\n .description('Which occurrence: \"1st\", \"2nd\", \"3rd\", \"4th\", \"5th\", or \"last\".'),\n weekday: validator\n .string()\n .valid('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday')\n .required()\n .description('Day of the week.'),\n month: validator.number().required().description('Month number (1–12).'),\n year: validator.number().optional().description('Year (defaults to current year).'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n }),\n handler: async (args) => {\n const {\n nth,\n weekday,\n month: rawMonth,\n year: rawYear,\n timezone,\n } = args as {\n nth: string\n weekday: string\n month: number\n year?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const weekdayNames: Record<string, number> = {\n monday: 1,\n tuesday: 2,\n wednesday: 3,\n thursday: 4,\n friday: 5,\n saturday: 6,\n sunday: 7,\n }\n\n const targetWeekday = weekdayNames[weekday.toLowerCase()]\n const month = Math.floor(rawMonth)\n if (month < 1 || month > 12) return `Error: Month must be 1–12, got ${rawMonth}.`\n\n const year = Math.floor(rawYear ?? DateTime.now().setZone(zone).year)\n const nthRaw = nth.toLowerCase().replace(/\\s/g, '')\n\n const firstOfMonth = DateTime.fromObject({ year, month, day: 1 }, { zone })\n if (!firstOfMonth.isValid) return `Error: Invalid date for ${year}-${month}.`\n\n const occurrences: DateTime[] = []\n let cursor = firstOfMonth\n while (cursor.weekday !== targetWeekday) {\n cursor = cursor.plus({ days: 1 })\n }\n while (cursor.month === month) {\n occurrences.push(cursor)\n cursor = cursor.plus({ weeks: 1 })\n }\n\n let result: DateTime | undefined\n\n if (nthRaw === 'last') {\n result = occurrences[occurrences.length - 1]\n } else {\n const nthMap: Record<string, number> = {\n '1st': 1,\n '1': 1,\n 'first': 1,\n '2nd': 2,\n '2': 2,\n 'second': 2,\n '3rd': 3,\n '3': 3,\n 'third': 3,\n '4th': 4,\n '4': 4,\n 'fourth': 4,\n '5th': 5,\n '5': 5,\n 'fifth': 5,\n }\n const n = nthMap[nthRaw]\n if (!n) return `Error: Invalid nth value \"${nth}\". Use 1st–5th or \"last\".`\n if (n > occurrences.length) {\n return `Error: There is no ${nth} ${weekday} in ${firstOfMonth.toFormat('LLLL yyyy')} (only ${occurrences.length} occurrence${occurrences.length !== 1 ? 's' : ''}).`\n }\n result = occurrences[n - 1]\n }\n\n if (!result) return 'Error: Could not compute the date.'\n\n return `${nth} ${weekday} of ${result.toFormat('LLLL yyyy')}: ${result.toISODate()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy')}`\n },\n})\n\n/**\n * Get calendar metadata for a date.\n *\n * @remarks\n * Reports ISO week number, day of year, calendar quarter, fiscal quarter/year (configurable via\n * `fiscal_year_start_month`), week of month, and whether the date is a weekend. Accepts ISO\n * dates, natural-language (\"next Tuesday\"), and `now`.\n */\nexport const dateCalendarInfoTool = new Tool({\n name: 'date_calendar_info',\n description:\n 'Get calendar metadata for a date: ISO week number, day of year, calendar quarter, fiscal quarter/year, week of month, and whether it is a weekend or weekday.',\n inputSchema: validator.object({\n date: validator\n .string()\n .required()\n .description('ISO 8601 date, natural language date, or \"now\".'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description('Month when fiscal year starts (1–12, default: 1 = calendar year).'),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let dt: DateTime\n\n if (dateStr.toLowerCase() === 'now') {\n dt = DateTime.now().setZone(zone)\n } else {\n dt = DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) {\n const parsed = chrono.parseDate(dateStr, new Date())\n if (!parsed) return `Error: Could not parse date \"${dateStr}\".`\n dt = DateTime.fromJSDate(parsed).setZone(zone)\n }\n }\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n const calendarQuarter = Math.ceil(dt.month / 3)\n\n const monthInFY = (dt.month - fyStart + 12) % 12\n const fiscalQuarter = Math.floor(monthInFY / 3) + 1\n const fiscalYear = dt.month >= fyStart ? dt.year : dt.year - 1\n\n const firstOfMonth = dt.startOf('month')\n const weekOfMonth = Math.ceil((dt.day + firstOfMonth.weekday - 1) / 7)\n\n const dayOfYear = Math.floor(dt.diff(dt.startOf('year'), 'days').days) + 1\n\n const isWeekend = dt.weekday >= 6\n\n const lines = [\n `Date: ${dt.toISODate()} (${dt.toFormat('cccc, LLLL d, yyyy')})`,\n '',\n `ISO week number: ${dt.weekNumber} (ISO year: ${dt.weekYear})`,\n `Day of year: ${dayOfYear} / ${dt.daysInYear}`,\n `Day of week: ${dt.weekday} (${dt.toFormat('cccc')})`,\n `Week of month: ${weekOfMonth}`,\n `Weekend: ${isWeekend ? 'Yes' : 'No'}`,\n '',\n `Calendar quarter: Q${calendarQuarter}`,\n `Fiscal quarter: FQ${fiscalQuarter} (FY${fiscalYear}${fyStart !== 1 ? `, starts month ${fyStart}` : ''})`,\n ]\n\n return lines.join('\\n')\n },\n})\n\n/**\n * Parse a date/time expression from natural language or common formats.\n *\n * @remarks\n * Examples: `\"next Monday\"`, `\"March 5th\"`, `\"in 2 weeks\"`, `\"yesterday\"`. Uses chrono-node for\n * relative parsing. `reference_date` overrides the \"now\" anchor.\n */\nexport const dateParseTool = new Tool({\n name: 'date_parse',\n description:\n 'Parse a date/time string from natural language or common formats (\"next Monday\", \"March 5th\", \"in 2 weeks\", \"yesterday\"). Returns an ISO 8601 date.',\n inputSchema: validator.object({\n text: validator\n .string()\n .required()\n .description('Date/time expression to parse (natural language or structured)'),\n reference_date: validator\n .string()\n .optional()\n .description('ISO date to treat as \"now\" for relative expressions (default: current time)'),\n timezone: validator\n .string()\n .optional()\n .description('IANA timezone for the result (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n text,\n reference_date: referenceDate,\n timezone,\n } = args as {\n text: string\n reference_date?: string\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let refDate = new Date()\n if (referenceDate) {\n refDate = new Date(referenceDate)\n if (Number.isNaN(refDate.getTime()))\n return `Error: Invalid reference_date \"${referenceDate}\".`\n }\n\n const parsed = chrono.parseDate(text, refDate)\n if (!parsed) return `Error: Could not parse a date from \"${text}\".`\n\n const dt = DateTime.fromJSDate(parsed).setZone(zone)\n return `ISO: ${dt.toISO()}\\nFormatted: ${dt.toFormat('cccc, LLLL d, yyyy h:mm a ZZZZ')}`\n },\n})\n\n/**\n * Get the start or end of a time period containing a given date.\n *\n * @remarks\n * Periods: `day`, `week`, `isoweek` (Monday-start), `month`, `quarter`, `year`. Quarter and year\n * honour `fiscal_year_start_month` for fiscal calendars (default: 1 = calendar year).\n */\nexport const datePeriodTool = new Tool({\n name: 'date_period',\n description:\n 'Get the start or end of a time period (day, week, month, quarter, year) containing a given date. Supports fiscal year offsets.',\n inputSchema: validator.object({\n date: validator.string().required().description('ISO 8601 date or \"now\"'),\n period: validator\n .string()\n .valid('day', 'week', 'isoweek', 'month', 'quarter', 'year')\n .required()\n .description('Time period (isoweek = Monday-start week)'),\n boundary: validator\n .string()\n .valid('start', 'end')\n .required()\n .description('\"start\" for the first moment, \"end\" for the last moment of the period'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description(\n 'For quarter/year: month number when the fiscal year starts (1–12, default: 1 = calendar year)'\n ),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n period,\n boundary,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n period: 'day' | 'week' | 'isoweek' | 'month' | 'quarter' | 'year'\n boundary: 'start' | 'end'\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const dt =\n dateStr.toLowerCase() === 'now'\n ? DateTime.now().setZone(zone)\n : DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) return `Error: Invalid date \"${dateStr}\".`\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n let result: DateTime\n\n switch (period) {\n case 'day':\n result = boundary === 'start' ? dt.startOf('day') : dt.endOf('day')\n break\n case 'week':\n result = boundary === 'start' ? dt.startOf('week') : dt.endOf('week')\n break\n case 'isoweek':\n result =\n boundary === 'start'\n ? dt.startOf('week').set({ weekday: 1 })\n : dt.startOf('week').set({ weekday: 7 }).endOf('day')\n break\n case 'month':\n result = boundary === 'start' ? dt.startOf('month') : dt.endOf('month')\n break\n case 'quarter': {\n // Months since the fiscal year began (0–11), then the offset into the current quarter.\n // Stepping back that many whole months from the start of `dt`'s month lands on the quarter\n // start — and crucially handles quarters that span the calendar-year boundary (e.g. an\n // FY-Feb Q4 of Nov–Jan): subtracting months rolls the year back correctly, where the old\n // `dt.set({month})` kept the current year and produced a date in the wrong quarter.\n const monthInFY = (dt.month - fyStart + 12) % 12\n const monthsIntoQuarter = monthInFY % 3\n const qStart = dt.startOf('month').minus({ months: monthsIntoQuarter })\n result =\n boundary === 'start' ? qStart : qStart.plus({ months: 3 }).minus({ days: 1 }).endOf('day')\n break\n }\n case 'year':\n if (fyStart === 1) {\n result = boundary === 'start' ? dt.startOf('year') : dt.endOf('year')\n } else {\n const fyStartThis = dt.set({ month: fyStart, day: 1 }).startOf('day')\n const fyBase = dt >= fyStartThis ? fyStartThis : fyStartThis.minus({ years: 1 })\n result =\n boundary === 'start'\n ? fyBase\n : fyBase.plus({ years: 1 }).minus({ days: 1 }).endOf('day')\n }\n break\n }\n\n return `${boundary === 'start' ? 'Start' : 'End'} of ${period} containing ${dateStr}: ${result.toISO()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy h:mm:ss a ZZZZ')}`\n },\n})\n\n/**\n * Count business days between two dates, or compute the date N business days away.\n *\n * @remarks\n * Monday–Friday only; no holiday calendar awareness. Provide either `to` (count between) or\n * `add_days` (compute target date). Negative `add_days` walks backwards.\n */\nexport const dateBusinessDaysTool = new Tool({\n name: 'date_business_days',\n description:\n 'Count business days (Mon–Fri, no holiday awareness) between two dates, or calculate the date that is N business days from a start date.',\n inputSchema: validator.object({\n from: validator.string().required().description('Start date (ISO 8601 or \"now\")'),\n to: validator\n .string()\n .optional()\n .description('End date (ISO 8601 or \"now\") — for counting business days between two dates'),\n add_days: validator\n .number()\n .optional()\n .description('Instead of \"to\": number of business days to add (negative to subtract)'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n from: fromStr,\n to: toStr,\n add_days: addDays,\n timezone,\n } = args as {\n from: string\n to?: string\n add_days?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const fromDt = (\n fromStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(fromStr)\n ).setZone(zone)\n if (!fromDt.isValid) return `Error: Invalid from date \"${fromStr}\".`\n\n if (addDays !== undefined) {\n const n = Math.floor(addDays)\n let cursor = fromDt.startOf('day')\n let remaining = Math.abs(n)\n const dir = n >= 0 ? 1 : -1\n while (remaining > 0) {\n cursor = cursor.plus({ days: dir })\n if (cursor.weekday <= 5) remaining--\n }\n return `${n >= 0 ? '+' : ''}${n} business day${Math.abs(n) !== 1 ? 's' : ''} from ${fromStr}: ${cursor.toISODate()}\\nFormatted: ${cursor.toFormat('cccc, LLLL d, yyyy')}`\n }\n\n if (!toStr) return 'Error: Provide either \"to\" date or \"add_days\".'\n\n const toDt = (toStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(toStr)).setZone(\n zone\n )\n if (!toDt.isValid) return `Error: Invalid to date \"${toStr}\".`\n\n const count = countBusinessDays(fromDt, toDt)\n return `Business days from ${fromStr} to ${toStr}: ${count}`\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Ble4zEEl.js");
|
|
3
|
-
const require_tool = require("../../tool-
|
|
4
|
-
require("../../common-
|
|
3
|
+
const require_tool = require("../../tool-D5WGVIcI.js");
|
|
4
|
+
require("../../common-DZl3ADJs.js");
|
|
5
5
|
let _nhtio_validation = require("@nhtio/validation");
|
|
6
6
|
let luxon = require("luxon");
|
|
7
7
|
//#region src/batteries/tools/datetime_math/index.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as Tool } from "../../tool-
|
|
2
|
-
import "../../common-
|
|
1
|
+
import { t as Tool } from "../../tool-wMYMVl60.mjs";
|
|
2
|
+
import "../../common-DYDUi99O.mjs";
|
|
3
3
|
import { validator } from "@nhtio/validation";
|
|
4
4
|
import { DateTime, Duration, IANAZone } from "luxon";
|
|
5
5
|
//#region src/batteries/tools/datetime_math/index.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Ble4zEEl.js");
|
|
3
|
-
const require_tool_registry = require("../../tool_registry-
|
|
4
|
-
const require_tool = require("../../tool-
|
|
5
|
-
require("../../common-
|
|
3
|
+
const require_tool_registry = require("../../tool_registry-CKJPze3j.js");
|
|
4
|
+
const require_tool = require("../../tool-D5WGVIcI.js");
|
|
5
|
+
require("../../common-DZl3ADJs.js");
|
|
6
6
|
require("../../guards.cjs");
|
|
7
7
|
let _nhtio_validation = require("@nhtio/validation");
|
|
8
8
|
//#region src/batteries/tools/encoding/index.ts
|
|
@@ -28,6 +28,15 @@ var base64ToUtf8 = (b64) => {
|
|
|
28
28
|
return new TextDecoder().decode(bytes);
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
31
|
+
* Convert a numeric HTML-entity code point to its string, handling astral characters correctly.
|
|
32
|
+
* Returns the original entity text `fallback` for code points outside the valid Unicode range
|
|
33
|
+
* (0 – 0x10FFFF) so `String.fromCodePoint` never throws a RangeError.
|
|
34
|
+
*/
|
|
35
|
+
var codePointToString = (cp, fallback) => {
|
|
36
|
+
if (!Number.isInteger(cp) || cp < 0 || cp > 1114111) return fallback;
|
|
37
|
+
return String.fromCodePoint(cp);
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
31
40
|
* Encode or decode text using common schemes: base64, url (percent-encoding), html_entities.
|
|
32
41
|
*
|
|
33
42
|
* @remarks
|
|
@@ -56,7 +65,7 @@ var encodeTextTool = new require_tool.Tool({
|
|
|
56
65
|
}
|
|
57
66
|
if (scheme === "html_entities") {
|
|
58
67
|
if (direction === "encode") return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
59
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "\"").replace(/'/g, "'").replace(/&#(\d+);/g, (
|
|
68
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "\"").replace(/'/g, "'").replace(/&#(\d+);/g, (m, code) => codePointToString(Number.parseInt(code, 10), m)).replace(/&#x([0-9a-fA-F]+);/g, (m, hex) => codePointToString(Number.parseInt(hex, 16), m));
|
|
60
69
|
}
|
|
61
70
|
return `Error: Unknown scheme "${scheme}".`;
|
|
62
71
|
} catch (err) {
|