@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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exceptions-CitH5wZI.js","names":[],"sources":["../src/lib/classes/base_exception.ts","../src/lib/utils/validation.ts","../src/lib/utils/exceptions.ts"],"sourcesContent":["/**\n * Base class for all structured exceptions in the ADK.\n *\n * @remarks\n * Subclasses should declare static `code`, `status`, `fatal`, and optionally `help` to avoid\n * repeating those values on every instance. Instance-level options always take precedence over\n * static defaults, so a single exception class can still be thrown with per-site overrides when\n * needed.\n *\n * The runtime cross-realm guard is inlined here rather than imported from `../utils/guards`\n * to break a circular-import chain: `guards` depends on `validation`, which extends\n * `BaseException`. Importing the shared `isInstanceOf` helper into this file would create a\n * load-order cycle that leaves `BaseException` undefined when `ValidationException extends\n * BaseException` evaluates.\n */\nexport class BaseException extends Error {\n /**\n * Returns `true` if `value` is a {@link BaseException} instance.\n *\n * @remarks\n * Performs cross-realm-safe detection: tries `instanceof`, then `Symbol.hasInstance`, then\n * constructor-name comparison. The ADK does not export the `BaseException` class itself\n * as a constructable value — use this guard plus the {@link BaseException} type for runtime\n * detection and TypeScript narrowing.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link BaseException} instance.\n */\n public static isBaseException(value: unknown): value is BaseException {\n // eslint-disable-next-line adk/use-is-instance-of -- module cycle (guards ↔ validation ↔ BaseException); the cross-realm fallback is inlined below\n if (value instanceof BaseException) return true\n if (\n typeof BaseException[Symbol.hasInstance] === 'function' &&\n BaseException[Symbol.hasInstance](value)\n )\n return true\n // eslint-disable-next-line adk/prefer-is-object -- module cycle (guards ↔ validation ↔ BaseException); isObject would create a load-order cycle\n if (typeof value === 'object' && value !== null) {\n const ctorName = (value as { constructor?: { name?: string } }).constructor?.name\n if (ctorName === 'BaseException') return true\n }\n return false\n }\n /**\n * Default help text inherited by all instances unless overridden at the throw site.\n */\n declare static help?: string\n /**\n * Default machine-readable error code inherited by all instances.\n */\n declare static code?: string\n /**\n * Default HTTP status code inherited by all instances.\n */\n declare static status?: number\n /**\n * Whether exceptions of this class are fatal by default.\n */\n declare static fatal?: boolean\n /**\n * Default message used when no message is supplied to the constructor.\n */\n declare static message?: string\n\n /**\n * Name of the class that raised the exception.\n */\n name: string\n\n /**\n * Human-readable guidance for resolving or reporting this error.\n */\n declare help?: string\n\n /**\n * Machine-readable error code for narrowing exception-handling logic.\n */\n declare code?: string\n\n /**\n * HTTP status code associated with this error.\n */\n declare status?: number\n\n /**\n * When `true`, the ADK treats this error as unrecoverable and should halt the agent loop.\n */\n declare fatal?: boolean\n\n /**\n * @param message - Human-readable error message. Falls back to the static `message` on the\n * subclass if omitted.\n * @param options - Standard `ErrorOptions` extended with `code`, `status`, and `fatal`\n * overrides. Static defaults on the subclass are used when these are absent.\n */\n constructor(\n message?: string,\n options?: ErrorOptions & { code?: string; status?: number; fatal?: boolean }\n ) {\n super(message, options)\n\n const ErrorConstructor = this.constructor as typeof BaseException\n\n this.name = ErrorConstructor.name\n this.message = message || ErrorConstructor.message || ''\n\n const code = options?.code || ErrorConstructor.code\n if (code !== undefined) {\n this.code = code\n }\n\n const status = options?.status || ErrorConstructor.status\n if (status !== undefined) {\n this.status = status\n }\n\n const fatal = options?.fatal ?? ErrorConstructor.fatal\n if (fatal !== undefined) {\n this.fatal = fatal\n }\n\n const help = ErrorConstructor.help\n if (help !== undefined) {\n this.help = help\n }\n\n Error.captureStackTrace(this, ErrorConstructor)\n }\n\n get [Symbol.toStringTag]() {\n return this.constructor.name\n }\n\n toString() {\n if (this.code) {\n return `${this.name} [${this.code}]: ${this.message}`\n }\n return `${this.name}: ${this.message}`\n }\n}\n","import { BaseException } from '../classes/base_exception'\nimport { validator, ValidationError } from '@nhtio/validation'\nimport type { Schema } from '@nhtio/validation'\n\n/**\n * Returns `true` if `value` satisfies `schema` without throwing.\n *\n * @remarks\n * Aborts on the first validation error. Use {@link validateOrThrow} or\n * {@link asyncValidateOrThrow} when you need the full set of field errors.\n *\n * @param schema - The schema to validate against.\n * @param value - The value to test.\n * @returns `true` when `value` passes the schema; `false` otherwise.\n */\nexport const passesSchema = (schema: Schema, value: unknown): boolean => {\n const { error } = schema.validate(value, { abortEarly: true })\n return !error\n}\n\n/**\n * Returns `true` if `value` is a `ValidationError` or satisfies its minimum duck-type shape.\n *\n * @remarks\n * The duck-typing path handles `ValidationError` objects that cross module or realm boundaries\n * where `instanceof` would return `false`.\n *\n * @param value - The value to test.\n * @returns `true` when `value` conforms to the `ValidationError` shape.\n */\nexport const isValidationError = (value: unknown): value is ValidationError => {\n const schema = validator.alternatives(\n validator.object().instance(ValidationError as any),\n validator.function().instance(ValidationError as any),\n validator\n .object({\n message: validator.string().required(),\n details: validator\n .array()\n .items(\n validator.object({\n message: validator.string().required(),\n path: validator\n .array()\n .items(validator.alternatives(validator.string(), validator.number()))\n .required(),\n type: validator.string().required(),\n context: validator.object().unknown(true).required(),\n })\n )\n .required(),\n })\n .unknown(true)\n )\n return passesSchema(schema, value)\n}\n\nconst messageFromValidationError = (reason: ValidationError | undefined, fallback: string) => {\n return reason ? reason.details.map((d) => d.message).join(' and ') : fallback\n}\n\n/**\n * Thrown when input fails schema validation.\n *\n * @remarks\n * Carries the full `details` array from the underlying `ValidationError` so callers can surface\n * field-level messages without unwrapping the `cause` manually.\n */\nexport class ValidationException extends BaseException {\n static status = 422\n static code = 'VALIDATION_EXCEPTION'\n static fatal = false\n\n /** The raw field-level error details from the underlying `ValidationError`. */\n declare readonly details?: ValidationError['details']\n\n /**\n * @param reason - The `ValidationError` thrown by the schema; its `details` are surfaced\n * directly on this exception and its messages are joined to form the human-readable message.\n */\n constructor(reason: ValidationError) {\n const message = messageFromValidationError(reason, 'Validation failed')\n super(message, {\n code: ValidationException.code,\n status: ValidationException.status,\n fatal: ValidationException.fatal,\n cause: reason,\n })\n Object.defineProperty(this, 'details', {\n value: reason.details,\n enumerable: true,\n configurable: false,\n writable: false,\n })\n }\n}\n\n/**\n * Validates `value` against `schema` synchronously and returns the coerced result typed as `T`.\n *\n * @remarks\n * Collects all field errors before throwing. Use {@link asyncValidateOrThrow} for schemas that\n * include async custom validators.\n *\n * @typeParam T - The expected type of `value` after successful validation.\n * @param schema - The schema to validate against.\n * @param value - The value to validate.\n * @param convert - When `true`, the validator coerces values to their target types (e.g. string\n * `\"1\"` → number `1`). Defaults to `false` to prevent silent type coercion.\n * @returns The validated (and optionally coerced) value typed as `T`.\n * @throws {@link ValidationException} when `value` does not satisfy `schema`.\n */\nexport const validateOrThrow = <T>(schema: Schema, value: unknown, convert: boolean = false): T => {\n const { value: returnable, error } = schema.validate(value, { abortEarly: false, convert })\n if (error) {\n throw new ValidationException(error)\n }\n return returnable as T\n}\n\n/**\n * Validates `value` against `schema` asynchronously and returns the coerced result typed as `T`.\n *\n * @remarks\n * Collects all field errors before throwing. Prefer this over {@link validateOrThrow} when the\n * schema includes async custom validators.\n *\n * @typeParam T - The expected type of the validated and coerced return value.\n * @param schema - The schema to validate against.\n * @param value - The value to validate.\n * @param convert - When `true`, the validator coerces values to their target types (e.g. string\n * `\"1\"` → number `1`). Defaults to `false` to prevent silent type coercion.\n * @returns The validated (and optionally coerced) value typed as `T`.\n * @throws {@link ValidationException} when `value` does not satisfy `schema`.\n */\nexport const asyncValidateOrThrow = async <T>(\n schema: Schema,\n value: unknown,\n convert: boolean = false\n): Promise<T> => {\n try {\n return await schema.validateAsync(value, { abortEarly: false, convert })\n } catch (error) {\n if (isValidationError(error)) {\n throw new ValidationException(error)\n }\n throw error\n }\n}\n","import { passesSchema } from './validation'\nimport { validator } from '@nhtio/validation'\nimport { printf as format } from 'fast-printf'\nimport { BaseException } from '../classes/base_exception'\n\n/**\n * Options accepted by {@link @nhtio/adk!BaseException} (and factory-created exceptions) beyond the\n * standard `ErrorOptions`.\n *\n * @remarks\n * These mirror the static defaults on {@link @nhtio/adk!BaseException} but allow per-throw overrides so a\n * single exception class can carry different metadata at different throw sites.\n */\nexport type ExceptionOptions = ErrorOptions & {\n code?: string\n status?: number\n fatal?: boolean\n}\n\n/**\n * Constructor signature of an exception class produced by {@link createException}.\n *\n * @typeParam T - Tuple of printf-style format argument types. When `T` is an empty tuple the\n * constructor takes no positional message arguments; when non-empty the first argument must be\n * an array of values matching `T`.\n */\nexport type CreatedException<T extends any[] = []> = typeof BaseException &\n (T extends []\n ? {\n new (options?: ExceptionOptions): BaseException\n }\n : { new (args: T, options?: ExceptionOptions): BaseException })\n\n/**\n * Factory that produces a named {@link @nhtio/adk!BaseException} subclass with a fixed printf-style message\n * template, error code, HTTP status, and fatality flag.\n *\n * @remarks\n * Prefer this over hand-writing subclasses for simple, static exception definitions.\n *\n * @typeParam T - Tuple of printf format argument types. Pass a non-empty tuple to require\n * callers to supply interpolation values at the throw site.\n *\n * @param name - The `name` property set on thrown instances (used by {@link isNamedException}).\n * @param message - Printf-style template string for the error message.\n * @param code - Machine-readable error code stored on the static and instance `code` property.\n * @param status - HTTP status code associated with this exception class.\n * @param fatal - When `true`, signals that the error is unrecoverable.\n * @returns A constructor for a {@link @nhtio/adk!BaseException} subclass with the given metadata baked in.\n *\n * @example\n * ```ts\n * export const E_NOT_FOUND = createException<[string]>(\n * 'E_NOT_FOUND', 'Resource %s not found', 'E_NOT_FOUND', 404, false\n * )\n * throw new E_NOT_FOUND(['my-id'])\n * ```\n */\nexport const createException = <T extends any[] = []>(\n name: string,\n message: string,\n code: string,\n status?: number,\n fatal?: boolean\n): CreatedException<T> => {\n const Ctor = class extends BaseException {\n static message = message\n static code = code\n static status = status\n static fatal = fatal\n constructor(args?: T | ExceptionOptions, options?: ExceptionOptions) {\n const hasMessageArgs = Array.isArray(args)\n const messageArgs = hasMessageArgs ? args : []\n const errorOptions = hasMessageArgs ? options : args\n\n super(format(message, ...messageArgs), errorOptions)\n this.name = name\n }\n }\n // Without this, the factory returns an anonymous class — constructor.name is \"\" and\n // cross-realm `isInstanceOf(err, 'E_FOO')` (which falls back to constructor-name comparison)\n // never matches. Setting the name on the class itself makes the identity carry through.\n Object.defineProperty(Ctor, 'name', { value: name, configurable: true })\n return Ctor as unknown as CreatedException<T>\n}\n\n/**\n * Returns `true` if `value` is a {@link @nhtio/adk!BaseException} or satisfies its minimum duck-type shape.\n *\n * @remarks\n * The duck-typing path handles exceptions that cross module or realm boundaries where\n * `instanceof` would return `false` for structurally identical objects.\n *\n * @param value - The value to test.\n * @returns `true` when `value` conforms to the {@link @nhtio/adk!BaseException} shape.\n */\nexport const isException = (value: unknown): value is BaseException => {\n const schema = validator.alternatives(\n validator.object().instance(BaseException as any),\n validator.function().instance(BaseException as any),\n validator\n .object({\n name: validator.string().required(),\n message: validator.string().required(),\n help: validator.string().optional(),\n code: validator.string().optional(),\n status: validator.number().optional(),\n fatal: validator.boolean().optional(),\n })\n .unknown(true)\n )\n return passesSchema(schema, value)\n}\n\n/**\n * Narrows `value` to a {@link @nhtio/adk!BaseException} whose `name` property matches `name` exactly.\n *\n * @remarks\n * Useful for catching a specific factory-created exception by its string identifier when\n * `instanceof` checks are not available (e.g. across module boundaries).\n *\n * @param value - The value to test.\n * @param name - The exact string to compare against `value.name`.\n * @returns `true` when `value` is a {@link @nhtio/adk!BaseException} with the given `name`.\n */\nexport const isNamedException = (value: unknown, name: string): value is BaseException => {\n return isException(value) && value.name === name\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spooled_markdown_artifact-CALSDxIx.js","names":["#format","#resolveFormat","#resolveRecords","#parsed","#resolveIndex","#index","#frontmatter"],"sources":["../src/lib/classes/spooled_json_artifact.ts","../src/lib/classes/spooled_markdown_artifact.ts"],"sourcesContent":["import { default as JSON5 } from 'json5'\nimport { JSONPath } from 'jsonpath-plus'\nimport { validator } from '@nhtio/validation'\nimport { ArtifactTool } from './artifact_tool'\nimport { ToolRegistry } from './tool_registry'\nimport { isInstanceOf, isObject } from '../utils/guards'\nimport { SpooledArtifact, defaultSerialise } from './spooled_artifact'\nimport type { SpoolReader } from '../contracts/spool_reader'\nimport type { ToolMethodDescriptor } from './spooled_artifact'\nimport type { DispatchContext } from '../contracts/dispatch_context'\n\n/**\n * The set of JSON-derived formats that {@link SpooledJsonArtifact} can handle.\n *\n * @remarks\n * - `json` — a single JSON value spanning the entire artifact (strict RFC 8259).\n * - `json5` — a single JSON5 value spanning the entire artifact; permits comments, trailing\n * commas, unquoted keys, and other relaxed syntax via the `json5` package.\n * - `jsonl` — newline-delimited JSON; each non-empty line is an independent JSON value.\n * - `ndjson` — alias for `jsonl`; both names are accepted and behave identically.\n */\nexport type JsonArtifactFormat = 'json' | 'json5' | 'jsonl' | 'ndjson'\n\n/**\n * Detects the {@link JsonArtifactFormat} of a raw string.\n *\n * @remarks\n * Detection strategy (in order):\n * 1. If the content parses as strict JSON → `json`.\n * 2. If every non-empty line parses as strict JSON → `jsonl`.\n * 3. If the content parses as JSON5 → `json5`.\n * 4. Otherwise throws.\n *\n * Strict JSON is tried before JSON5 so that well-formed JSON files are not unnecessarily\n * classified as JSON5.\n *\n * @param content - The full artifact text to inspect.\n * @returns The inferred format.\n * @throws `Error` when the content cannot be classified as any supported JSON format.\n */\nfunction inferFormat(content: string): JsonArtifactFormat {\n const trimmed = content.trim()\n\n // 1. Try strict JSON\n try {\n JSON.parse(trimmed)\n return 'json'\n } catch {\n // fall through\n }\n\n // 2. Try JSONL (every non-empty line is valid JSON)\n const nonEmptyLines = trimmed.split('\\n').filter((l) => l.trim().length > 0)\n if (\n nonEmptyLines.length > 0 &&\n nonEmptyLines.every((l) => {\n try {\n JSON.parse(l)\n return true\n } catch {\n return false\n }\n })\n ) {\n return 'jsonl'\n }\n\n // 3. Try JSON5\n try {\n JSON5.parse(trimmed)\n return 'json5'\n } catch {\n // fall through\n }\n\n throw new Error('Unable to infer JSON format: content is not valid JSON, JSONL, NDJSON, or JSON5')\n}\n\n/**\n * A {@link @nhtio/adk!SpooledArtifact} specialisation that adds JSON-aware read operations.\n *\n * @typeParam T - The expected shape of each parsed record. Defaults to `unknown`.\n *\n * @remarks\n * Construct with an optional `format` hint. When omitted the format is auto-detected on first\n * access by reading the full artifact and running {@link inferFormat}. Once detected (or\n * provided), the format is cached for the lifetime of the instance.\n *\n * All JSON methods are async, consistent with {@link @nhtio/adk!SpooledArtifact}.\n *\n * Path-based methods (`json_get`, `json_filter`, `json_pluck`) use\n * [JSONPath-Plus](https://github.com/JSONPath-Plus/JSONPath) expressions. Full JSONPath syntax\n * is supported, including recursive descent (`..`), filter expressions (`[?(@.age > 18)]`),\n * and union selectors.\n */\nexport class SpooledJsonArtifact<T = unknown> extends SpooledArtifact {\n #format: JsonArtifactFormat | undefined\n #parsed: T[] | undefined\n\n /**\n * @param reader - The backing store to read from.\n * @param format - Optional format hint. When omitted, the format is inferred on first access.\n */\n constructor(reader: SpoolReader, format?: JsonArtifactFormat) {\n super(reader)\n this.#format = format\n }\n\n /**\n * Returns `true` if `value` is a {@link SpooledJsonArtifact} instance.\n *\n * @remarks\n * Uses the cross-realm-safe {@link @nhtio/adk!isInstanceOf} guard: `instanceof` first, then\n * `Symbol.hasInstance`, then a `constructor.name` fallback. Matches the pattern used by every\n * other class guard in the ADK; safe against the dual-module-copy case where two distinct\n * `SpooledJsonArtifact` classes coexist in the same realm.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link SpooledJsonArtifact} instance.\n */\n public static isSpooledJsonArtifact(value: unknown): value is SpooledJsonArtifact {\n return isInstanceOf(value, 'SpooledJsonArtifact', SpooledJsonArtifact)\n }\n\n /**\n * The JSON-specific artifact-query descriptors this class adds on top of the base set.\n *\n * @remarks\n * Lists `artifact_json_type`, `artifact_json_keys`, `artifact_json_length`,\n * `artifact_json_get`, `artifact_json_filter`, `artifact_json_slice`, `artifact_json_pluck`.\n * The base seven descriptors (`artifact_head`, etc.) are NOT included here — they are\n * forged separately by {@link SpooledJsonArtifact.forgeTools}, which calls\n * `SpooledArtifact.forgeTools(ctx)` to produce the base-narrowed tools and then registers\n * its own JSON tools on the result. Downstream consumers building custom subclasses\n * should follow the same pattern: own only your own descriptors; override `forgeTools` to\n * compose with the base output.\n */\n public static toolMethods: ReadonlyArray<ToolMethodDescriptor> = Object.freeze([\n {\n name: 'artifact_json_type',\n method: 'json_type',\n description:\n 'Return the JSON format (json | json5 | jsonl | ndjson) of a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({}),\n },\n {\n name: 'artifact_json_keys',\n method: 'json_keys',\n description: 'Return the top-level keys of a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({}),\n },\n {\n name: 'artifact_json_length',\n method: 'json_length',\n description:\n 'Return the record count of a JSON artifact produced earlier in this turn (1 for json/json5; line count for jsonl/ndjson).',\n argsSchema: validator.object({}),\n },\n {\n name: 'artifact_json_get',\n method: 'json_get',\n description:\n 'Evaluate a JSONPath expression against a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({\n path: validator.string().required().description(\"JSONPath expression, e.g. '$.user.name'.\"),\n }),\n },\n {\n name: 'artifact_json_filter',\n method: 'json_filter',\n description:\n 'Return records of a JSON artifact (produced earlier in this turn) matched by a JSONPath filter.',\n argsSchema: validator.object({\n path: validator\n .string()\n .required()\n .description(\"JSONPath filter expression, e.g. '$[?(@.age>18)]'.\"),\n }),\n },\n {\n name: 'artifact_json_slice',\n method: 'json_slice',\n description:\n 'Return a slice of records by index range from a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({\n start: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start index (inclusive).'),\n end: validator.number().integer().min(0).optional().description('End index (exclusive).'),\n }),\n },\n {\n name: 'artifact_json_pluck',\n method: 'json_pluck',\n description:\n 'Return all values matched by a JSONPath expression across every record of a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({\n path: validator.string().required().description(\"JSONPath expression, e.g. '$..name'.\"),\n }),\n },\n ])\n\n /**\n * Forges base-class tools plus JSON-specific tools narrowed to {@link SpooledJsonArtifact}.\n *\n * @remarks\n * Standard subclass extension pattern: call `SpooledArtifact.forgeTools(ctx)` to produce\n * the base seven `artifact_*` tools narrowed to any `SpooledArtifact` in the turn, then\n * register one `ArtifactTool` per JSON-specific descriptor narrowed to JSON artifacts.\n * Downstream consumers building their own subclasses should follow the same shape.\n */\n public static override forgeTools(ctx: DispatchContext): ToolRegistry {\n const registry = SpooledArtifact.forgeTools(ctx)\n const requires = SpooledJsonArtifact\n const compatibleIds = [...ctx.turnToolCalls]\n .filter((tc) => !tc.fromArtifactTool && isInstanceOf(tc.results, requires.name, requires))\n .map((tc) => tc.id)\n if (compatibleIds.length === 0) return registry\n\n for (const descriptor of this.toolMethods) {\n const callIdSchema = validator\n .string()\n .valid(...compatibleIds)\n .required()\n .description('ToolCall id of the artifact to query.')\n\n const argsSchema = (\n descriptor.argsSchema ?? validator.object<Record<string, never>>({})\n ).append({\n callId: callIdSchema,\n })\n\n const tool = new ArtifactTool({\n name: descriptor.name,\n description: descriptor.description,\n inputSchema: argsSchema,\n ephemeral: true,\n onCollision: 'replace',\n handler: async (rawArgs, ctxInner) => {\n const args = rawArgs as Record<string, unknown> & { callId: string }\n const tc = [...ctxInner.turnToolCalls].find((t) => t.id === args.callId)\n if (!tc) {\n return `Error: no tool call with id ${args.callId} in this turn`\n }\n const artifact = tc.results\n if (!isInstanceOf(artifact, requires.name, requires)) {\n return `Error: tool call ${args.callId} results are not a ${requires.name} instance`\n }\n const methodArgs: unknown[] = []\n if (\n descriptor.method === 'json_get' ||\n descriptor.method === 'json_filter' ||\n descriptor.method === 'json_pluck'\n ) {\n methodArgs.push(args.path as string)\n } else if (descriptor.method === 'json_slice') {\n methodArgs.push(args.start as number | undefined, args.end as number | undefined)\n }\n const fn = (artifact as unknown as Record<string, (...a: unknown[]) => unknown>)[\n descriptor.method\n ]\n if (typeof fn !== 'function') {\n return `Error: artifact has no method ${descriptor.method}`\n }\n const result = await Promise.resolve(fn.apply(artifact, methodArgs))\n const serialise = descriptor.serialise ?? defaultSerialise\n return serialise(result)\n },\n })\n registry.register(tool)\n }\n return registry\n }\n\n /**\n * Resolves and caches the detected or provided format.\n */\n async #resolveFormat(): Promise<JsonArtifactFormat> {\n if (this.#format !== undefined) {\n return this.#format\n }\n const lines = await this.cat()\n this.#format = inferFormat(lines.join('\\n'))\n return this.#format\n }\n\n /**\n * Parses and caches all records from the artifact.\n *\n * @remarks\n * For `json`/`json5` format: returns a single-element array containing the parsed root value.\n * For `jsonl`/`ndjson` format: returns one element per non-empty line.\n */\n async #resolveRecords(): Promise<T[]> {\n if (this.#parsed !== undefined) {\n return this.#parsed\n }\n const format = await this.#resolveFormat()\n const lines = await this.cat()\n if (format === 'json') {\n this.#parsed = [JSON.parse(lines.join('\\n')) as T]\n } else if (format === 'json5') {\n this.#parsed = [JSON5.parse(lines.join('\\n')) as T]\n } else {\n // jsonl / ndjson\n this.#parsed = lines.filter((l) => l.trim().length > 0).map((l) => JSON.parse(l) as T)\n }\n return this.#parsed\n }\n\n /**\n * Returns the detected or provided format for this artifact.\n *\n * @returns One of `'json'`, `'json5'`, `'jsonl'`, or `'ndjson'`.\n */\n async json_type(): Promise<JsonArtifactFormat> {\n return this.#resolveFormat()\n }\n\n /**\n * Returns the top-level keys of the parsed content.\n *\n * @remarks\n * - For `json`/`json5`: returns the keys of the root object, or `undefined` when the root is\n * not a plain object (e.g. an array or scalar).\n * - For `jsonl`/`ndjson`: returns the union of keys across all records that are plain objects.\n * Duplicate keys are deduplicated.\n *\n * @returns Array of key strings, or `undefined` when no object keys are present.\n */\n async json_keys(): Promise<string[] | undefined> {\n const records = await this.#resolveRecords()\n const format = await this.#resolveFormat()\n if (format === 'json' || format === 'json5') {\n const root = records[0]\n if (isObject(root)) {\n return Object.keys(root as object)\n }\n return undefined\n }\n const keySet = new Set<string>()\n for (const record of records) {\n if (isObject(record)) {\n for (const key of Object.keys(record as object)) {\n keySet.add(key)\n }\n }\n }\n return keySet.size > 0 ? Array.from(keySet) : undefined\n }\n\n /**\n * Returns the total number of records in the artifact.\n *\n * @remarks\n * - For `json`/`json5`: always `1` (the entire artifact is a single value).\n * - For `jsonl`/`ndjson`: the number of non-empty lines.\n *\n * @returns The record count.\n */\n async json_length(): Promise<number> {\n const records = await this.#resolveRecords()\n return records.length\n }\n\n /**\n * Evaluates a JSONPath expression against the parsed content.\n *\n * @remarks\n * Uses [JSONPath-Plus](https://github.com/JSONPath-Plus/JSONPath). Full JSONPath syntax is\n * supported: recursive descent (`$..*`), filter expressions (`$[?(@.age > 18)]`), union\n * selectors, and more.\n *\n * - For `json`/`json5`: evaluates the expression against the root value.\n * - For `jsonl`/`ndjson`: evaluates the expression against each record and returns a flat\n * array of all matches across all records.\n *\n * @param path - A JSONPath expression (e.g. `'$.user.address.city'`, `'$..name'`).\n * @returns Array of matched values. Empty array when no matches are found.\n */\n async json_get(path: string): Promise<unknown[]> {\n const records = await this.#resolveRecords()\n const format = await this.#resolveFormat()\n if (format === 'json' || format === 'json5') {\n return JSONPath({ path, json: records[0] as object })\n }\n return records.flatMap((r) => JSONPath({ path, json: r as object }))\n }\n\n /**\n * Returns a slice of the parsed records by index range.\n *\n * @remarks\n * For `json`/`json5`: always returns `[root]` — the artifact is a single record so slicing is\n * not meaningful. For `jsonl`/`ndjson`: behaves like `Array.prototype.slice`.\n *\n * @param start - Start index (inclusive). Defaults to `0`.\n * @param end - End index (exclusive). Defaults to the record count.\n * @returns Array of sliced records.\n */\n async json_slice(start?: number, end?: number): Promise<T[]> {\n const records = await this.#resolveRecords()\n const format = await this.#resolveFormat()\n if (format === 'json' || format === 'json5') {\n return records\n }\n return records.slice(start, end)\n }\n\n /**\n * Returns records matched by a JSONPath filter expression.\n *\n * @remarks\n * Evaluates `path` against each record and returns those for which the expression produces at\n * least one match. For `json`/`json5`, evaluates against the root value and returns it in an\n * array if matched.\n *\n * @param path - A JSONPath expression (e.g. `'$[?(@.status === \"active\")]'`).\n * @returns Array of matching records.\n */\n async json_filter(path: string): Promise<T[]> {\n const records = await this.#resolveRecords()\n return records.filter((r) => {\n const matches = JSONPath({ path, json: r as object })\n return Array.isArray(matches) && matches.length > 0\n })\n }\n\n /**\n * Returns all values matched by a JSONPath expression across every record.\n *\n * @remarks\n * Convenience over {@link SpooledJsonArtifact.json_get} with an identical signature — use\n * whichever name better communicates intent at the call site. `json_pluck` reads well for\n * extracting a single field column; `json_get` reads well for structured queries.\n *\n * @param path - A JSONPath expression (e.g. `'$..name'`).\n * @returns Array of matched values.\n */\n async json_pluck(path: string): Promise<unknown[]> {\n return this.json_get(path)\n }\n}\n","import { remark } from 'remark'\nimport { visit } from 'unist-util-visit'\nimport { load as yamlLoad } from 'js-yaml'\nimport { validator } from '@nhtio/validation'\nimport { isInstanceOf } from '../utils/guards'\nimport { ArtifactTool } from './artifact_tool'\nimport { ToolRegistry } from './tool_registry'\nimport { default as remarkGfm } from 'remark-gfm'\nimport { toString as mdastToString } from 'mdast-util-to-string'\nimport { default as remarkFrontmatter } from 'remark-frontmatter'\nimport { SpooledArtifact, defaultSerialise } from './spooled_artifact'\nimport type { Root, Link, Image } from 'mdast'\nimport type { SpoolReader } from '../contracts/spool_reader'\nimport type { ToolMethodDescriptor } from './spooled_artifact'\nimport type { DispatchContext } from '../contracts/dispatch_context'\n\n/**\n * A single heading entry in the document's structural index.\n *\n * @remarks\n * `startLine` is the 0-based line of the heading itself. `endLine` is the 0-based index of the\n * last line belonging to this section (inclusive) — the line immediately before the next heading\n * of equal or lesser depth, or the last line of the document.\n */\nexport interface MarkdownHeadingEntry {\n /** ATX heading depth: 1 (`#`) through 6 (`######`). */\n depth: 1 | 2 | 3 | 4 | 5 | 6\n /** The heading text with the leading `#` prefix stripped and trimmed. */\n text: string\n /** 0-based line index of the heading line itself. */\n startLine: number\n /** 0-based line index of the last line in this section (inclusive). */\n endLine: number\n}\n\n/**\n * A single fenced code block entry in the document's structural index.\n */\nexport interface MarkdownCodeEntry {\n /** The language identifier immediately after the opening fence, or `null` when absent. */\n lang: string | null\n /** 0-based line index of the opening fence line. */\n startLine: number\n /** 0-based line index of the closing fence line. */\n endLine: number\n}\n\ninterface MarkdownIndex {\n headings: MarkdownHeadingEntry[]\n codeBlocks: MarkdownCodeEntry[]\n}\n\n/**\n * A section of a markdown document as returned by {@link SpooledMarkdownArtifact.md_sections}.\n *\n * @remarks\n * Contains only line-range metadata — no content is fetched until the caller explicitly\n * requests it via `cat(bodyStartLine, bodyEndLine + 1)`.\n */\nexport interface MarkdownSection {\n depth: 1 | 2 | 3 | 4 | 5 | 6\n /** The heading text. */\n heading: string\n /** 0-based line of the heading itself. */\n headingLine: number\n /** 0-based line of the first body line (heading line + 1). */\n bodyStartLine: number\n /** 0-based line of the last body line (inclusive). */\n bodyEndLine: number\n}\n\n/**\n * Returns a configured remark processor with frontmatter and GFM support.\n */\nfunction processor() {\n return remark().use(remarkFrontmatter).use(remarkGfm)\n}\n\n/**\n * Parses a heading line (e.g. `## My Heading`) and returns `{ depth, text }`, or `null` when\n * the line is not an ATX heading.\n */\nfunction parseHeadingLine(line: string): { depth: 1 | 2 | 3 | 4 | 5 | 6; text: string } | null {\n const match = /^(#{1,6})\\s+(.*)$/.exec(line)\n if (!match) return null\n const depth = match[1].length as 1 | 2 | 3 | 4 | 5 | 6\n return { depth, text: match[2].trim() }\n}\n\n/**\n * Returns the length of a fence marker at the start of `line` (3+), or `0` if the line is not\n * a fence opener/closer. Handles both backtick (` ``` `) and tilde (`~~~`) fences.\n */\nfunction fenceLength(line: string): number {\n const trimmed = line.trimStart()\n const match = /^(`{3,}|~{3,})/.exec(trimmed)\n return match ? match[1].length : 0\n}\n\n/**\n * Extracts the language identifier from a fence opener line (e.g. ` ```ts ` → `'ts'`), or\n * `null` when none is present.\n */\nfunction fenceLang(line: string): string | null {\n const trimmed = line.trimStart()\n const match = /^(?:`{3,}|~{3,})(\\S+)/.exec(trimmed)\n return match ? match[1] : null\n}\n\n/**\n * A {@link @nhtio/adk!SpooledArtifact} specialisation that adds markdown-aware structural queries.\n *\n * @remarks\n * Designed for large markdown documents where loading the full content into memory is\n * impractical. The structural index (heading positions, code block positions) is built by a\n * single line-by-line scan of the {@link @nhtio/adk!SpoolReader} without retaining any content. Only the\n * tiny metadata index and the parsed frontmatter object are cached.\n *\n * Content retrieval is always bounded — use `cat(start, end)` or the `startLine`/`endLine`\n * parameters on inline methods to fetch only the lines you need.\n *\n * Inline methods (`md_links`, `md_images`, `md_text`, `md_ast`) accept optional line-range\n * arguments. Without a range they read the full document — documented trade-off, caller\n * responsibility to bound the range for large documents.\n *\n * The processor always applies `remark-gfm` (tables, task lists, strikethrough, autolinks)\n * in addition to standard CommonMark and YAML frontmatter.\n */\nexport class SpooledMarkdownArtifact extends SpooledArtifact {\n #index: MarkdownIndex | undefined\n #frontmatter: Record<string, unknown> | null | undefined\n\n /**\n * @param reader - The backing store to read from.\n */\n constructor(reader: SpoolReader) {\n super(reader)\n }\n\n /**\n * Returns `true` if `value` is a {@link SpooledMarkdownArtifact} instance.\n *\n * @remarks\n * Uses the cross-realm-safe {@link @nhtio/adk!isInstanceOf} guard: `instanceof` first, then\n * `Symbol.hasInstance`, then a `constructor.name` fallback. Matches the pattern used by every\n * other class guard in the ADK; safe against the dual-module-copy case where two distinct\n * `SpooledMarkdownArtifact` classes coexist in the same realm.\n */\n public static isSpooledMarkdownArtifact(value: unknown): value is SpooledMarkdownArtifact {\n return isInstanceOf(value, 'SpooledMarkdownArtifact', SpooledMarkdownArtifact)\n }\n\n /**\n * The markdown-specific artifact-query descriptors this class adds on top of the base set.\n *\n * @remarks\n * Lists `artifact_md_frontmatter`, `artifact_md_headings`, `artifact_md_code_blocks`,\n * `artifact_md_sections`, `artifact_md_links`, `artifact_md_images`, `artifact_md_text`,\n * `artifact_md_ast`. The base seven descriptors (`artifact_head`, etc.) are NOT included\n * here — they are forged separately by {@link SpooledMarkdownArtifact.forgeTools}, which\n * calls `SpooledArtifact.forgeTools(ctx)` to produce the base-narrowed tools and then\n * registers its own markdown tools on the result. Downstream consumers building custom\n * subclasses should follow the same pattern: own only your own descriptors; override\n * `forgeTools` to compose with the base output.\n */\n public static toolMethods: ReadonlyArray<ToolMethodDescriptor> = Object.freeze([\n {\n name: 'artifact_md_frontmatter',\n method: 'md_frontmatter',\n description:\n 'Return parsed YAML frontmatter (or undefined) from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({}),\n },\n {\n name: 'artifact_md_headings',\n method: 'md_headings',\n description:\n 'Return all headings, optionally filtered by depth, from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n depth: validator\n .number()\n .integer()\n .min(1)\n .max(6)\n .optional()\n .description('ATX heading depth (1-6).'),\n }),\n },\n {\n name: 'artifact_md_code_blocks',\n method: 'md_code_blocks',\n description:\n 'Return all fenced code block entries, optionally filtered by language, from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n lang: validator\n .string()\n .optional()\n .description('Language identifier. Pass empty string to match blocks with no lang.'),\n }),\n },\n {\n name: 'artifact_md_sections',\n method: 'md_sections',\n description:\n 'Return document sections (line-range metadata only) from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n depth: validator\n .number()\n .integer()\n .min(1)\n .max(6)\n .optional()\n .description('ATX heading depth (1-6).'),\n }),\n },\n {\n name: 'artifact_md_links',\n method: 'md_links',\n description:\n 'Return all inline and reference links within the given line range from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n startLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start line (inclusive).'),\n endLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('End line (exclusive).'),\n }),\n },\n {\n name: 'artifact_md_images',\n method: 'md_images',\n description:\n 'Return all images within the given line range from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n startLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start line (inclusive).'),\n endLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('End line (exclusive).'),\n }),\n },\n {\n name: 'artifact_md_text',\n method: 'md_text',\n description:\n 'Return plain text with markup stripped, for the given line range, from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n startLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start line (inclusive).'),\n endLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('End line (exclusive).'),\n }),\n },\n {\n name: 'artifact_md_ast',\n method: 'md_ast',\n description:\n 'Return the full MDAST Root for the specified line range from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n startLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start line (inclusive).'),\n endLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('End line (exclusive).'),\n }),\n },\n ])\n\n /**\n * Forges base-class tools plus markdown-specific tools narrowed to\n * {@link SpooledMarkdownArtifact}.\n *\n * @remarks\n * Standard subclass extension pattern: call `SpooledArtifact.forgeTools(ctx)` to produce\n * the base seven `artifact_*` tools narrowed to any `SpooledArtifact` in the turn, then\n * register one `ArtifactTool` per markdown-specific descriptor narrowed to markdown\n * artifacts. Downstream consumers building their own subclasses should follow the same\n * shape.\n */\n public static override forgeTools(ctx: DispatchContext): ToolRegistry {\n const registry = SpooledArtifact.forgeTools(ctx)\n const requires = SpooledMarkdownArtifact\n const compatibleIds = [...ctx.turnToolCalls]\n .filter((tc) => !tc.fromArtifactTool && isInstanceOf(tc.results, requires.name, requires))\n .map((tc) => tc.id)\n if (compatibleIds.length === 0) return registry\n\n for (const descriptor of this.toolMethods) {\n const callIdSchema = validator\n .string()\n .valid(...compatibleIds)\n .required()\n .description('ToolCall id of the artifact to query.')\n\n const argsSchema = (\n descriptor.argsSchema ?? validator.object<Record<string, never>>({})\n ).append({\n callId: callIdSchema,\n })\n\n const tool = new ArtifactTool({\n name: descriptor.name,\n description: descriptor.description,\n inputSchema: argsSchema,\n ephemeral: true,\n onCollision: 'replace',\n handler: async (rawArgs, ctxInner) => {\n const args = rawArgs as Record<string, unknown> & { callId: string }\n const tc = [...ctxInner.turnToolCalls].find((t) => t.id === args.callId)\n if (!tc) {\n return `Error: no tool call with id ${args.callId} in this turn`\n }\n const artifact = tc.results\n if (!isInstanceOf(artifact, requires.name, requires)) {\n return `Error: tool call ${args.callId} results are not a ${requires.name} instance`\n }\n const methodArgs: unknown[] = []\n if (descriptor.method === 'md_headings' || descriptor.method === 'md_sections') {\n methodArgs.push(args.depth as number | undefined)\n } else if (descriptor.method === 'md_code_blocks') {\n methodArgs.push(args.lang as string | undefined)\n } else if (\n descriptor.method === 'md_links' ||\n descriptor.method === 'md_images' ||\n descriptor.method === 'md_text' ||\n descriptor.method === 'md_ast'\n ) {\n methodArgs.push(\n args.startLine as number | undefined,\n args.endLine as number | undefined\n )\n }\n const fn = (artifact as unknown as Record<string, (...a: unknown[]) => unknown>)[\n descriptor.method\n ]\n if (typeof fn !== 'function') {\n return `Error: artifact has no method ${descriptor.method}`\n }\n const result = await Promise.resolve(fn.apply(artifact, methodArgs))\n const serialise = descriptor.serialise ?? defaultSerialise\n return serialise(result)\n },\n })\n registry.register(tool)\n }\n return registry\n }\n\n /**\n * Builds the structural index in a single top-to-bottom pass, retaining only metadata.\n */\n async #resolveIndex(): Promise<MarkdownIndex> {\n if (this.#index !== undefined) return this.#index\n\n const count = await this.lineCount()\n const headingsRaw: Array<{ depth: 1 | 2 | 3 | 4 | 5 | 6; text: string; startLine: number }> = []\n const codeBlocks: MarkdownCodeEntry[] = []\n\n let inFrontmatter = false\n let frontmatterClosed = false\n let inCodeBlock = false\n let openFenceLen = 0\n let openFenceStartLine = 0\n let openFenceLang: string | null = null\n\n for (let i = 0; i < count; i++) {\n const rawLine = await this.line(i)\n const l = rawLine ?? ''\n\n // Handle frontmatter block at the top of the document\n if (i === 0 && l.trim() === '---') {\n inFrontmatter = true\n continue\n }\n if (inFrontmatter) {\n if (l.trim() === '---') {\n inFrontmatter = false\n frontmatterClosed = true\n }\n continue\n }\n if (!frontmatterClosed && i === 0) {\n // No frontmatter — treat as normal document from the start\n }\n\n // Handle fenced code blocks\n const fLen = fenceLength(l)\n if (!inCodeBlock && fLen >= 3) {\n inCodeBlock = true\n openFenceLen = fLen\n openFenceStartLine = i\n openFenceLang = fenceLang(l)\n continue\n }\n if (inCodeBlock) {\n // A closing fence must use the same fence character (` or ~) and be at least as long.\n if (fLen >= openFenceLen) {\n const openLine = (await this.line(openFenceStartLine)) ?? ''\n const openChar = openLine.trimStart()[0]\n const closeChar = l.trimStart()[0]\n if (closeChar === openChar) {\n codeBlocks.push({ lang: openFenceLang, startLine: openFenceStartLine, endLine: i })\n inCodeBlock = false\n openFenceLen = 0\n }\n }\n continue\n }\n\n // Detect ATX headings (not inside code blocks, not in frontmatter)\n const heading = parseHeadingLine(l)\n if (heading) {\n headingsRaw.push({ ...heading, startLine: i })\n }\n }\n\n // Unclosed code block — record it anyway\n if (inCodeBlock) {\n codeBlocks.push({ lang: openFenceLang, startLine: openFenceStartLine, endLine: count - 1 })\n }\n\n // Post-process heading endLine values\n const headings: MarkdownHeadingEntry[] = headingsRaw.map((h, idx) => {\n const nextBoundary = headingsRaw.slice(idx + 1).find((n) => n.depth <= h.depth)\n const endLine = nextBoundary ? nextBoundary.startLine - 1 : count - 1\n return { ...h, endLine }\n })\n\n this.#index = { headings, codeBlocks }\n return this.#index\n }\n\n // ── Frontmatter ───────────────────────────────────────────────────────────\n\n /**\n * Returns the parsed YAML frontmatter, or `undefined` when no frontmatter block is present.\n *\n * @remarks\n * Short-circuits after reading the frontmatter block — never reads the document body. Caches\n * the result so subsequent calls are free. The result is `undefined` (not an empty object)\n * when no frontmatter is found, distinguishing \"no frontmatter\" from \"empty frontmatter\".\n */\n async md_frontmatter(): Promise<Record<string, unknown> | undefined> {\n if (this.#frontmatter !== undefined) return this.#frontmatter ?? undefined\n\n const firstLine = await this.line(0)\n if (firstLine?.trim() !== '---') {\n this.#frontmatter = null\n return undefined\n }\n\n const maxScan = Math.min(await this.lineCount(), 200)\n const yamlLines: string[] = []\n let closed = false\n for (let i = 1; i < maxScan; i++) {\n const l = await this.line(i)\n if (l?.trim() === '---') {\n closed = true\n break\n }\n yamlLines.push(l ?? '')\n }\n\n if (!closed) {\n this.#frontmatter = null\n return undefined\n }\n\n this.#frontmatter = yamlLoad(yamlLines.join('\\n')) as Record<string, unknown>\n return this.#frontmatter\n }\n\n // ── Structural index queries ──────────────────────────────────────────────\n\n /**\n * Returns all headings in document order, optionally filtered by depth.\n *\n * @remarks\n * Uses the cached structural index — no content is fetched from the {@link @nhtio/adk!SpoolReader}.\n *\n * @param depth - When provided, only headings at this ATX depth (1–6) are returned.\n */\n async md_headings(depth?: 1 | 2 | 3 | 4 | 5 | 6): Promise<MarkdownHeadingEntry[]> {\n const index = await this.#resolveIndex()\n if (depth === undefined) return index.headings.slice()\n return index.headings.filter((h) => h.depth === depth)\n }\n\n /**\n * Returns all fenced code block entries, optionally filtered by language identifier.\n *\n * @remarks\n * Returns line-range metadata only — no content is fetched. Use `cat(entry.startLine + 1,\n * entry.endLine)` to retrieve the code body (excluding fence lines).\n *\n * @param lang - When provided, only blocks with this exact lang identifier are returned.\n * Pass an empty string to match blocks with no lang identifier.\n */\n async md_code_blocks(lang?: string): Promise<MarkdownCodeEntry[]> {\n const index = await this.#resolveIndex()\n if (lang === undefined) return index.codeBlocks.slice()\n const target = lang === '' ? null : lang\n return index.codeBlocks.filter((b) => b.lang === target)\n }\n\n /**\n * Returns document sections derived from the structural index.\n *\n * @remarks\n * Returns only line-range metadata — body content is never fetched. To retrieve the body of a\n * section, call `cat(section.bodyStartLine, section.bodyEndLine + 1)`.\n *\n * When `depth` is provided, only sections introduced by a heading at that depth are returned;\n * deeper headings become part of the body.\n *\n * @param depth - When provided, only sections at this ATX depth (1–6) are returned.\n */\n async md_sections(depth?: 1 | 2 | 3 | 4 | 5 | 6): Promise<MarkdownSection[]> {\n const index = await this.#resolveIndex()\n const headings =\n depth !== undefined ? index.headings.filter((h) => h.depth === depth) : index.headings\n return headings.map((h) => ({\n depth: h.depth,\n heading: h.text,\n headingLine: h.startLine,\n bodyStartLine: h.startLine + 1,\n bodyEndLine: h.endLine,\n }))\n }\n\n // ── Inline queries (bounded) ──────────────────────────────────────────────\n\n /**\n * Returns the full MDAST Root for the specified line range.\n *\n * @remarks\n * Without a range, reads the full document — for large documents, use\n * {@link SpooledMarkdownArtifact.md_sections} to locate sections and pass\n * bounded line ranges here.\n *\n * @param startLine - 0-based start line (inclusive). Defaults to `0`.\n * @param endLine - 0-based end line (exclusive). Defaults to `lineCount()`.\n */\n async md_ast(startLine?: number, endLine?: number): Promise<Root> {\n const lines = await this.cat(startLine, endLine)\n return processor().parse(lines.join('\\n')) as Root\n }\n\n /**\n * Returns all inline and reference links in the specified line range.\n *\n * @param startLine - 0-based start line (inclusive). Defaults to `0`.\n * @param endLine - 0-based end line (exclusive). Defaults to `lineCount()`.\n */\n async md_links(\n startLine?: number,\n endLine?: number\n ): Promise<Array<{ text: string; url: string; title?: string }>> {\n const lines = await this.cat(startLine, endLine)\n const ast = processor().parse(lines.join('\\n'))\n const results: Array<{ text: string; url: string; title?: string }> = []\n visit(ast, 'link', (node: Link) => {\n results.push({\n text: mdastToString(node),\n url: node.url,\n title: node.title ?? undefined,\n })\n })\n return results\n }\n\n /**\n * Returns all images in the specified line range.\n *\n * @param startLine - 0-based start line (inclusive). Defaults to `0`.\n * @param endLine - 0-based end line (exclusive). Defaults to `lineCount()`.\n */\n async md_images(\n startLine?: number,\n endLine?: number\n ): Promise<Array<{ alt: string; url: string; title?: string }>> {\n const lines = await this.cat(startLine, endLine)\n const ast = processor().parse(lines.join('\\n'))\n const results: Array<{ alt: string; url: string; title?: string }> = []\n visit(ast, 'image', (node: Image) => {\n results.push({\n alt: node.alt ?? '',\n url: node.url,\n title: node.title ?? undefined,\n })\n })\n return results\n }\n\n /**\n * Returns all document text with markup stripped, for the specified line range.\n *\n * @remarks\n * Uses `mdast-util-to-string` to extract plain text from the AST — code, link text, and\n * alt text are included; markdown syntax is removed.\n *\n * @param startLine - 0-based start line (inclusive). Defaults to `0`.\n * @param endLine - 0-based end line (exclusive). Defaults to `lineCount()`.\n */\n async md_text(startLine?: number, endLine?: number): Promise<string> {\n const lines = await this.cat(startLine, endLine)\n const ast = processor().parse(lines.join('\\n'))\n return mdastToString(ast)\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spooled_markdown_artifact-Ci5UL7l4.mjs","names":["#format","#resolveFormat","#resolveRecords","#parsed","#resolveIndex","#index","#frontmatter"],"sources":["../src/lib/classes/spooled_json_artifact.ts","../src/lib/classes/spooled_markdown_artifact.ts"],"sourcesContent":["import { default as JSON5 } from 'json5'\nimport { JSONPath } from 'jsonpath-plus'\nimport { validator } from '@nhtio/validation'\nimport { ArtifactTool } from './artifact_tool'\nimport { ToolRegistry } from './tool_registry'\nimport { isInstanceOf, isObject } from '../utils/guards'\nimport { SpooledArtifact, defaultSerialise } from './spooled_artifact'\nimport type { SpoolReader } from '../contracts/spool_reader'\nimport type { ToolMethodDescriptor } from './spooled_artifact'\nimport type { DispatchContext } from '../contracts/dispatch_context'\n\n/**\n * The set of JSON-derived formats that {@link SpooledJsonArtifact} can handle.\n *\n * @remarks\n * - `json` — a single JSON value spanning the entire artifact (strict RFC 8259).\n * - `json5` — a single JSON5 value spanning the entire artifact; permits comments, trailing\n * commas, unquoted keys, and other relaxed syntax via the `json5` package.\n * - `jsonl` — newline-delimited JSON; each non-empty line is an independent JSON value.\n * - `ndjson` — alias for `jsonl`; both names are accepted and behave identically.\n */\nexport type JsonArtifactFormat = 'json' | 'json5' | 'jsonl' | 'ndjson'\n\n/**\n * Detects the {@link JsonArtifactFormat} of a raw string.\n *\n * @remarks\n * Detection strategy (in order):\n * 1. If the content parses as strict JSON → `json`.\n * 2. If every non-empty line parses as strict JSON → `jsonl`.\n * 3. If the content parses as JSON5 → `json5`.\n * 4. Otherwise throws.\n *\n * Strict JSON is tried before JSON5 so that well-formed JSON files are not unnecessarily\n * classified as JSON5.\n *\n * @param content - The full artifact text to inspect.\n * @returns The inferred format.\n * @throws `Error` when the content cannot be classified as any supported JSON format.\n */\nfunction inferFormat(content: string): JsonArtifactFormat {\n const trimmed = content.trim()\n\n // 1. Try strict JSON\n try {\n JSON.parse(trimmed)\n return 'json'\n } catch {\n // fall through\n }\n\n // 2. Try JSONL (every non-empty line is valid JSON)\n const nonEmptyLines = trimmed.split('\\n').filter((l) => l.trim().length > 0)\n if (\n nonEmptyLines.length > 0 &&\n nonEmptyLines.every((l) => {\n try {\n JSON.parse(l)\n return true\n } catch {\n return false\n }\n })\n ) {\n return 'jsonl'\n }\n\n // 3. Try JSON5\n try {\n JSON5.parse(trimmed)\n return 'json5'\n } catch {\n // fall through\n }\n\n throw new Error('Unable to infer JSON format: content is not valid JSON, JSONL, NDJSON, or JSON5')\n}\n\n/**\n * A {@link @nhtio/adk!SpooledArtifact} specialisation that adds JSON-aware read operations.\n *\n * @typeParam T - The expected shape of each parsed record. Defaults to `unknown`.\n *\n * @remarks\n * Construct with an optional `format` hint. When omitted the format is auto-detected on first\n * access by reading the full artifact and running {@link inferFormat}. Once detected (or\n * provided), the format is cached for the lifetime of the instance.\n *\n * All JSON methods are async, consistent with {@link @nhtio/adk!SpooledArtifact}.\n *\n * Path-based methods (`json_get`, `json_filter`, `json_pluck`) use\n * [JSONPath-Plus](https://github.com/JSONPath-Plus/JSONPath) expressions. Full JSONPath syntax\n * is supported, including recursive descent (`..`), filter expressions (`[?(@.age > 18)]`),\n * and union selectors.\n */\nexport class SpooledJsonArtifact<T = unknown> extends SpooledArtifact {\n #format: JsonArtifactFormat | undefined\n #parsed: T[] | undefined\n\n /**\n * @param reader - The backing store to read from.\n * @param format - Optional format hint. When omitted, the format is inferred on first access.\n */\n constructor(reader: SpoolReader, format?: JsonArtifactFormat) {\n super(reader)\n this.#format = format\n }\n\n /**\n * Returns `true` if `value` is a {@link SpooledJsonArtifact} instance.\n *\n * @remarks\n * Uses the cross-realm-safe {@link @nhtio/adk!isInstanceOf} guard: `instanceof` first, then\n * `Symbol.hasInstance`, then a `constructor.name` fallback. Matches the pattern used by every\n * other class guard in the ADK; safe against the dual-module-copy case where two distinct\n * `SpooledJsonArtifact` classes coexist in the same realm.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link SpooledJsonArtifact} instance.\n */\n public static isSpooledJsonArtifact(value: unknown): value is SpooledJsonArtifact {\n return isInstanceOf(value, 'SpooledJsonArtifact', SpooledJsonArtifact)\n }\n\n /**\n * The JSON-specific artifact-query descriptors this class adds on top of the base set.\n *\n * @remarks\n * Lists `artifact_json_type`, `artifact_json_keys`, `artifact_json_length`,\n * `artifact_json_get`, `artifact_json_filter`, `artifact_json_slice`, `artifact_json_pluck`.\n * The base seven descriptors (`artifact_head`, etc.) are NOT included here — they are\n * forged separately by {@link SpooledJsonArtifact.forgeTools}, which calls\n * `SpooledArtifact.forgeTools(ctx)` to produce the base-narrowed tools and then registers\n * its own JSON tools on the result. Downstream consumers building custom subclasses\n * should follow the same pattern: own only your own descriptors; override `forgeTools` to\n * compose with the base output.\n */\n public static toolMethods: ReadonlyArray<ToolMethodDescriptor> = Object.freeze([\n {\n name: 'artifact_json_type',\n method: 'json_type',\n description:\n 'Return the JSON format (json | json5 | jsonl | ndjson) of a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({}),\n },\n {\n name: 'artifact_json_keys',\n method: 'json_keys',\n description: 'Return the top-level keys of a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({}),\n },\n {\n name: 'artifact_json_length',\n method: 'json_length',\n description:\n 'Return the record count of a JSON artifact produced earlier in this turn (1 for json/json5; line count for jsonl/ndjson).',\n argsSchema: validator.object({}),\n },\n {\n name: 'artifact_json_get',\n method: 'json_get',\n description:\n 'Evaluate a JSONPath expression against a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({\n path: validator.string().required().description(\"JSONPath expression, e.g. '$.user.name'.\"),\n }),\n },\n {\n name: 'artifact_json_filter',\n method: 'json_filter',\n description:\n 'Return records of a JSON artifact (produced earlier in this turn) matched by a JSONPath filter.',\n argsSchema: validator.object({\n path: validator\n .string()\n .required()\n .description(\"JSONPath filter expression, e.g. '$[?(@.age>18)]'.\"),\n }),\n },\n {\n name: 'artifact_json_slice',\n method: 'json_slice',\n description:\n 'Return a slice of records by index range from a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({\n start: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start index (inclusive).'),\n end: validator.number().integer().min(0).optional().description('End index (exclusive).'),\n }),\n },\n {\n name: 'artifact_json_pluck',\n method: 'json_pluck',\n description:\n 'Return all values matched by a JSONPath expression across every record of a JSON artifact produced earlier in this turn.',\n argsSchema: validator.object({\n path: validator.string().required().description(\"JSONPath expression, e.g. '$..name'.\"),\n }),\n },\n ])\n\n /**\n * Forges base-class tools plus JSON-specific tools narrowed to {@link SpooledJsonArtifact}.\n *\n * @remarks\n * Standard subclass extension pattern: call `SpooledArtifact.forgeTools(ctx)` to produce\n * the base seven `artifact_*` tools narrowed to any `SpooledArtifact` in the turn, then\n * register one `ArtifactTool` per JSON-specific descriptor narrowed to JSON artifacts.\n * Downstream consumers building their own subclasses should follow the same shape.\n */\n public static override forgeTools(ctx: DispatchContext): ToolRegistry {\n const registry = SpooledArtifact.forgeTools(ctx)\n const requires = SpooledJsonArtifact\n const compatibleIds = [...ctx.turnToolCalls]\n .filter((tc) => !tc.fromArtifactTool && isInstanceOf(tc.results, requires.name, requires))\n .map((tc) => tc.id)\n if (compatibleIds.length === 0) return registry\n\n for (const descriptor of this.toolMethods) {\n const callIdSchema = validator\n .string()\n .valid(...compatibleIds)\n .required()\n .description('ToolCall id of the artifact to query.')\n\n const argsSchema = (\n descriptor.argsSchema ?? validator.object<Record<string, never>>({})\n ).append({\n callId: callIdSchema,\n })\n\n const tool = new ArtifactTool({\n name: descriptor.name,\n description: descriptor.description,\n inputSchema: argsSchema,\n ephemeral: true,\n onCollision: 'replace',\n handler: async (rawArgs, ctxInner) => {\n const args = rawArgs as Record<string, unknown> & { callId: string }\n const tc = [...ctxInner.turnToolCalls].find((t) => t.id === args.callId)\n if (!tc) {\n return `Error: no tool call with id ${args.callId} in this turn`\n }\n const artifact = tc.results\n if (!isInstanceOf(artifact, requires.name, requires)) {\n return `Error: tool call ${args.callId} results are not a ${requires.name} instance`\n }\n const methodArgs: unknown[] = []\n if (\n descriptor.method === 'json_get' ||\n descriptor.method === 'json_filter' ||\n descriptor.method === 'json_pluck'\n ) {\n methodArgs.push(args.path as string)\n } else if (descriptor.method === 'json_slice') {\n methodArgs.push(args.start as number | undefined, args.end as number | undefined)\n }\n const fn = (artifact as unknown as Record<string, (...a: unknown[]) => unknown>)[\n descriptor.method\n ]\n if (typeof fn !== 'function') {\n return `Error: artifact has no method ${descriptor.method}`\n }\n const result = await Promise.resolve(fn.apply(artifact, methodArgs))\n const serialise = descriptor.serialise ?? defaultSerialise\n return serialise(result)\n },\n })\n registry.register(tool)\n }\n return registry\n }\n\n /**\n * Resolves and caches the detected or provided format.\n */\n async #resolveFormat(): Promise<JsonArtifactFormat> {\n if (this.#format !== undefined) {\n return this.#format\n }\n const lines = await this.cat()\n this.#format = inferFormat(lines.join('\\n'))\n return this.#format\n }\n\n /**\n * Parses and caches all records from the artifact.\n *\n * @remarks\n * For `json`/`json5` format: returns a single-element array containing the parsed root value.\n * For `jsonl`/`ndjson` format: returns one element per non-empty line.\n */\n async #resolveRecords(): Promise<T[]> {\n if (this.#parsed !== undefined) {\n return this.#parsed\n }\n const format = await this.#resolveFormat()\n const lines = await this.cat()\n if (format === 'json') {\n this.#parsed = [JSON.parse(lines.join('\\n')) as T]\n } else if (format === 'json5') {\n this.#parsed = [JSON5.parse(lines.join('\\n')) as T]\n } else {\n // jsonl / ndjson\n this.#parsed = lines.filter((l) => l.trim().length > 0).map((l) => JSON.parse(l) as T)\n }\n return this.#parsed\n }\n\n /**\n * Returns the detected or provided format for this artifact.\n *\n * @returns One of `'json'`, `'json5'`, `'jsonl'`, or `'ndjson'`.\n */\n async json_type(): Promise<JsonArtifactFormat> {\n return this.#resolveFormat()\n }\n\n /**\n * Returns the top-level keys of the parsed content.\n *\n * @remarks\n * - For `json`/`json5`: returns the keys of the root object, or `undefined` when the root is\n * not a plain object (e.g. an array or scalar).\n * - For `jsonl`/`ndjson`: returns the union of keys across all records that are plain objects.\n * Duplicate keys are deduplicated.\n *\n * @returns Array of key strings, or `undefined` when no object keys are present.\n */\n async json_keys(): Promise<string[] | undefined> {\n const records = await this.#resolveRecords()\n const format = await this.#resolveFormat()\n if (format === 'json' || format === 'json5') {\n const root = records[0]\n if (isObject(root)) {\n return Object.keys(root as object)\n }\n return undefined\n }\n const keySet = new Set<string>()\n for (const record of records) {\n if (isObject(record)) {\n for (const key of Object.keys(record as object)) {\n keySet.add(key)\n }\n }\n }\n return keySet.size > 0 ? Array.from(keySet) : undefined\n }\n\n /**\n * Returns the total number of records in the artifact.\n *\n * @remarks\n * - For `json`/`json5`: always `1` (the entire artifact is a single value).\n * - For `jsonl`/`ndjson`: the number of non-empty lines.\n *\n * @returns The record count.\n */\n async json_length(): Promise<number> {\n const records = await this.#resolveRecords()\n return records.length\n }\n\n /**\n * Evaluates a JSONPath expression against the parsed content.\n *\n * @remarks\n * Uses [JSONPath-Plus](https://github.com/JSONPath-Plus/JSONPath). Full JSONPath syntax is\n * supported: recursive descent (`$..*`), filter expressions (`$[?(@.age > 18)]`), union\n * selectors, and more.\n *\n * - For `json`/`json5`: evaluates the expression against the root value.\n * - For `jsonl`/`ndjson`: evaluates the expression against each record and returns a flat\n * array of all matches across all records.\n *\n * @param path - A JSONPath expression (e.g. `'$.user.address.city'`, `'$..name'`).\n * @returns Array of matched values. Empty array when no matches are found.\n */\n async json_get(path: string): Promise<unknown[]> {\n const records = await this.#resolveRecords()\n const format = await this.#resolveFormat()\n if (format === 'json' || format === 'json5') {\n return JSONPath({ path, json: records[0] as object })\n }\n return records.flatMap((r) => JSONPath({ path, json: r as object }))\n }\n\n /**\n * Returns a slice of the parsed records by index range.\n *\n * @remarks\n * For `json`/`json5`: always returns `[root]` — the artifact is a single record so slicing is\n * not meaningful. For `jsonl`/`ndjson`: behaves like `Array.prototype.slice`.\n *\n * @param start - Start index (inclusive). Defaults to `0`.\n * @param end - End index (exclusive). Defaults to the record count.\n * @returns Array of sliced records.\n */\n async json_slice(start?: number, end?: number): Promise<T[]> {\n const records = await this.#resolveRecords()\n const format = await this.#resolveFormat()\n if (format === 'json' || format === 'json5') {\n return records\n }\n return records.slice(start, end)\n }\n\n /**\n * Returns records matched by a JSONPath filter expression.\n *\n * @remarks\n * Evaluates `path` against each record and returns those for which the expression produces at\n * least one match. For `json`/`json5`, evaluates against the root value and returns it in an\n * array if matched.\n *\n * @param path - A JSONPath expression (e.g. `'$[?(@.status === \"active\")]'`).\n * @returns Array of matching records.\n */\n async json_filter(path: string): Promise<T[]> {\n const records = await this.#resolveRecords()\n return records.filter((r) => {\n const matches = JSONPath({ path, json: r as object })\n return Array.isArray(matches) && matches.length > 0\n })\n }\n\n /**\n * Returns all values matched by a JSONPath expression across every record.\n *\n * @remarks\n * Convenience over {@link SpooledJsonArtifact.json_get} with an identical signature — use\n * whichever name better communicates intent at the call site. `json_pluck` reads well for\n * extracting a single field column; `json_get` reads well for structured queries.\n *\n * @param path - A JSONPath expression (e.g. `'$..name'`).\n * @returns Array of matched values.\n */\n async json_pluck(path: string): Promise<unknown[]> {\n return this.json_get(path)\n }\n}\n","import { remark } from 'remark'\nimport { visit } from 'unist-util-visit'\nimport { load as yamlLoad } from 'js-yaml'\nimport { validator } from '@nhtio/validation'\nimport { isInstanceOf } from '../utils/guards'\nimport { ArtifactTool } from './artifact_tool'\nimport { ToolRegistry } from './tool_registry'\nimport { default as remarkGfm } from 'remark-gfm'\nimport { toString as mdastToString } from 'mdast-util-to-string'\nimport { default as remarkFrontmatter } from 'remark-frontmatter'\nimport { SpooledArtifact, defaultSerialise } from './spooled_artifact'\nimport type { Root, Link, Image } from 'mdast'\nimport type { SpoolReader } from '../contracts/spool_reader'\nimport type { ToolMethodDescriptor } from './spooled_artifact'\nimport type { DispatchContext } from '../contracts/dispatch_context'\n\n/**\n * A single heading entry in the document's structural index.\n *\n * @remarks\n * `startLine` is the 0-based line of the heading itself. `endLine` is the 0-based index of the\n * last line belonging to this section (inclusive) — the line immediately before the next heading\n * of equal or lesser depth, or the last line of the document.\n */\nexport interface MarkdownHeadingEntry {\n /** ATX heading depth: 1 (`#`) through 6 (`######`). */\n depth: 1 | 2 | 3 | 4 | 5 | 6\n /** The heading text with the leading `#` prefix stripped and trimmed. */\n text: string\n /** 0-based line index of the heading line itself. */\n startLine: number\n /** 0-based line index of the last line in this section (inclusive). */\n endLine: number\n}\n\n/**\n * A single fenced code block entry in the document's structural index.\n */\nexport interface MarkdownCodeEntry {\n /** The language identifier immediately after the opening fence, or `null` when absent. */\n lang: string | null\n /** 0-based line index of the opening fence line. */\n startLine: number\n /** 0-based line index of the closing fence line. */\n endLine: number\n}\n\ninterface MarkdownIndex {\n headings: MarkdownHeadingEntry[]\n codeBlocks: MarkdownCodeEntry[]\n}\n\n/**\n * A section of a markdown document as returned by {@link SpooledMarkdownArtifact.md_sections}.\n *\n * @remarks\n * Contains only line-range metadata — no content is fetched until the caller explicitly\n * requests it via `cat(bodyStartLine, bodyEndLine + 1)`.\n */\nexport interface MarkdownSection {\n depth: 1 | 2 | 3 | 4 | 5 | 6\n /** The heading text. */\n heading: string\n /** 0-based line of the heading itself. */\n headingLine: number\n /** 0-based line of the first body line (heading line + 1). */\n bodyStartLine: number\n /** 0-based line of the last body line (inclusive). */\n bodyEndLine: number\n}\n\n/**\n * Returns a configured remark processor with frontmatter and GFM support.\n */\nfunction processor() {\n return remark().use(remarkFrontmatter).use(remarkGfm)\n}\n\n/**\n * Parses a heading line (e.g. `## My Heading`) and returns `{ depth, text }`, or `null` when\n * the line is not an ATX heading.\n */\nfunction parseHeadingLine(line: string): { depth: 1 | 2 | 3 | 4 | 5 | 6; text: string } | null {\n const match = /^(#{1,6})\\s+(.*)$/.exec(line)\n if (!match) return null\n const depth = match[1].length as 1 | 2 | 3 | 4 | 5 | 6\n return { depth, text: match[2].trim() }\n}\n\n/**\n * Returns the length of a fence marker at the start of `line` (3+), or `0` if the line is not\n * a fence opener/closer. Handles both backtick (` ``` `) and tilde (`~~~`) fences.\n */\nfunction fenceLength(line: string): number {\n const trimmed = line.trimStart()\n const match = /^(`{3,}|~{3,})/.exec(trimmed)\n return match ? match[1].length : 0\n}\n\n/**\n * Extracts the language identifier from a fence opener line (e.g. ` ```ts ` → `'ts'`), or\n * `null` when none is present.\n */\nfunction fenceLang(line: string): string | null {\n const trimmed = line.trimStart()\n const match = /^(?:`{3,}|~{3,})(\\S+)/.exec(trimmed)\n return match ? match[1] : null\n}\n\n/**\n * A {@link @nhtio/adk!SpooledArtifact} specialisation that adds markdown-aware structural queries.\n *\n * @remarks\n * Designed for large markdown documents where loading the full content into memory is\n * impractical. The structural index (heading positions, code block positions) is built by a\n * single line-by-line scan of the {@link @nhtio/adk!SpoolReader} without retaining any content. Only the\n * tiny metadata index and the parsed frontmatter object are cached.\n *\n * Content retrieval is always bounded — use `cat(start, end)` or the `startLine`/`endLine`\n * parameters on inline methods to fetch only the lines you need.\n *\n * Inline methods (`md_links`, `md_images`, `md_text`, `md_ast`) accept optional line-range\n * arguments. Without a range they read the full document — documented trade-off, caller\n * responsibility to bound the range for large documents.\n *\n * The processor always applies `remark-gfm` (tables, task lists, strikethrough, autolinks)\n * in addition to standard CommonMark and YAML frontmatter.\n */\nexport class SpooledMarkdownArtifact extends SpooledArtifact {\n #index: MarkdownIndex | undefined\n #frontmatter: Record<string, unknown> | null | undefined\n\n /**\n * @param reader - The backing store to read from.\n */\n constructor(reader: SpoolReader) {\n super(reader)\n }\n\n /**\n * Returns `true` if `value` is a {@link SpooledMarkdownArtifact} instance.\n *\n * @remarks\n * Uses the cross-realm-safe {@link @nhtio/adk!isInstanceOf} guard: `instanceof` first, then\n * `Symbol.hasInstance`, then a `constructor.name` fallback. Matches the pattern used by every\n * other class guard in the ADK; safe against the dual-module-copy case where two distinct\n * `SpooledMarkdownArtifact` classes coexist in the same realm.\n */\n public static isSpooledMarkdownArtifact(value: unknown): value is SpooledMarkdownArtifact {\n return isInstanceOf(value, 'SpooledMarkdownArtifact', SpooledMarkdownArtifact)\n }\n\n /**\n * The markdown-specific artifact-query descriptors this class adds on top of the base set.\n *\n * @remarks\n * Lists `artifact_md_frontmatter`, `artifact_md_headings`, `artifact_md_code_blocks`,\n * `artifact_md_sections`, `artifact_md_links`, `artifact_md_images`, `artifact_md_text`,\n * `artifact_md_ast`. The base seven descriptors (`artifact_head`, etc.) are NOT included\n * here — they are forged separately by {@link SpooledMarkdownArtifact.forgeTools}, which\n * calls `SpooledArtifact.forgeTools(ctx)` to produce the base-narrowed tools and then\n * registers its own markdown tools on the result. Downstream consumers building custom\n * subclasses should follow the same pattern: own only your own descriptors; override\n * `forgeTools` to compose with the base output.\n */\n public static toolMethods: ReadonlyArray<ToolMethodDescriptor> = Object.freeze([\n {\n name: 'artifact_md_frontmatter',\n method: 'md_frontmatter',\n description:\n 'Return parsed YAML frontmatter (or undefined) from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({}),\n },\n {\n name: 'artifact_md_headings',\n method: 'md_headings',\n description:\n 'Return all headings, optionally filtered by depth, from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n depth: validator\n .number()\n .integer()\n .min(1)\n .max(6)\n .optional()\n .description('ATX heading depth (1-6).'),\n }),\n },\n {\n name: 'artifact_md_code_blocks',\n method: 'md_code_blocks',\n description:\n 'Return all fenced code block entries, optionally filtered by language, from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n lang: validator\n .string()\n .optional()\n .description('Language identifier. Pass empty string to match blocks with no lang.'),\n }),\n },\n {\n name: 'artifact_md_sections',\n method: 'md_sections',\n description:\n 'Return document sections (line-range metadata only) from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n depth: validator\n .number()\n .integer()\n .min(1)\n .max(6)\n .optional()\n .description('ATX heading depth (1-6).'),\n }),\n },\n {\n name: 'artifact_md_links',\n method: 'md_links',\n description:\n 'Return all inline and reference links within the given line range from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n startLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start line (inclusive).'),\n endLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('End line (exclusive).'),\n }),\n },\n {\n name: 'artifact_md_images',\n method: 'md_images',\n description:\n 'Return all images within the given line range from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n startLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start line (inclusive).'),\n endLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('End line (exclusive).'),\n }),\n },\n {\n name: 'artifact_md_text',\n method: 'md_text',\n description:\n 'Return plain text with markup stripped, for the given line range, from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n startLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start line (inclusive).'),\n endLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('End line (exclusive).'),\n }),\n },\n {\n name: 'artifact_md_ast',\n method: 'md_ast',\n description:\n 'Return the full MDAST Root for the specified line range from a markdown artifact produced earlier in this turn.',\n argsSchema: validator.object({\n startLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('Start line (inclusive).'),\n endLine: validator\n .number()\n .integer()\n .min(0)\n .optional()\n .description('End line (exclusive).'),\n }),\n },\n ])\n\n /**\n * Forges base-class tools plus markdown-specific tools narrowed to\n * {@link SpooledMarkdownArtifact}.\n *\n * @remarks\n * Standard subclass extension pattern: call `SpooledArtifact.forgeTools(ctx)` to produce\n * the base seven `artifact_*` tools narrowed to any `SpooledArtifact` in the turn, then\n * register one `ArtifactTool` per markdown-specific descriptor narrowed to markdown\n * artifacts. Downstream consumers building their own subclasses should follow the same\n * shape.\n */\n public static override forgeTools(ctx: DispatchContext): ToolRegistry {\n const registry = SpooledArtifact.forgeTools(ctx)\n const requires = SpooledMarkdownArtifact\n const compatibleIds = [...ctx.turnToolCalls]\n .filter((tc) => !tc.fromArtifactTool && isInstanceOf(tc.results, requires.name, requires))\n .map((tc) => tc.id)\n if (compatibleIds.length === 0) return registry\n\n for (const descriptor of this.toolMethods) {\n const callIdSchema = validator\n .string()\n .valid(...compatibleIds)\n .required()\n .description('ToolCall id of the artifact to query.')\n\n const argsSchema = (\n descriptor.argsSchema ?? validator.object<Record<string, never>>({})\n ).append({\n callId: callIdSchema,\n })\n\n const tool = new ArtifactTool({\n name: descriptor.name,\n description: descriptor.description,\n inputSchema: argsSchema,\n ephemeral: true,\n onCollision: 'replace',\n handler: async (rawArgs, ctxInner) => {\n const args = rawArgs as Record<string, unknown> & { callId: string }\n const tc = [...ctxInner.turnToolCalls].find((t) => t.id === args.callId)\n if (!tc) {\n return `Error: no tool call with id ${args.callId} in this turn`\n }\n const artifact = tc.results\n if (!isInstanceOf(artifact, requires.name, requires)) {\n return `Error: tool call ${args.callId} results are not a ${requires.name} instance`\n }\n const methodArgs: unknown[] = []\n if (descriptor.method === 'md_headings' || descriptor.method === 'md_sections') {\n methodArgs.push(args.depth as number | undefined)\n } else if (descriptor.method === 'md_code_blocks') {\n methodArgs.push(args.lang as string | undefined)\n } else if (\n descriptor.method === 'md_links' ||\n descriptor.method === 'md_images' ||\n descriptor.method === 'md_text' ||\n descriptor.method === 'md_ast'\n ) {\n methodArgs.push(\n args.startLine as number | undefined,\n args.endLine as number | undefined\n )\n }\n const fn = (artifact as unknown as Record<string, (...a: unknown[]) => unknown>)[\n descriptor.method\n ]\n if (typeof fn !== 'function') {\n return `Error: artifact has no method ${descriptor.method}`\n }\n const result = await Promise.resolve(fn.apply(artifact, methodArgs))\n const serialise = descriptor.serialise ?? defaultSerialise\n return serialise(result)\n },\n })\n registry.register(tool)\n }\n return registry\n }\n\n /**\n * Builds the structural index in a single top-to-bottom pass, retaining only metadata.\n */\n async #resolveIndex(): Promise<MarkdownIndex> {\n if (this.#index !== undefined) return this.#index\n\n const count = await this.lineCount()\n const headingsRaw: Array<{ depth: 1 | 2 | 3 | 4 | 5 | 6; text: string; startLine: number }> = []\n const codeBlocks: MarkdownCodeEntry[] = []\n\n let inFrontmatter = false\n let frontmatterClosed = false\n let inCodeBlock = false\n let openFenceLen = 0\n let openFenceStartLine = 0\n let openFenceLang: string | null = null\n\n for (let i = 0; i < count; i++) {\n const rawLine = await this.line(i)\n const l = rawLine ?? ''\n\n // Handle frontmatter block at the top of the document\n if (i === 0 && l.trim() === '---') {\n inFrontmatter = true\n continue\n }\n if (inFrontmatter) {\n if (l.trim() === '---') {\n inFrontmatter = false\n frontmatterClosed = true\n }\n continue\n }\n if (!frontmatterClosed && i === 0) {\n // No frontmatter — treat as normal document from the start\n }\n\n // Handle fenced code blocks\n const fLen = fenceLength(l)\n if (!inCodeBlock && fLen >= 3) {\n inCodeBlock = true\n openFenceLen = fLen\n openFenceStartLine = i\n openFenceLang = fenceLang(l)\n continue\n }\n if (inCodeBlock) {\n // A closing fence must use the same fence character (` or ~) and be at least as long.\n if (fLen >= openFenceLen) {\n const openLine = (await this.line(openFenceStartLine)) ?? ''\n const openChar = openLine.trimStart()[0]\n const closeChar = l.trimStart()[0]\n if (closeChar === openChar) {\n codeBlocks.push({ lang: openFenceLang, startLine: openFenceStartLine, endLine: i })\n inCodeBlock = false\n openFenceLen = 0\n }\n }\n continue\n }\n\n // Detect ATX headings (not inside code blocks, not in frontmatter)\n const heading = parseHeadingLine(l)\n if (heading) {\n headingsRaw.push({ ...heading, startLine: i })\n }\n }\n\n // Unclosed code block — record it anyway\n if (inCodeBlock) {\n codeBlocks.push({ lang: openFenceLang, startLine: openFenceStartLine, endLine: count - 1 })\n }\n\n // Post-process heading endLine values\n const headings: MarkdownHeadingEntry[] = headingsRaw.map((h, idx) => {\n const nextBoundary = headingsRaw.slice(idx + 1).find((n) => n.depth <= h.depth)\n const endLine = nextBoundary ? nextBoundary.startLine - 1 : count - 1\n return { ...h, endLine }\n })\n\n this.#index = { headings, codeBlocks }\n return this.#index\n }\n\n // ── Frontmatter ───────────────────────────────────────────────────────────\n\n /**\n * Returns the parsed YAML frontmatter, or `undefined` when no frontmatter block is present.\n *\n * @remarks\n * Short-circuits after reading the frontmatter block — never reads the document body. Caches\n * the result so subsequent calls are free. The result is `undefined` (not an empty object)\n * when no frontmatter is found, distinguishing \"no frontmatter\" from \"empty frontmatter\".\n */\n async md_frontmatter(): Promise<Record<string, unknown> | undefined> {\n if (this.#frontmatter !== undefined) return this.#frontmatter ?? undefined\n\n const firstLine = await this.line(0)\n if (firstLine?.trim() !== '---') {\n this.#frontmatter = null\n return undefined\n }\n\n const maxScan = Math.min(await this.lineCount(), 200)\n const yamlLines: string[] = []\n let closed = false\n for (let i = 1; i < maxScan; i++) {\n const l = await this.line(i)\n if (l?.trim() === '---') {\n closed = true\n break\n }\n yamlLines.push(l ?? '')\n }\n\n if (!closed) {\n this.#frontmatter = null\n return undefined\n }\n\n this.#frontmatter = yamlLoad(yamlLines.join('\\n')) as Record<string, unknown>\n return this.#frontmatter\n }\n\n // ── Structural index queries ──────────────────────────────────────────────\n\n /**\n * Returns all headings in document order, optionally filtered by depth.\n *\n * @remarks\n * Uses the cached structural index — no content is fetched from the {@link @nhtio/adk!SpoolReader}.\n *\n * @param depth - When provided, only headings at this ATX depth (1–6) are returned.\n */\n async md_headings(depth?: 1 | 2 | 3 | 4 | 5 | 6): Promise<MarkdownHeadingEntry[]> {\n const index = await this.#resolveIndex()\n if (depth === undefined) return index.headings.slice()\n return index.headings.filter((h) => h.depth === depth)\n }\n\n /**\n * Returns all fenced code block entries, optionally filtered by language identifier.\n *\n * @remarks\n * Returns line-range metadata only — no content is fetched. Use `cat(entry.startLine + 1,\n * entry.endLine)` to retrieve the code body (excluding fence lines).\n *\n * @param lang - When provided, only blocks with this exact lang identifier are returned.\n * Pass an empty string to match blocks with no lang identifier.\n */\n async md_code_blocks(lang?: string): Promise<MarkdownCodeEntry[]> {\n const index = await this.#resolveIndex()\n if (lang === undefined) return index.codeBlocks.slice()\n const target = lang === '' ? null : lang\n return index.codeBlocks.filter((b) => b.lang === target)\n }\n\n /**\n * Returns document sections derived from the structural index.\n *\n * @remarks\n * Returns only line-range metadata — body content is never fetched. To retrieve the body of a\n * section, call `cat(section.bodyStartLine, section.bodyEndLine + 1)`.\n *\n * When `depth` is provided, only sections introduced by a heading at that depth are returned;\n * deeper headings become part of the body.\n *\n * @param depth - When provided, only sections at this ATX depth (1–6) are returned.\n */\n async md_sections(depth?: 1 | 2 | 3 | 4 | 5 | 6): Promise<MarkdownSection[]> {\n const index = await this.#resolveIndex()\n const headings =\n depth !== undefined ? index.headings.filter((h) => h.depth === depth) : index.headings\n return headings.map((h) => ({\n depth: h.depth,\n heading: h.text,\n headingLine: h.startLine,\n bodyStartLine: h.startLine + 1,\n bodyEndLine: h.endLine,\n }))\n }\n\n // ── Inline queries (bounded) ──────────────────────────────────────────────\n\n /**\n * Returns the full MDAST Root for the specified line range.\n *\n * @remarks\n * Without a range, reads the full document — for large documents, use\n * {@link SpooledMarkdownArtifact.md_sections} to locate sections and pass\n * bounded line ranges here.\n *\n * @param startLine - 0-based start line (inclusive). Defaults to `0`.\n * @param endLine - 0-based end line (exclusive). Defaults to `lineCount()`.\n */\n async md_ast(startLine?: number, endLine?: number): Promise<Root> {\n const lines = await this.cat(startLine, endLine)\n return processor().parse(lines.join('\\n')) as Root\n }\n\n /**\n * Returns all inline and reference links in the specified line range.\n *\n * @param startLine - 0-based start line (inclusive). Defaults to `0`.\n * @param endLine - 0-based end line (exclusive). Defaults to `lineCount()`.\n */\n async md_links(\n startLine?: number,\n endLine?: number\n ): Promise<Array<{ text: string; url: string; title?: string }>> {\n const lines = await this.cat(startLine, endLine)\n const ast = processor().parse(lines.join('\\n'))\n const results: Array<{ text: string; url: string; title?: string }> = []\n visit(ast, 'link', (node: Link) => {\n results.push({\n text: mdastToString(node),\n url: node.url,\n title: node.title ?? undefined,\n })\n })\n return results\n }\n\n /**\n * Returns all images in the specified line range.\n *\n * @param startLine - 0-based start line (inclusive). Defaults to `0`.\n * @param endLine - 0-based end line (exclusive). Defaults to `lineCount()`.\n */\n async md_images(\n startLine?: number,\n endLine?: number\n ): Promise<Array<{ alt: string; url: string; title?: string }>> {\n const lines = await this.cat(startLine, endLine)\n const ast = processor().parse(lines.join('\\n'))\n const results: Array<{ alt: string; url: string; title?: string }> = []\n visit(ast, 'image', (node: Image) => {\n results.push({\n alt: node.alt ?? '',\n url: node.url,\n title: node.title ?? undefined,\n })\n })\n return results\n }\n\n /**\n * Returns all document text with markup stripped, for the specified line range.\n *\n * @remarks\n * Uses `mdast-util-to-string` to extract plain text from the AST — code, link text, and\n * alt text are included; markdown syntax is removed.\n *\n * @param startLine - 0-based start line (inclusive). Defaults to `0`.\n * @param endLine - 0-based end line (exclusive). Defaults to `lineCount()`.\n */\n async md_text(startLine?: number, endLine?: number): Promise<string> {\n const lines = await this.cat(startLine, endLine)\n const ast = processor().parse(lines.join('\\n'))\n return mdastToString(ast)\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool_call-CV5qVNlb.mjs","names":["#id","#kind","#mimeType","#filename","#source","#trustTier","#modalityHazard","#reader","#stash","#id","#tool","#args","#checksum","#isComplete","#isError","#results","#fromArtifactTool","#inline","#createdAt","#updatedAt","#completedAt"],"sources":["../src/lib/contracts/media_reader.ts","../src/lib/classes/media.ts","../src/lib/classes/tool_call.ts"],"sourcesContent":["import { validator } from '@nhtio/validation'\nimport { passesSchema } from '../utils/validation'\n\n/**\n * Re-openable byte source contract for a Media instance.\n *\n * @remarks\n * Peer to {@link @nhtio/adk!SpoolReader} but tuned for binary streaming rather than line-indexed text.\n * Each `stream()` call must return a fresh, drainable `ReadableStream` over the same underlying\n * bytes — implementations model replay: in-memory readers reconstitute the stream from the\n * buffer, file-backed readers reopen the file handle, HTTP-backed readers re-issue the fetch,\n * cloud blob readers re-issue the GET. The implementor owns the storage and the cost of keeping\n * the underlying source addressable. Implementors whose underlying source is genuinely\n * non-replayable (a raw HTTP body they were handed once) are responsible for caching locally\n * before constructing the Media.\n *\n * Both methods may be synchronous or asynchronous to accommodate both in-memory and I/O-backed\n * implementations without forcing unnecessary promise overhead on simple cases.\n */\nexport interface MediaReader {\n /**\n * Re-opens the underlying byte source and returns a fresh ReadableStream.\n *\n * @remarks\n * Each call yields a new, drainable stream over the same bytes. Render code that needs the\n * full buffer (e.g. base64-encoding an inline image_url) drains the stream; render code that\n * can forward the stream (e.g. multipart upload) passes the stream through without buffering.\n *\n * @returns A drainable ReadableStream of Uint8Array chunks over the underlying bytes.\n */\n stream(): ReadableStream<Uint8Array> | Promise<ReadableStream<Uint8Array>>\n\n /**\n * Returns the total number of bytes in the underlying data, or `undefined` if unknown.\n *\n * @remarks\n * Used for telemetry, budget checks, and pre-flight provider size validation without forcing\n * a stream drain. Sources of unknown length may return `undefined` — absence is treated as\n * \"unknown\", not \"zero\".\n *\n * @returns The byte length of the underlying data, or `undefined` when unknown.\n */\n byteLength(): number | undefined | Promise<number | undefined>\n}\n\n/**\n * Validator schema used to validate a MediaReader value.\n *\n * @remarks\n * Because MediaReader is a structural interface with no associated constructor, validation is\n * duck-typed: the value must be an object, class instance, or function with `stream` and\n * `byteLength` present as callable properties. Arity is not enforced.\n */\nexport const mediaReaderSchema = validator\n .any()\n .required()\n .custom((value, helpers) => {\n if (\n value !== null &&\n value !== undefined &&\n typeof (value as any).stream === 'function' &&\n typeof (value as any).byteLength === 'function'\n ) {\n return value as MediaReader\n }\n return helpers.error('any.invalid')\n })\n\n/**\n * Returns `true` if `value` implements the MediaReader interface.\n *\n * @remarks\n * Duck-typed: checks that `value` is non-null with `stream` and `byteLength` as callable\n * functions. Does not use `instanceof` — there is no MediaReader constructor.\n *\n * @param value - The value to test.\n * @returns `true` when `value` conforms to the MediaReader interface.\n */\nexport const implementsMediaReader = (value: unknown): value is MediaReader => {\n return passesSchema(mediaReaderSchema, value)\n}\n","import { v6 as uuidv6 } from 'uuid'\nimport { Registry } from './registry'\nimport { isError } from '../utils/guards'\nimport { validator } from '@nhtio/validation'\nimport { isInstanceOf } from '../utils/guards'\nimport { validateOrThrow } from '../utils/validation'\nimport { implementsMediaReader, mediaReaderSchema } from '../contracts/media_reader'\nimport { E_INVALID_INITIAL_MEDIA_VALUE, E_NOT_A_MEDIA_READER } from '../exceptions/runtime'\nimport type { MediaReader } from '../contracts/media_reader'\n\n/**\n * The set of supported media kinds.\n *\n * @remarks\n * Modality coverage is asymmetric across providers. The framework defines no\n * `supportedModalities` field — how a battery handles a modality it cannot natively render is\n * the battery author's call (see `unsupportedMediaPolicy` on the OpenAI Chat Completions\n * battery).\n */\nexport const MediaKind = ['image', 'audio', 'video', 'document'] as const\n\n/**\n * Union of all recognised media kind identifier strings.\n */\nexport type MediaKind = (typeof MediaKind)[number]\n\n/**\n * Provenance axis. *Who is the framework willing to vouch for as the source of these bytes?*\n *\n * @remarks\n * Mirrors `RetrievableTrustTier` deliberately — same vocabulary, same question:\n * *did this content come from a place the agent should treat as authoritative?*\n *\n * - `'first-party'` — deployer-vetted bytes (tool output the operator authored, signed\n * internal assets).\n * - `'third-party-public'` — open-web fetches, public APIs, public corpora.\n * - `'third-party-private'` — user uploads, partner APIs, private corpora.\n */\nexport const MediaTrustTier = ['first-party', 'third-party-public', 'third-party-private'] as const\nexport type MediaTrustTier = (typeof MediaTrustTier)[number]\n\n/**\n * Modality-hazard axis. *How dangerous is it to let the model decode these bytes?*\n *\n * @remarks\n * Orthogonal to provenance — a first-party trusted PDF can still carry hidden text layers; a\n * third-party-public raw image can still be encoded as opaque pixels with adversarial\n * perturbations.\n *\n * - `'inert'` — bytes the model never decodes as instructions (e.g. a handle that is never\n * inlined into the prompt).\n * - `'extractable-instructions'` — text-bearing media: PDFs, screenshots with UI text, documents.\n * Hazard is OCR / embedded-text-layer reads.\n * - `'opaque-perceptual'` — raw vision/audio/video the model encodes directly. Hazard is\n * steganographic LSB prompts, adversarial perturbations, ultrasonic audio — invisible to any\n * pre-screen.\n *\n * See `/the-loop/trust-tiers/media` and its research sub-page `/the-loop/trust-tiers/media/research`.\n */\nexport const MediaModalityHazard = [\n 'inert',\n 'extractable-instructions',\n 'opaque-perceptual',\n] as const\nexport type MediaModalityHazard = (typeof MediaModalityHazard)[number]\n\n/**\n * Per-entry shape stored in a {@link Media}'s `stash` register.\n *\n * @remarks\n * Each entry carries its own trust tier so render code can route derived text (OCR, captions,\n * transcripts) through its own envelope independent of the parent media. How a battery or\n * middleware assigns those entry-level tiers is the implementor's call — the primitive contract\n * does not enforce a \"downgrade derived interpretation from possibly-adversarial bytes\" policy.\n */\nexport interface MediaStashEntry {\n /** The value of the entry — any serialisable shape the consumer wants to store. */\n value: unknown\n /** Trust tier for this specific entry; routed independently of the parent media. */\n trustTier: MediaTrustTier\n /** Optional pointer to the parent Media id this entry was derived from. */\n derivedFromMedia?: string\n}\n\n/**\n * Plain input object supplied to {@link Media} at construction time.\n *\n * @remarks\n * Validated against `rawMediaSchema` before the `Media` instance is created.\n */\nexport interface RawMedia {\n /**\n * Stable unique identifier for this media instance. Required for strict symmetry with\n * `Message.id` and `ToolCall.id`. When omitted, a fresh UUIDv6 is assigned at construction\n * time.\n */\n id?: string\n /** The media kind. See {@link MediaKind}. */\n kind: MediaKind\n /** The MIME type of the underlying bytes. */\n mimeType: string\n /** Filename used by providers that key on it (e.g. OpenAI `file.filename`). */\n filename: string\n /** Re-openable byte source. See {@link @nhtio/adk!MediaReader}. */\n reader: MediaReader\n /**\n * Trust tier declared at construction time. Required — there is NO default.\n * See {@link MediaTrustTier}.\n */\n trustTier: MediaTrustTier\n /**\n * Modality hazard declared at construction time. Required — there is NO default.\n * See {@link MediaModalityHazard}.\n */\n modalityHazard: MediaModalityHazard\n /** Optional provenance pointer (URL, tool name, etc.) for audit / events. */\n source?: string\n /**\n * Free-form per-instance metadata register. Middleware pipelines append to this — typically\n * with a text description, transcript, caption, or alt-text — so downstream code that cannot\n * consume the media natively has a model-readable fallback. No keys are reserved by the\n * framework. Defaults to `{}`.\n */\n stash?: Record<string, MediaStashEntry>\n}\n\nconst stashEntrySchema = validator\n .object<MediaStashEntry>({\n value: validator.any().required(),\n trustTier: validator\n .string()\n .valid(...MediaTrustTier)\n .required(),\n derivedFromMedia: validator.string().optional(),\n })\n .unknown(false)\n\n/**\n * Validator schema used to validate a {@link RawMedia} before constructing a {@link Media}.\n */\nconst rawMediaSchema = validator.object<RawMedia>({\n id: validator.string().optional(),\n kind: validator\n .string()\n .valid(...MediaKind)\n .required(),\n mimeType: validator.string().required(),\n filename: validator.string().required(),\n reader: mediaReaderSchema.required(),\n trustTier: validator\n .string()\n .valid(...MediaTrustTier)\n .required(),\n modalityHazard: validator\n .string()\n .valid(...MediaModalityHazard)\n .required(),\n source: validator.string().optional(),\n stash: validator.object().pattern(validator.string(), stashEntrySchema).optional(),\n})\n\ninterface ResolvedMedia {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n trustTier: MediaTrustTier\n modalityHazard: MediaModalityHazard\n source?: string\n stash?: Record<string, MediaStashEntry>\n}\n\nconst conservativeHazardForKind = (kind: MediaKind): MediaModalityHazard => {\n return kind === 'document' ? 'extractable-instructions' : 'opaque-perceptual'\n}\n\n/**\n * Shape returned by {@link Media.toJSON}. Metadata-only — bytes and the reader are stripped so\n * naive event/log serialisation never materialises bytes.\n */\nexport interface SerializedMedia {\n id: string\n kind: MediaKind\n mimeType: string\n filename: string\n source?: string\n trustTier: MediaTrustTier\n modalityHazard: MediaModalityHazard\n stash: Record<string, MediaStashEntry>\n byteLength?: number\n}\n\n/**\n * Cross-environment base64 encoder for a `Uint8Array`.\n *\n * @remarks\n * Prefers Node's `Buffer.from(buf).toString('base64')` when `globalThis.Buffer` exists; otherwise\n * chunk-encodes through `btoa` with a 0x8000-byte window to avoid `Maximum call stack size\n * exceeded` on large buffers.\n */\nconst encodeBase64 = (bytes: Uint8Array): string => {\n const maybeBuffer = (\n globalThis as { Buffer?: { from(b: Uint8Array): { toString(enc: string): string } } }\n ).Buffer\n if (maybeBuffer && typeof maybeBuffer.from === 'function') {\n return maybeBuffer.from(bytes).toString('base64')\n }\n const chunkSize = 0x8000\n let binary = ''\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, i + chunkSize)\n binary += String.fromCharCode.apply(null, Array.from(chunk) as number[])\n }\n return btoa(binary)\n}\n\n/**\n * Lazy, re-openable view over a binary asset (image, audio, video, document).\n *\n * @remarks\n * Dual-peer to {@link @nhtio/adk!Tokenizable} (silo) and {@link @nhtio/adk!SpooledArtifact}\n * (handle). Wraps a {@link @nhtio/adk!MediaReader} contract — the framework owns the contract, the\n * implementor owns the storage backend. Bytes are reached only through the reader; the primitive\n * itself never inlines bytes.\n *\n * Construction requires `trustTier` and `modalityHazard` — the framework refuses to guess\n * provenance or decoding hazard. Ergonomic factories ({@link Media.userAttachment},\n * {@link Media.toolGenerated}, {@link Media.retrievedPublic}, {@link Media.retrievedPrivate})\n * force the labelling decision at the call site without becoming defaults on the bare\n * constructor.\n */\nexport class Media {\n /**\n * Validator schema that accepts a {@link RawMedia} object.\n */\n public static schema = rawMediaSchema\n\n /**\n * The set of recognised media kinds. Exposed for downstream schemas that need to discriminate\n * on `kind`.\n */\n public static MediaKind = MediaKind\n\n /**\n * The set of recognised trust tiers.\n */\n public static MediaTrustTier = MediaTrustTier\n\n /**\n * The set of recognised modality hazards.\n */\n public static MediaModalityHazard = MediaModalityHazard\n\n /**\n * Returns `true` if `value` is a {@link Media} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Media} instance.\n */\n public static isMedia(value: unknown): value is Media {\n return isInstanceOf(value, 'Media', Media)\n }\n\n /** Stable unique identifier. */\n declare readonly id: string\n /** Media kind. */\n declare readonly kind: MediaKind\n /** MIME type of the underlying bytes. */\n declare readonly mimeType: string\n /** Filename surfaced to providers that key on it. */\n declare readonly filename: string\n /** Optional provenance pointer. */\n declare readonly source: string | undefined\n /** Trust tier declared at construction time. */\n declare readonly trustTier: MediaTrustTier\n /** Modality hazard declared at construction time. */\n declare readonly modalityHazard: MediaModalityHazard\n /** Mutable per-instance metadata register; middleware pipelines append to this. */\n declare readonly stash: Registry\n\n #id: string\n #kind: MediaKind\n #mimeType: string\n #filename: string\n #source?: string\n #trustTier: MediaTrustTier\n #modalityHazard: MediaModalityHazard\n #reader: MediaReader\n #stash: Registry\n\n /**\n * @param raw - The raw media input validated against `rawMediaSchema`.\n * @throws {@link @nhtio/adk/exceptions!E_INVALID_INITIAL_MEDIA_VALUE} when `raw` does not satisfy the schema.\n * @throws {@link @nhtio/adk/exceptions!E_NOT_A_MEDIA_READER} when `raw.reader` does not implement {@link @nhtio/adk!MediaReader}.\n */\n constructor(raw: RawMedia) {\n let resolved: ResolvedMedia\n try {\n resolved = validateOrThrow<ResolvedMedia>(rawMediaSchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_MEDIA_VALUE({ cause: isError(err) ? err : undefined })\n }\n if (!implementsMediaReader(resolved.reader)) {\n throw new E_NOT_A_MEDIA_READER()\n }\n this.#id = resolved.id ?? uuidv6()\n this.#kind = resolved.kind\n this.#mimeType = resolved.mimeType\n this.#filename = resolved.filename\n this.#source = resolved.source\n this.#trustTier = resolved.trustTier\n this.#modalityHazard = resolved.modalityHazard\n this.#reader = resolved.reader\n this.#stash = new Registry(resolved.stash as Record<string, unknown> | undefined)\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n kind: {\n get: () => this.#kind,\n enumerable: true,\n configurable: false,\n },\n mimeType: {\n get: () => this.#mimeType,\n enumerable: true,\n configurable: false,\n },\n filename: {\n get: () => this.#filename,\n enumerable: true,\n configurable: false,\n },\n source: {\n get: () => this.#source,\n enumerable: true,\n configurable: false,\n },\n trustTier: {\n get: () => this.#trustTier,\n enumerable: true,\n configurable: false,\n },\n modalityHazard: {\n get: () => this.#modalityHazard,\n enumerable: true,\n configurable: false,\n },\n stash: {\n get: () => this.#stash,\n enumerable: true,\n configurable: false,\n },\n })\n }\n\n /**\n * Re-opens the underlying byte source and returns a fresh ReadableStream.\n *\n * @returns A drainable `ReadableStream` over the underlying bytes.\n */\n async stream(): Promise<ReadableStream<Uint8Array>> {\n return this.#reader.stream()\n }\n\n /**\n * Returns the total number of bytes in the underlying data, or `undefined` if unknown.\n *\n * @returns The byte length, or `undefined` when the underlying source cannot report it.\n */\n async byteLength(): Promise<number | undefined> {\n return this.#reader.byteLength()\n }\n\n /**\n * Drains the reader's stream and returns the underlying bytes as a single `Uint8Array`.\n *\n * @remarks\n * Convenience for callers that need the full buffer (e.g. inline base64 encoding). Forces\n * full materialisation — large assets should be piped through {@link Media.stream} instead.\n */\n async asBytes(): Promise<Uint8Array> {\n const stream = await this.stream()\n const reader = stream.getReader()\n const chunks: Uint8Array[] = []\n let total = 0\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n if (value) {\n chunks.push(value)\n total += value.byteLength\n }\n }\n const out = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n out.set(chunk, offset)\n offset += chunk.byteLength\n }\n return out\n }\n\n /**\n * Drains the reader's stream and returns the underlying bytes as a base64 string.\n *\n * @remarks\n * Cross-environment: prefers Node's `Buffer.from(buf).toString('base64')` when available;\n * otherwise chunk-encodes through `btoa` with a 0x8000-byte window to avoid stack overflow\n * on large buffers.\n */\n async asBase64(): Promise<string> {\n const bytes = await this.asBytes()\n return encodeBase64(bytes)\n }\n\n /**\n * Returns the metadata-only serialisation of this Media. Bytes and the reader are stripped\n * so naive event/log serialisation never materialises bytes.\n *\n * @remarks\n * Implementations that have cheap, already-cached `byteLength` may opt to include it; this\n * default implementation omits it to preserve the \"lazy by default\" invariant. Consumers that\n * need byteLength on the serialised payload should call `await media.byteLength()` and merge\n * the result.\n */\n toJSON(): SerializedMedia {\n return {\n id: this.#id,\n kind: this.#kind,\n mimeType: this.#mimeType,\n filename: this.#filename,\n source: this.#source,\n trustTier: this.#trustTier,\n modalityHazard: this.#modalityHazard,\n stash: this.#stash.all() as Record<string, MediaStashEntry>,\n }\n }\n\n /**\n * Factory: constructs a {@link Media} representing a user-supplied attachment.\n *\n * @remarks\n * Pre-fills `trustTier: 'third-party-private'` and derives `modalityHazard` from `kind`\n * (`document` → `'extractable-instructions'`; everything else → `'opaque-perceptual'`).\n * Use the bare constructor when the conservative kind→hazard mapping is wrong for your case.\n */\n public static userAttachment(args: {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n source?: string\n stash?: Record<string, MediaStashEntry>\n }): Media {\n return new Media({\n ...args,\n trustTier: 'third-party-private',\n modalityHazard: conservativeHazardForKind(args.kind),\n })\n }\n\n /**\n * Factory: constructs a {@link Media} produced by a first-party tool.\n *\n * @remarks\n * Pre-fills `trustTier: 'first-party'` and derives `modalityHazard` from `kind`.\n */\n public static toolGenerated(args: {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n source?: string\n stash?: Record<string, MediaStashEntry>\n }): Media {\n return new Media({\n ...args,\n trustTier: 'first-party',\n modalityHazard: conservativeHazardForKind(args.kind),\n })\n }\n\n /**\n * Factory: constructs a {@link Media} retrieved from a public third-party source.\n *\n * @remarks\n * Pre-fills `trustTier: 'third-party-public'` and derives `modalityHazard` from `kind`.\n */\n public static retrievedPublic(args: {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n source?: string\n stash?: Record<string, MediaStashEntry>\n }): Media {\n return new Media({\n ...args,\n trustTier: 'third-party-public',\n modalityHazard: conservativeHazardForKind(args.kind),\n })\n }\n\n /**\n * Factory: constructs a {@link Media} retrieved from a private third-party source.\n *\n * @remarks\n * Pre-fills `trustTier: 'third-party-private'` and derives `modalityHazard` from `kind`.\n */\n public static retrievedPrivate(args: {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n source?: string\n stash?: Record<string, MediaStashEntry>\n }): Media {\n return new Media({\n ...args,\n trustTier: 'third-party-private',\n modalityHazard: conservativeHazardForKind(args.kind),\n })\n }\n}\n\n/**\n * Returns `true` if `value` is a {@link Media} instance.\n *\n * @remarks\n * Module-level convenience alias for {@link Media.isMedia}. Uses {@link @nhtio/adk!isInstanceOf} for\n * cross-realm safety.\n */\nexport const isMedia = (value: unknown): value is Media => {\n return isInstanceOf(value, 'Media', Media)\n}\n","import { Media } from './media'\nimport { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { SpooledArtifact } from './spooled_artifact'\nimport { validateOrThrow } from '../utils/validation'\nimport { isObject, isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_TOOL_CALL_VALUE } from '../exceptions/runtime'\nimport type { DateTime } from 'luxon'\n\n/**\n * Union of every shape a {@link ToolCall.results} field may carry.\n *\n * @remarks\n * Three silos with distinct render-time semantics:\n *\n * - {@link @nhtio/adk!Tokenizable} — always singular. The {@link @nhtio/adk!ArtifactTool}\n * carve-out: a model-visible text answer that explicitly opts out of artifact wrapping to\n * break the recursive grep-on-the-grep-result loop.\n * - {@link @nhtio/adk!SpooledArtifact} or `SpooledArtifact[]` — bounded text output spooled to durable\n * storage. A single tool call may legitimately produce multiple artifacts (e.g. one tool\n * that returns N PR bodies). LLM adapters render either inline (full body in trust envelope)\n * or as a handle reference (forged artifact-query tools).\n * - {@link @nhtio/adk!Media} or `Media[]` — binary modality output (image, audio, video, document).\n * Adapters render as provider-specific content blocks (`image_url`, `input_audio`, `file`,\n * etc.). Bytes are lazy — reached only through {@link @nhtio/adk!Media.stream}.\n */\nexport type ToolCallResults = Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]\n\nconst isToolCallResults = (value: unknown): value is ToolCallResults => {\n if (Tokenizable.isTokenizable(value)) return true\n if (SpooledArtifact.isSpooledArtifact(value)) return true\n if (Media.isMedia(value)) return true\n if (Array.isArray(value) && value.length > 0) {\n const allMedia = value.every((entry) => Media.isMedia(entry))\n if (allMedia) return true\n const allSpooled = value.every((entry) => SpooledArtifact.isSpooledArtifact(entry))\n if (allSpooled) return true\n }\n return false\n}\n\n/**\n * Plain input object supplied to {@link ToolCall} at construction time.\n *\n * @remarks\n * Validated against `rawToolCallSchema` before the `ToolCall` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n */\nexport interface RawToolCall {\n /** Stable unique identifier for this tool call; correlates the request with its result. */\n id: string\n /** Name of the tool the model has requested. */\n tool: string\n /**\n * Arguments the model supplied for this tool call.\n *\n * @remarks\n * Accepts either a plain object or a JSON-encoded string that deserialises to an object.\n * Always exposed as a plain object on the constructed {@link ToolCall} instance.\n */\n args: string | Record<string, unknown>\n /** Integrity checksum over `tool` and `args`; can be used to detect tampering before execution. */\n checksum: string\n /** `true` once the tool call has finished (successfully or not). */\n isComplete: boolean\n /** `true` when the tool execution produced an error; inspect `results` for detail. */\n isError: boolean\n /**\n * Result returned by the tool, or error detail when `isError` is `true`.\n *\n * @remarks\n * Three silos with distinct render-time semantics — see {@link ToolCallResults}:\n *\n * - For a normal {@link @nhtio/adk!Tool} call whose handler returned `string` or\n * `Uint8Array`, this is a {@link @nhtio/adk!SpooledArtifact} (or one of its subclasses) wrapping the\n * spooled bytes. Tools that legitimately produce multiple bounded artifacts may return\n * a `SpooledArtifact[]`.\n * - For a `Tool` call whose handler returned a {@link @nhtio/adk!Media} or `Media[]`, this is the same\n * media handle(s) — the explicit-modality silo bypasses `SpooledArtifact` wrapping because\n * the bytes are binary and rendered as provider-specific content blocks, not text.\n * - For an {@link @nhtio/adk!ArtifactTool} call (a forged artifact-query tool),\n * this is a {@link @nhtio/adk!Tokenizable} holding the raw model-visible answer — `ArtifactTool`\n * explicitly opts out of wrapping to break the recursive grep-on-the-grep-result loop.\n *\n * The ADK sets {@link RawToolCall.fromArtifactTool} on calls produced by an\n * `ArtifactTool` so subsequent `forgeTools(ctx)` invocations can filter them out of the\n * `callId` enum.\n */\n results: ToolCallResults\n /**\n * `true` when this tool call originated from an {@link @nhtio/adk!ArtifactTool}\n * invocation. Defaults to `false`.\n *\n * @remarks\n * Set by the ADK's result-wrapping touch sites when `ArtifactTool.isArtifactTool(tool)`\n * holds. Read by `SpooledArtifact.forgeTools(ctx)` when building each descriptor's `callId`\n * enum — calls with this flag set are excluded so the model can't `artifact_grep` on a\n * previous `artifact_grep` result. Optional in the raw shape (defaults to `false`); always\n * defined on the constructed {@link ToolCall}.\n *\n * @defaultValue `false`\n */\n fromArtifactTool?: boolean\n /**\n * When `true` (default), LLM adapters render this tool call's result inline — the full\n * stringified body is wrapped in the adapter's trust envelope and sent to the model as the\n * `tool` role content. When `false`, the adapter surfaces the result as a \"handle\" — a\n * directions-bearing envelope that tells the model which forged artifact-query tools to call\n * against this `tc.id` to read the content incrementally.\n *\n * @remarks\n * Policy is the producer's or middleware's call:\n * - A normal tool returns its result with `inline: true` by default so its output is shown\n * verbatim.\n * - Middleware that wants to keep large results out of the model's prompt sets `inline: false`\n * (typically via `ctx.mutateToolCall(tc.id, { inline: false })`) before yielding.\n * - LLM adapters do not override the flag, do not size-check the result, and do not silently\n * switch to the handle pattern.\n *\n * For {@link @nhtio/adk!Tokenizable} results, the flag is effectively informational — handles only make\n * sense for {@link @nhtio/adk!SpooledArtifact} (which is the only result kind the forged artifact-query\n * tools can read). When `inline: false` is set on a call whose `results` is a `Tokenizable`,\n * the adapter renders inline anyway and may log a warning.\n *\n * @defaultValue `true`\n */\n inline?: boolean\n /** When this tool call was first created. */\n createdAt: string | number | Date | DateTime\n /** When this tool call was last modified. */\n updatedAt: string | number | Date | DateTime\n /** When the tool call completed. */\n completedAt: string | number | Date | DateTime\n}\n\n/**\n * A fully-resolved {@link RawToolCall} where temporal fields have been normalised to Luxon\n * `DateTime` instances.\n *\n * @remarks\n * Used internally by the {@link ToolCall} constructor to assign private fields with\n * guaranteed types.\n */\ninterface ResolvedToolCall {\n id: string\n tool: string\n args: Record<string, unknown>\n checksum: string\n isComplete: boolean\n isError: boolean\n results: ToolCallResults\n fromArtifactTool: boolean\n inline: boolean\n createdAt: DateTime\n updatedAt: DateTime\n completedAt: DateTime\n}\n\n/**\n * Validator schema used to validate a {@link RawToolCall} before constructing a {@link ToolCall}.\n *\n * @remarks\n * Validates all fields of {@link RawToolCall}:\n * - `id` — required non-empty string.\n * - `tool` — required non-empty string.\n * - `args` — required; either a plain object or a JSON string that deserialises to an object.\n * Strings are parsed and the resulting object is stored.\n * - `checksum` — required string.\n * - `isComplete` — required boolean.\n * - `isError` — required boolean.\n * - `results` — required; one of {@link @nhtio/adk!Tokenizable}, {@link @nhtio/adk!SpooledArtifact}, a non-empty\n * `SpooledArtifact[]`, {@link @nhtio/adk!Media}, or a non-empty `Media[]`. Arrays must be homogeneous.\n * - `createdAt` / `updatedAt` / `completedAt` — required datetime-parseable values, normalised to `DateTime`.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_CALL_VALUE} (via the {@link ToolCall} constructor) when\n * validation fails.\n */\nconst rawToolCallSchema = validator.object<RawToolCall>({\n id: validator.string().required(),\n tool: validator.string().required(),\n args: validator\n .alternatives(\n validator.object().unknown(true),\n validator.string().custom((value, helpers) => {\n try {\n const parsed = JSON.parse(value)\n if (!isObject(parsed)) {\n return helpers.error('any.invalid')\n }\n return parsed\n } catch {\n return helpers.error('any.invalid')\n }\n })\n )\n .required(),\n checksum: validator.string().required(),\n isComplete: validator.boolean().required(),\n isError: validator.boolean().required(),\n results: validator\n .any()\n .custom((value, helpers) => {\n if (isToolCallResults(value)) {\n return value\n }\n return helpers.error('any.invalid')\n })\n .required(),\n fromArtifactTool: validator.boolean().default(false),\n inline: validator.boolean().default(true),\n createdAt: validator.datetime().required(),\n updatedAt: validator.datetime().required(),\n completedAt: validator.datetime().required(),\n})\n\n/**\n * An immutable, validated tool call record associated with a turn.\n *\n * @remarks\n * Represents a completed tool invocation from the conversation history — `results`,\n * `completedAt`, `isComplete`, and `isError` are all present and required.\n * Temporal fields are normalised to Luxon `DateTime` instances at construction time.\n */\nexport class ToolCall {\n /**\n * Validator schema that accepts a {@link RawToolCall} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a tool call entry.\n */\n public static schema = rawToolCallSchema\n\n /**\n * Returns `true` if `value` is a {@link ToolCall} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link ToolCall} instance.\n */\n public static isToolCall(value: unknown): value is ToolCall {\n return isInstanceOf(value, 'ToolCall', ToolCall)\n }\n\n /** Stable unique identifier for this tool call; correlates the request with its result. */\n declare readonly id: string\n /** Name of the tool the model has requested. */\n declare readonly tool: string\n /** Arguments the model supplied for this tool call, always as a plain object. */\n declare readonly args: Record<string, unknown>\n /** Integrity checksum over `tool` and `args`. */\n declare readonly checksum: string\n /** `true` once the tool call has finished (successfully or not). */\n declare readonly isComplete: boolean\n /** `true` when the tool execution produced an error; inspect `results` for detail. */\n declare readonly isError: boolean\n /**\n * Result returned by the tool, or error detail when `isError` is `true`.\n *\n * @remarks\n * One of three silos — see {@link ToolCallResults}. {@link @nhtio/adk!SpooledArtifact} or\n * `SpooledArtifact[]` for normal text-output {@link @nhtio/adk!Tool} calls;\n * {@link @nhtio/adk!Media} or `Media[]` for tool calls whose handler returned binary modality output;\n * {@link @nhtio/adk!Tokenizable} for {@link @nhtio/adk!ArtifactTool} calls\n * (see {@link ToolCall.fromArtifactTool}).\n */\n declare readonly results: ToolCallResults\n /**\n * `true` when this tool call originated from an {@link @nhtio/adk!ArtifactTool}\n * invocation. Used by `SpooledArtifact.forgeTools(ctx)` to filter out forged-tool results from\n * the `callId` enum it builds.\n */\n declare readonly fromArtifactTool: boolean\n /**\n * `true` (default) renders this tool call's result inline in the prompt; `false` instructs LLM\n * adapters to surface the result as a handle reference. See {@link RawToolCall.inline}.\n */\n declare readonly inline: boolean\n /** When this tool call was first created. */\n declare readonly createdAt: DateTime\n /** When this tool call was last modified. */\n declare readonly updatedAt: DateTime\n /** When the tool call completed. */\n declare readonly completedAt: DateTime\n\n #id: string\n #tool: string\n #args: Record<string, unknown>\n #checksum: string\n #isComplete: boolean\n #isError: boolean\n #results: ToolCallResults\n #fromArtifactTool: boolean\n #inline: boolean\n #createdAt: DateTime\n #updatedAt: DateTime\n #completedAt: DateTime\n\n /**\n * @param raw - The raw tool call input validated against `rawToolCallSchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_CALL_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawToolCall) {\n let resolved: ResolvedToolCall\n try {\n resolved = validateOrThrow<ResolvedToolCall>(rawToolCallSchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_TOOL_CALL_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#id = resolved.id\n this.#tool = resolved.tool\n this.#args = resolved.args\n this.#checksum = resolved.checksum\n this.#isComplete = resolved.isComplete\n this.#isError = resolved.isError\n this.#results = resolved.results\n this.#fromArtifactTool = resolved.fromArtifactTool\n this.#inline = resolved.inline\n this.#createdAt = resolved.createdAt\n this.#updatedAt = resolved.updatedAt\n this.#completedAt = resolved.completedAt\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n tool: {\n get: () => this.#tool,\n enumerable: true,\n configurable: false,\n },\n args: {\n get: () => this.#args,\n enumerable: true,\n configurable: false,\n },\n checksum: {\n get: () => this.#checksum,\n enumerable: true,\n configurable: false,\n },\n isComplete: {\n get: () => this.#isComplete,\n enumerable: true,\n configurable: false,\n },\n isError: {\n get: () => this.#isError,\n enumerable: true,\n configurable: false,\n },\n results: {\n get: () => this.#results,\n enumerable: true,\n configurable: false,\n },\n fromArtifactTool: {\n get: () => this.#fromArtifactTool,\n enumerable: true,\n configurable: false,\n },\n inline: {\n get: () => this.#inline,\n enumerable: true,\n configurable: false,\n },\n createdAt: {\n get: () => this.#createdAt,\n enumerable: true,\n configurable: false,\n },\n updatedAt: {\n get: () => this.#updatedAt,\n enumerable: true,\n configurable: false,\n },\n completedAt: {\n get: () => this.#completedAt,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool_call-Db68hB7y.js","names":["#id","#kind","#mimeType","#filename","#source","#trustTier","#modalityHazard","#reader","#stash","#id","#tool","#args","#checksum","#isComplete","#isError","#results","#fromArtifactTool","#inline","#createdAt","#updatedAt","#completedAt"],"sources":["../src/lib/contracts/media_reader.ts","../src/lib/classes/media.ts","../src/lib/classes/tool_call.ts"],"sourcesContent":["import { validator } from '@nhtio/validation'\nimport { passesSchema } from '../utils/validation'\n\n/**\n * Re-openable byte source contract for a Media instance.\n *\n * @remarks\n * Peer to {@link @nhtio/adk!SpoolReader} but tuned for binary streaming rather than line-indexed text.\n * Each `stream()` call must return a fresh, drainable `ReadableStream` over the same underlying\n * bytes — implementations model replay: in-memory readers reconstitute the stream from the\n * buffer, file-backed readers reopen the file handle, HTTP-backed readers re-issue the fetch,\n * cloud blob readers re-issue the GET. The implementor owns the storage and the cost of keeping\n * the underlying source addressable. Implementors whose underlying source is genuinely\n * non-replayable (a raw HTTP body they were handed once) are responsible for caching locally\n * before constructing the Media.\n *\n * Both methods may be synchronous or asynchronous to accommodate both in-memory and I/O-backed\n * implementations without forcing unnecessary promise overhead on simple cases.\n */\nexport interface MediaReader {\n /**\n * Re-opens the underlying byte source and returns a fresh ReadableStream.\n *\n * @remarks\n * Each call yields a new, drainable stream over the same bytes. Render code that needs the\n * full buffer (e.g. base64-encoding an inline image_url) drains the stream; render code that\n * can forward the stream (e.g. multipart upload) passes the stream through without buffering.\n *\n * @returns A drainable ReadableStream of Uint8Array chunks over the underlying bytes.\n */\n stream(): ReadableStream<Uint8Array> | Promise<ReadableStream<Uint8Array>>\n\n /**\n * Returns the total number of bytes in the underlying data, or `undefined` if unknown.\n *\n * @remarks\n * Used for telemetry, budget checks, and pre-flight provider size validation without forcing\n * a stream drain. Sources of unknown length may return `undefined` — absence is treated as\n * \"unknown\", not \"zero\".\n *\n * @returns The byte length of the underlying data, or `undefined` when unknown.\n */\n byteLength(): number | undefined | Promise<number | undefined>\n}\n\n/**\n * Validator schema used to validate a MediaReader value.\n *\n * @remarks\n * Because MediaReader is a structural interface with no associated constructor, validation is\n * duck-typed: the value must be an object, class instance, or function with `stream` and\n * `byteLength` present as callable properties. Arity is not enforced.\n */\nexport const mediaReaderSchema = validator\n .any()\n .required()\n .custom((value, helpers) => {\n if (\n value !== null &&\n value !== undefined &&\n typeof (value as any).stream === 'function' &&\n typeof (value as any).byteLength === 'function'\n ) {\n return value as MediaReader\n }\n return helpers.error('any.invalid')\n })\n\n/**\n * Returns `true` if `value` implements the MediaReader interface.\n *\n * @remarks\n * Duck-typed: checks that `value` is non-null with `stream` and `byteLength` as callable\n * functions. Does not use `instanceof` — there is no MediaReader constructor.\n *\n * @param value - The value to test.\n * @returns `true` when `value` conforms to the MediaReader interface.\n */\nexport const implementsMediaReader = (value: unknown): value is MediaReader => {\n return passesSchema(mediaReaderSchema, value)\n}\n","import { v6 as uuidv6 } from 'uuid'\nimport { Registry } from './registry'\nimport { isError } from '../utils/guards'\nimport { validator } from '@nhtio/validation'\nimport { isInstanceOf } from '../utils/guards'\nimport { validateOrThrow } from '../utils/validation'\nimport { implementsMediaReader, mediaReaderSchema } from '../contracts/media_reader'\nimport { E_INVALID_INITIAL_MEDIA_VALUE, E_NOT_A_MEDIA_READER } from '../exceptions/runtime'\nimport type { MediaReader } from '../contracts/media_reader'\n\n/**\n * The set of supported media kinds.\n *\n * @remarks\n * Modality coverage is asymmetric across providers. The framework defines no\n * `supportedModalities` field — how a battery handles a modality it cannot natively render is\n * the battery author's call (see `unsupportedMediaPolicy` on the OpenAI Chat Completions\n * battery).\n */\nexport const MediaKind = ['image', 'audio', 'video', 'document'] as const\n\n/**\n * Union of all recognised media kind identifier strings.\n */\nexport type MediaKind = (typeof MediaKind)[number]\n\n/**\n * Provenance axis. *Who is the framework willing to vouch for as the source of these bytes?*\n *\n * @remarks\n * Mirrors `RetrievableTrustTier` deliberately — same vocabulary, same question:\n * *did this content come from a place the agent should treat as authoritative?*\n *\n * - `'first-party'` — deployer-vetted bytes (tool output the operator authored, signed\n * internal assets).\n * - `'third-party-public'` — open-web fetches, public APIs, public corpora.\n * - `'third-party-private'` — user uploads, partner APIs, private corpora.\n */\nexport const MediaTrustTier = ['first-party', 'third-party-public', 'third-party-private'] as const\nexport type MediaTrustTier = (typeof MediaTrustTier)[number]\n\n/**\n * Modality-hazard axis. *How dangerous is it to let the model decode these bytes?*\n *\n * @remarks\n * Orthogonal to provenance — a first-party trusted PDF can still carry hidden text layers; a\n * third-party-public raw image can still be encoded as opaque pixels with adversarial\n * perturbations.\n *\n * - `'inert'` — bytes the model never decodes as instructions (e.g. a handle that is never\n * inlined into the prompt).\n * - `'extractable-instructions'` — text-bearing media: PDFs, screenshots with UI text, documents.\n * Hazard is OCR / embedded-text-layer reads.\n * - `'opaque-perceptual'` — raw vision/audio/video the model encodes directly. Hazard is\n * steganographic LSB prompts, adversarial perturbations, ultrasonic audio — invisible to any\n * pre-screen.\n *\n * See `/the-loop/trust-tiers/media` and its research sub-page `/the-loop/trust-tiers/media/research`.\n */\nexport const MediaModalityHazard = [\n 'inert',\n 'extractable-instructions',\n 'opaque-perceptual',\n] as const\nexport type MediaModalityHazard = (typeof MediaModalityHazard)[number]\n\n/**\n * Per-entry shape stored in a {@link Media}'s `stash` register.\n *\n * @remarks\n * Each entry carries its own trust tier so render code can route derived text (OCR, captions,\n * transcripts) through its own envelope independent of the parent media. How a battery or\n * middleware assigns those entry-level tiers is the implementor's call — the primitive contract\n * does not enforce a \"downgrade derived interpretation from possibly-adversarial bytes\" policy.\n */\nexport interface MediaStashEntry {\n /** The value of the entry — any serialisable shape the consumer wants to store. */\n value: unknown\n /** Trust tier for this specific entry; routed independently of the parent media. */\n trustTier: MediaTrustTier\n /** Optional pointer to the parent Media id this entry was derived from. */\n derivedFromMedia?: string\n}\n\n/**\n * Plain input object supplied to {@link Media} at construction time.\n *\n * @remarks\n * Validated against `rawMediaSchema` before the `Media` instance is created.\n */\nexport interface RawMedia {\n /**\n * Stable unique identifier for this media instance. Required for strict symmetry with\n * `Message.id` and `ToolCall.id`. When omitted, a fresh UUIDv6 is assigned at construction\n * time.\n */\n id?: string\n /** The media kind. See {@link MediaKind}. */\n kind: MediaKind\n /** The MIME type of the underlying bytes. */\n mimeType: string\n /** Filename used by providers that key on it (e.g. OpenAI `file.filename`). */\n filename: string\n /** Re-openable byte source. See {@link @nhtio/adk!MediaReader}. */\n reader: MediaReader\n /**\n * Trust tier declared at construction time. Required — there is NO default.\n * See {@link MediaTrustTier}.\n */\n trustTier: MediaTrustTier\n /**\n * Modality hazard declared at construction time. Required — there is NO default.\n * See {@link MediaModalityHazard}.\n */\n modalityHazard: MediaModalityHazard\n /** Optional provenance pointer (URL, tool name, etc.) for audit / events. */\n source?: string\n /**\n * Free-form per-instance metadata register. Middleware pipelines append to this — typically\n * with a text description, transcript, caption, or alt-text — so downstream code that cannot\n * consume the media natively has a model-readable fallback. No keys are reserved by the\n * framework. Defaults to `{}`.\n */\n stash?: Record<string, MediaStashEntry>\n}\n\nconst stashEntrySchema = validator\n .object<MediaStashEntry>({\n value: validator.any().required(),\n trustTier: validator\n .string()\n .valid(...MediaTrustTier)\n .required(),\n derivedFromMedia: validator.string().optional(),\n })\n .unknown(false)\n\n/**\n * Validator schema used to validate a {@link RawMedia} before constructing a {@link Media}.\n */\nconst rawMediaSchema = validator.object<RawMedia>({\n id: validator.string().optional(),\n kind: validator\n .string()\n .valid(...MediaKind)\n .required(),\n mimeType: validator.string().required(),\n filename: validator.string().required(),\n reader: mediaReaderSchema.required(),\n trustTier: validator\n .string()\n .valid(...MediaTrustTier)\n .required(),\n modalityHazard: validator\n .string()\n .valid(...MediaModalityHazard)\n .required(),\n source: validator.string().optional(),\n stash: validator.object().pattern(validator.string(), stashEntrySchema).optional(),\n})\n\ninterface ResolvedMedia {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n trustTier: MediaTrustTier\n modalityHazard: MediaModalityHazard\n source?: string\n stash?: Record<string, MediaStashEntry>\n}\n\nconst conservativeHazardForKind = (kind: MediaKind): MediaModalityHazard => {\n return kind === 'document' ? 'extractable-instructions' : 'opaque-perceptual'\n}\n\n/**\n * Shape returned by {@link Media.toJSON}. Metadata-only — bytes and the reader are stripped so\n * naive event/log serialisation never materialises bytes.\n */\nexport interface SerializedMedia {\n id: string\n kind: MediaKind\n mimeType: string\n filename: string\n source?: string\n trustTier: MediaTrustTier\n modalityHazard: MediaModalityHazard\n stash: Record<string, MediaStashEntry>\n byteLength?: number\n}\n\n/**\n * Cross-environment base64 encoder for a `Uint8Array`.\n *\n * @remarks\n * Prefers Node's `Buffer.from(buf).toString('base64')` when `globalThis.Buffer` exists; otherwise\n * chunk-encodes through `btoa` with a 0x8000-byte window to avoid `Maximum call stack size\n * exceeded` on large buffers.\n */\nconst encodeBase64 = (bytes: Uint8Array): string => {\n const maybeBuffer = (\n globalThis as { Buffer?: { from(b: Uint8Array): { toString(enc: string): string } } }\n ).Buffer\n if (maybeBuffer && typeof maybeBuffer.from === 'function') {\n return maybeBuffer.from(bytes).toString('base64')\n }\n const chunkSize = 0x8000\n let binary = ''\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, i + chunkSize)\n binary += String.fromCharCode.apply(null, Array.from(chunk) as number[])\n }\n return btoa(binary)\n}\n\n/**\n * Lazy, re-openable view over a binary asset (image, audio, video, document).\n *\n * @remarks\n * Dual-peer to {@link @nhtio/adk!Tokenizable} (silo) and {@link @nhtio/adk!SpooledArtifact}\n * (handle). Wraps a {@link @nhtio/adk!MediaReader} contract — the framework owns the contract, the\n * implementor owns the storage backend. Bytes are reached only through the reader; the primitive\n * itself never inlines bytes.\n *\n * Construction requires `trustTier` and `modalityHazard` — the framework refuses to guess\n * provenance or decoding hazard. Ergonomic factories ({@link Media.userAttachment},\n * {@link Media.toolGenerated}, {@link Media.retrievedPublic}, {@link Media.retrievedPrivate})\n * force the labelling decision at the call site without becoming defaults on the bare\n * constructor.\n */\nexport class Media {\n /**\n * Validator schema that accepts a {@link RawMedia} object.\n */\n public static schema = rawMediaSchema\n\n /**\n * The set of recognised media kinds. Exposed for downstream schemas that need to discriminate\n * on `kind`.\n */\n public static MediaKind = MediaKind\n\n /**\n * The set of recognised trust tiers.\n */\n public static MediaTrustTier = MediaTrustTier\n\n /**\n * The set of recognised modality hazards.\n */\n public static MediaModalityHazard = MediaModalityHazard\n\n /**\n * Returns `true` if `value` is a {@link Media} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Media} instance.\n */\n public static isMedia(value: unknown): value is Media {\n return isInstanceOf(value, 'Media', Media)\n }\n\n /** Stable unique identifier. */\n declare readonly id: string\n /** Media kind. */\n declare readonly kind: MediaKind\n /** MIME type of the underlying bytes. */\n declare readonly mimeType: string\n /** Filename surfaced to providers that key on it. */\n declare readonly filename: string\n /** Optional provenance pointer. */\n declare readonly source: string | undefined\n /** Trust tier declared at construction time. */\n declare readonly trustTier: MediaTrustTier\n /** Modality hazard declared at construction time. */\n declare readonly modalityHazard: MediaModalityHazard\n /** Mutable per-instance metadata register; middleware pipelines append to this. */\n declare readonly stash: Registry\n\n #id: string\n #kind: MediaKind\n #mimeType: string\n #filename: string\n #source?: string\n #trustTier: MediaTrustTier\n #modalityHazard: MediaModalityHazard\n #reader: MediaReader\n #stash: Registry\n\n /**\n * @param raw - The raw media input validated against `rawMediaSchema`.\n * @throws {@link @nhtio/adk/exceptions!E_INVALID_INITIAL_MEDIA_VALUE} when `raw` does not satisfy the schema.\n * @throws {@link @nhtio/adk/exceptions!E_NOT_A_MEDIA_READER} when `raw.reader` does not implement {@link @nhtio/adk!MediaReader}.\n */\n constructor(raw: RawMedia) {\n let resolved: ResolvedMedia\n try {\n resolved = validateOrThrow<ResolvedMedia>(rawMediaSchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_MEDIA_VALUE({ cause: isError(err) ? err : undefined })\n }\n if (!implementsMediaReader(resolved.reader)) {\n throw new E_NOT_A_MEDIA_READER()\n }\n this.#id = resolved.id ?? uuidv6()\n this.#kind = resolved.kind\n this.#mimeType = resolved.mimeType\n this.#filename = resolved.filename\n this.#source = resolved.source\n this.#trustTier = resolved.trustTier\n this.#modalityHazard = resolved.modalityHazard\n this.#reader = resolved.reader\n this.#stash = new Registry(resolved.stash as Record<string, unknown> | undefined)\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n kind: {\n get: () => this.#kind,\n enumerable: true,\n configurable: false,\n },\n mimeType: {\n get: () => this.#mimeType,\n enumerable: true,\n configurable: false,\n },\n filename: {\n get: () => this.#filename,\n enumerable: true,\n configurable: false,\n },\n source: {\n get: () => this.#source,\n enumerable: true,\n configurable: false,\n },\n trustTier: {\n get: () => this.#trustTier,\n enumerable: true,\n configurable: false,\n },\n modalityHazard: {\n get: () => this.#modalityHazard,\n enumerable: true,\n configurable: false,\n },\n stash: {\n get: () => this.#stash,\n enumerable: true,\n configurable: false,\n },\n })\n }\n\n /**\n * Re-opens the underlying byte source and returns a fresh ReadableStream.\n *\n * @returns A drainable `ReadableStream` over the underlying bytes.\n */\n async stream(): Promise<ReadableStream<Uint8Array>> {\n return this.#reader.stream()\n }\n\n /**\n * Returns the total number of bytes in the underlying data, or `undefined` if unknown.\n *\n * @returns The byte length, or `undefined` when the underlying source cannot report it.\n */\n async byteLength(): Promise<number | undefined> {\n return this.#reader.byteLength()\n }\n\n /**\n * Drains the reader's stream and returns the underlying bytes as a single `Uint8Array`.\n *\n * @remarks\n * Convenience for callers that need the full buffer (e.g. inline base64 encoding). Forces\n * full materialisation — large assets should be piped through {@link Media.stream} instead.\n */\n async asBytes(): Promise<Uint8Array> {\n const stream = await this.stream()\n const reader = stream.getReader()\n const chunks: Uint8Array[] = []\n let total = 0\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n if (value) {\n chunks.push(value)\n total += value.byteLength\n }\n }\n const out = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n out.set(chunk, offset)\n offset += chunk.byteLength\n }\n return out\n }\n\n /**\n * Drains the reader's stream and returns the underlying bytes as a base64 string.\n *\n * @remarks\n * Cross-environment: prefers Node's `Buffer.from(buf).toString('base64')` when available;\n * otherwise chunk-encodes through `btoa` with a 0x8000-byte window to avoid stack overflow\n * on large buffers.\n */\n async asBase64(): Promise<string> {\n const bytes = await this.asBytes()\n return encodeBase64(bytes)\n }\n\n /**\n * Returns the metadata-only serialisation of this Media. Bytes and the reader are stripped\n * so naive event/log serialisation never materialises bytes.\n *\n * @remarks\n * Implementations that have cheap, already-cached `byteLength` may opt to include it; this\n * default implementation omits it to preserve the \"lazy by default\" invariant. Consumers that\n * need byteLength on the serialised payload should call `await media.byteLength()` and merge\n * the result.\n */\n toJSON(): SerializedMedia {\n return {\n id: this.#id,\n kind: this.#kind,\n mimeType: this.#mimeType,\n filename: this.#filename,\n source: this.#source,\n trustTier: this.#trustTier,\n modalityHazard: this.#modalityHazard,\n stash: this.#stash.all() as Record<string, MediaStashEntry>,\n }\n }\n\n /**\n * Factory: constructs a {@link Media} representing a user-supplied attachment.\n *\n * @remarks\n * Pre-fills `trustTier: 'third-party-private'` and derives `modalityHazard` from `kind`\n * (`document` → `'extractable-instructions'`; everything else → `'opaque-perceptual'`).\n * Use the bare constructor when the conservative kind→hazard mapping is wrong for your case.\n */\n public static userAttachment(args: {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n source?: string\n stash?: Record<string, MediaStashEntry>\n }): Media {\n return new Media({\n ...args,\n trustTier: 'third-party-private',\n modalityHazard: conservativeHazardForKind(args.kind),\n })\n }\n\n /**\n * Factory: constructs a {@link Media} produced by a first-party tool.\n *\n * @remarks\n * Pre-fills `trustTier: 'first-party'` and derives `modalityHazard` from `kind`.\n */\n public static toolGenerated(args: {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n source?: string\n stash?: Record<string, MediaStashEntry>\n }): Media {\n return new Media({\n ...args,\n trustTier: 'first-party',\n modalityHazard: conservativeHazardForKind(args.kind),\n })\n }\n\n /**\n * Factory: constructs a {@link Media} retrieved from a public third-party source.\n *\n * @remarks\n * Pre-fills `trustTier: 'third-party-public'` and derives `modalityHazard` from `kind`.\n */\n public static retrievedPublic(args: {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n source?: string\n stash?: Record<string, MediaStashEntry>\n }): Media {\n return new Media({\n ...args,\n trustTier: 'third-party-public',\n modalityHazard: conservativeHazardForKind(args.kind),\n })\n }\n\n /**\n * Factory: constructs a {@link Media} retrieved from a private third-party source.\n *\n * @remarks\n * Pre-fills `trustTier: 'third-party-private'` and derives `modalityHazard` from `kind`.\n */\n public static retrievedPrivate(args: {\n id?: string\n kind: MediaKind\n mimeType: string\n filename: string\n reader: MediaReader\n source?: string\n stash?: Record<string, MediaStashEntry>\n }): Media {\n return new Media({\n ...args,\n trustTier: 'third-party-private',\n modalityHazard: conservativeHazardForKind(args.kind),\n })\n }\n}\n\n/**\n * Returns `true` if `value` is a {@link Media} instance.\n *\n * @remarks\n * Module-level convenience alias for {@link Media.isMedia}. Uses {@link @nhtio/adk!isInstanceOf} for\n * cross-realm safety.\n */\nexport const isMedia = (value: unknown): value is Media => {\n return isInstanceOf(value, 'Media', Media)\n}\n","import { Media } from './media'\nimport { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { SpooledArtifact } from './spooled_artifact'\nimport { validateOrThrow } from '../utils/validation'\nimport { isObject, isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_TOOL_CALL_VALUE } from '../exceptions/runtime'\nimport type { DateTime } from 'luxon'\n\n/**\n * Union of every shape a {@link ToolCall.results} field may carry.\n *\n * @remarks\n * Three silos with distinct render-time semantics:\n *\n * - {@link @nhtio/adk!Tokenizable} — always singular. The {@link @nhtio/adk!ArtifactTool}\n * carve-out: a model-visible text answer that explicitly opts out of artifact wrapping to\n * break the recursive grep-on-the-grep-result loop.\n * - {@link @nhtio/adk!SpooledArtifact} or `SpooledArtifact[]` — bounded text output spooled to durable\n * storage. A single tool call may legitimately produce multiple artifacts (e.g. one tool\n * that returns N PR bodies). LLM adapters render either inline (full body in trust envelope)\n * or as a handle reference (forged artifact-query tools).\n * - {@link @nhtio/adk!Media} or `Media[]` — binary modality output (image, audio, video, document).\n * Adapters render as provider-specific content blocks (`image_url`, `input_audio`, `file`,\n * etc.). Bytes are lazy — reached only through {@link @nhtio/adk!Media.stream}.\n */\nexport type ToolCallResults = Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]\n\nconst isToolCallResults = (value: unknown): value is ToolCallResults => {\n if (Tokenizable.isTokenizable(value)) return true\n if (SpooledArtifact.isSpooledArtifact(value)) return true\n if (Media.isMedia(value)) return true\n if (Array.isArray(value) && value.length > 0) {\n const allMedia = value.every((entry) => Media.isMedia(entry))\n if (allMedia) return true\n const allSpooled = value.every((entry) => SpooledArtifact.isSpooledArtifact(entry))\n if (allSpooled) return true\n }\n return false\n}\n\n/**\n * Plain input object supplied to {@link ToolCall} at construction time.\n *\n * @remarks\n * Validated against `rawToolCallSchema` before the `ToolCall` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n */\nexport interface RawToolCall {\n /** Stable unique identifier for this tool call; correlates the request with its result. */\n id: string\n /** Name of the tool the model has requested. */\n tool: string\n /**\n * Arguments the model supplied for this tool call.\n *\n * @remarks\n * Accepts either a plain object or a JSON-encoded string that deserialises to an object.\n * Always exposed as a plain object on the constructed {@link ToolCall} instance.\n */\n args: string | Record<string, unknown>\n /** Integrity checksum over `tool` and `args`; can be used to detect tampering before execution. */\n checksum: string\n /** `true` once the tool call has finished (successfully or not). */\n isComplete: boolean\n /** `true` when the tool execution produced an error; inspect `results` for detail. */\n isError: boolean\n /**\n * Result returned by the tool, or error detail when `isError` is `true`.\n *\n * @remarks\n * Three silos with distinct render-time semantics — see {@link ToolCallResults}:\n *\n * - For a normal {@link @nhtio/adk!Tool} call whose handler returned `string` or\n * `Uint8Array`, this is a {@link @nhtio/adk!SpooledArtifact} (or one of its subclasses) wrapping the\n * spooled bytes. Tools that legitimately produce multiple bounded artifacts may return\n * a `SpooledArtifact[]`.\n * - For a `Tool` call whose handler returned a {@link @nhtio/adk!Media} or `Media[]`, this is the same\n * media handle(s) — the explicit-modality silo bypasses `SpooledArtifact` wrapping because\n * the bytes are binary and rendered as provider-specific content blocks, not text.\n * - For an {@link @nhtio/adk!ArtifactTool} call (a forged artifact-query tool),\n * this is a {@link @nhtio/adk!Tokenizable} holding the raw model-visible answer — `ArtifactTool`\n * explicitly opts out of wrapping to break the recursive grep-on-the-grep-result loop.\n *\n * The ADK sets {@link RawToolCall.fromArtifactTool} on calls produced by an\n * `ArtifactTool` so subsequent `forgeTools(ctx)` invocations can filter them out of the\n * `callId` enum.\n */\n results: ToolCallResults\n /**\n * `true` when this tool call originated from an {@link @nhtio/adk!ArtifactTool}\n * invocation. Defaults to `false`.\n *\n * @remarks\n * Set by the ADK's result-wrapping touch sites when `ArtifactTool.isArtifactTool(tool)`\n * holds. Read by `SpooledArtifact.forgeTools(ctx)` when building each descriptor's `callId`\n * enum — calls with this flag set are excluded so the model can't `artifact_grep` on a\n * previous `artifact_grep` result. Optional in the raw shape (defaults to `false`); always\n * defined on the constructed {@link ToolCall}.\n *\n * @defaultValue `false`\n */\n fromArtifactTool?: boolean\n /**\n * When `true` (default), LLM adapters render this tool call's result inline — the full\n * stringified body is wrapped in the adapter's trust envelope and sent to the model as the\n * `tool` role content. When `false`, the adapter surfaces the result as a \"handle\" — a\n * directions-bearing envelope that tells the model which forged artifact-query tools to call\n * against this `tc.id` to read the content incrementally.\n *\n * @remarks\n * Policy is the producer's or middleware's call:\n * - A normal tool returns its result with `inline: true` by default so its output is shown\n * verbatim.\n * - Middleware that wants to keep large results out of the model's prompt sets `inline: false`\n * (typically via `ctx.mutateToolCall(tc.id, { inline: false })`) before yielding.\n * - LLM adapters do not override the flag, do not size-check the result, and do not silently\n * switch to the handle pattern.\n *\n * For {@link @nhtio/adk!Tokenizable} results, the flag is effectively informational — handles only make\n * sense for {@link @nhtio/adk!SpooledArtifact} (which is the only result kind the forged artifact-query\n * tools can read). When `inline: false` is set on a call whose `results` is a `Tokenizable`,\n * the adapter renders inline anyway and may log a warning.\n *\n * @defaultValue `true`\n */\n inline?: boolean\n /** When this tool call was first created. */\n createdAt: string | number | Date | DateTime\n /** When this tool call was last modified. */\n updatedAt: string | number | Date | DateTime\n /** When the tool call completed. */\n completedAt: string | number | Date | DateTime\n}\n\n/**\n * A fully-resolved {@link RawToolCall} where temporal fields have been normalised to Luxon\n * `DateTime` instances.\n *\n * @remarks\n * Used internally by the {@link ToolCall} constructor to assign private fields with\n * guaranteed types.\n */\ninterface ResolvedToolCall {\n id: string\n tool: string\n args: Record<string, unknown>\n checksum: string\n isComplete: boolean\n isError: boolean\n results: ToolCallResults\n fromArtifactTool: boolean\n inline: boolean\n createdAt: DateTime\n updatedAt: DateTime\n completedAt: DateTime\n}\n\n/**\n * Validator schema used to validate a {@link RawToolCall} before constructing a {@link ToolCall}.\n *\n * @remarks\n * Validates all fields of {@link RawToolCall}:\n * - `id` — required non-empty string.\n * - `tool` — required non-empty string.\n * - `args` — required; either a plain object or a JSON string that deserialises to an object.\n * Strings are parsed and the resulting object is stored.\n * - `checksum` — required string.\n * - `isComplete` — required boolean.\n * - `isError` — required boolean.\n * - `results` — required; one of {@link @nhtio/adk!Tokenizable}, {@link @nhtio/adk!SpooledArtifact}, a non-empty\n * `SpooledArtifact[]`, {@link @nhtio/adk!Media}, or a non-empty `Media[]`. Arrays must be homogeneous.\n * - `createdAt` / `updatedAt` / `completedAt` — required datetime-parseable values, normalised to `DateTime`.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_CALL_VALUE} (via the {@link ToolCall} constructor) when\n * validation fails.\n */\nconst rawToolCallSchema = validator.object<RawToolCall>({\n id: validator.string().required(),\n tool: validator.string().required(),\n args: validator\n .alternatives(\n validator.object().unknown(true),\n validator.string().custom((value, helpers) => {\n try {\n const parsed = JSON.parse(value)\n if (!isObject(parsed)) {\n return helpers.error('any.invalid')\n }\n return parsed\n } catch {\n return helpers.error('any.invalid')\n }\n })\n )\n .required(),\n checksum: validator.string().required(),\n isComplete: validator.boolean().required(),\n isError: validator.boolean().required(),\n results: validator\n .any()\n .custom((value, helpers) => {\n if (isToolCallResults(value)) {\n return value\n }\n return helpers.error('any.invalid')\n })\n .required(),\n fromArtifactTool: validator.boolean().default(false),\n inline: validator.boolean().default(true),\n createdAt: validator.datetime().required(),\n updatedAt: validator.datetime().required(),\n completedAt: validator.datetime().required(),\n})\n\n/**\n * An immutable, validated tool call record associated with a turn.\n *\n * @remarks\n * Represents a completed tool invocation from the conversation history — `results`,\n * `completedAt`, `isComplete`, and `isError` are all present and required.\n * Temporal fields are normalised to Luxon `DateTime` instances at construction time.\n */\nexport class ToolCall {\n /**\n * Validator schema that accepts a {@link RawToolCall} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a tool call entry.\n */\n public static schema = rawToolCallSchema\n\n /**\n * Returns `true` if `value` is a {@link ToolCall} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link ToolCall} instance.\n */\n public static isToolCall(value: unknown): value is ToolCall {\n return isInstanceOf(value, 'ToolCall', ToolCall)\n }\n\n /** Stable unique identifier for this tool call; correlates the request with its result. */\n declare readonly id: string\n /** Name of the tool the model has requested. */\n declare readonly tool: string\n /** Arguments the model supplied for this tool call, always as a plain object. */\n declare readonly args: Record<string, unknown>\n /** Integrity checksum over `tool` and `args`. */\n declare readonly checksum: string\n /** `true` once the tool call has finished (successfully or not). */\n declare readonly isComplete: boolean\n /** `true` when the tool execution produced an error; inspect `results` for detail. */\n declare readonly isError: boolean\n /**\n * Result returned by the tool, or error detail when `isError` is `true`.\n *\n * @remarks\n * One of three silos — see {@link ToolCallResults}. {@link @nhtio/adk!SpooledArtifact} or\n * `SpooledArtifact[]` for normal text-output {@link @nhtio/adk!Tool} calls;\n * {@link @nhtio/adk!Media} or `Media[]` for tool calls whose handler returned binary modality output;\n * {@link @nhtio/adk!Tokenizable} for {@link @nhtio/adk!ArtifactTool} calls\n * (see {@link ToolCall.fromArtifactTool}).\n */\n declare readonly results: ToolCallResults\n /**\n * `true` when this tool call originated from an {@link @nhtio/adk!ArtifactTool}\n * invocation. Used by `SpooledArtifact.forgeTools(ctx)` to filter out forged-tool results from\n * the `callId` enum it builds.\n */\n declare readonly fromArtifactTool: boolean\n /**\n * `true` (default) renders this tool call's result inline in the prompt; `false` instructs LLM\n * adapters to surface the result as a handle reference. See {@link RawToolCall.inline}.\n */\n declare readonly inline: boolean\n /** When this tool call was first created. */\n declare readonly createdAt: DateTime\n /** When this tool call was last modified. */\n declare readonly updatedAt: DateTime\n /** When the tool call completed. */\n declare readonly completedAt: DateTime\n\n #id: string\n #tool: string\n #args: Record<string, unknown>\n #checksum: string\n #isComplete: boolean\n #isError: boolean\n #results: ToolCallResults\n #fromArtifactTool: boolean\n #inline: boolean\n #createdAt: DateTime\n #updatedAt: DateTime\n #completedAt: DateTime\n\n /**\n * @param raw - The raw tool call input validated against `rawToolCallSchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_CALL_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawToolCall) {\n let resolved: ResolvedToolCall\n try {\n resolved = validateOrThrow<ResolvedToolCall>(rawToolCallSchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_TOOL_CALL_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#id = resolved.id\n this.#tool = resolved.tool\n this.#args = resolved.args\n this.#checksum = resolved.checksum\n this.#isComplete = resolved.isComplete\n this.#isError = resolved.isError\n this.#results = resolved.results\n this.#fromArtifactTool = resolved.fromArtifactTool\n this.#inline = resolved.inline\n this.#createdAt = resolved.createdAt\n this.#updatedAt = resolved.updatedAt\n this.#completedAt = resolved.completedAt\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n tool: {\n get: () => this.#tool,\n enumerable: true,\n configurable: false,\n },\n args: {\n get: () => this.#args,\n enumerable: true,\n configurable: false,\n },\n checksum: {\n get: () => this.#checksum,\n enumerable: true,\n configurable: false,\n },\n isComplete: {\n get: () => this.#isComplete,\n enumerable: true,\n configurable: false,\n },\n isError: {\n get: () => this.#isError,\n enumerable: true,\n configurable: false,\n },\n results: {\n get: () => this.#results,\n enumerable: true,\n configurable: false,\n },\n fromArtifactTool: {\n get: () => this.#fromArtifactTool,\n enumerable: true,\n configurable: false,\n },\n inline: {\n get: () => this.#inline,\n enumerable: true,\n configurable: false,\n },\n createdAt: {\n get: () => this.#createdAt,\n enumerable: true,\n configurable: false,\n },\n updatedAt: {\n get: () => this.#updatedAt,\n enumerable: true,\n configurable: false,\n },\n completedAt: {\n get: () => this.#completedAt,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n"],"mappings":"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"}
|