@nhtio/adk 1.20260921.0 → 1.20260925.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 +92 -0
- package/adk-mcp.cjs +2 -2
- package/{arg_specs-iYmIM3wI.js → arg_specs-iYmIM3wI.cjs} +1 -1
- package/arg_specs-iYmIM3wI.cjs.map +1 -0
- package/artifact_methods-9BemAvd4.mjs +1 -0
- package/artifact_methods-FKgk4q_1.cjs +1 -0
- package/batteries/artifacts/ecmascript.cjs +2 -2
- package/batteries/artifacts/ecmascript.mjs +1 -1
- package/batteries/artifacts/toon.cjs +2 -2
- package/batteries/artifacts/toon.mjs +1 -1
- package/batteries/artifacts/xml.cjs +2 -2
- package/batteries/artifacts/xml.mjs +1 -1
- package/batteries/artifacts/yaml.cjs +2 -2
- package/batteries/artifacts/yaml.mjs +1 -1
- package/batteries/artifacts.cjs +5 -5
- package/batteries/artifacts.mjs +4 -4
- package/batteries/context/compact/contracts.cjs +1 -1
- package/batteries/context/compact/summarizer.cjs +1 -1
- package/batteries/context/compact.cjs +1 -1
- package/batteries/context/exceptions.cjs +2 -2
- package/batteries/context/thrift/contracts.cjs +1 -1
- package/batteries/context/thrift/relevance.cjs +1 -1
- package/batteries/context/thrift/subtractive_pass.cjs +1 -1
- package/batteries/context/thrift.cjs +1 -1
- package/batteries/context.cjs +1 -1
- package/batteries/dev-tools/conformance.cjs +2 -2
- package/batteries/dev-tools/forge.cjs +5 -5
- package/batteries/dev-tools/forge.mjs +3 -3
- package/batteries/dev-tools.cjs +9 -9
- package/batteries/dev-tools.mjs +3 -3
- package/batteries/embeddings/ollama/adapter.cjs +2 -2
- package/batteries/embeddings/ollama/exceptions.cjs +2 -2
- package/batteries/embeddings/ollama/types.cjs +1 -1
- package/batteries/embeddings/ollama/validation.cjs +1 -1
- package/batteries/embeddings/ollama.cjs +1 -1
- package/batteries/embeddings/openai/adapter.cjs +2 -2
- package/batteries/embeddings/openai/exceptions.cjs +2 -2
- package/batteries/embeddings/openai/helpers.cjs +1 -1
- package/batteries/embeddings/openai/types.cjs +1 -1
- package/batteries/embeddings/openai/validation.cjs +1 -1
- package/batteries/embeddings/openai.cjs +1 -1
- package/batteries/embeddings/transformers_js/adapter.cjs +3 -3
- package/batteries/embeddings/transformers_js/exceptions.cjs +2 -2
- package/batteries/embeddings/transformers_js/pooling.cjs +1 -1
- package/batteries/embeddings/transformers_js/types.cjs +1 -1
- package/batteries/embeddings/transformers_js/validation.cjs +2 -2
- package/batteries/embeddings/transformers_js.cjs +1 -1
- package/batteries/embeddings/webllm/adapter.cjs +2 -2
- package/batteries/embeddings/webllm/exceptions.cjs +2 -2
- package/batteries/embeddings/webllm/types.cjs +1 -1
- package/batteries/embeddings/webllm/validation.cjs +1 -1
- package/batteries/embeddings/webllm.cjs +1 -1
- package/batteries/embeddings.cjs +1 -1
- package/batteries/encoding.cjs +8 -8
- package/batteries/encoding.mjs +7 -7
- package/batteries/generation/_shared.cjs +2 -2
- package/batteries/generation/gemini/adapter.cjs +3 -3
- package/batteries/generation/gemini/adapter.mjs +1 -1
- package/batteries/generation/gemini/exceptions.cjs +2 -2
- package/batteries/generation/gemini/types.cjs +1 -1
- package/batteries/generation/gemini/validation.cjs +1 -1
- package/batteries/generation/gemini.cjs +1 -1
- package/batteries/generation/local_diffusion/adapter.cjs +5 -5
- package/batteries/generation/local_diffusion/adapter.mjs +2 -2
- package/batteries/generation/local_diffusion/exceptions.cjs +2 -2
- package/batteries/generation/local_diffusion/protocol.cjs +2 -2
- package/batteries/generation/local_diffusion/types.cjs +1 -1
- package/batteries/generation/local_diffusion/validation.cjs +1 -1
- package/batteries/generation/local_diffusion.cjs +1 -1
- package/batteries/generation/openai/adapter.cjs +3 -3
- package/batteries/generation/openai/adapter.mjs +1 -1
- package/batteries/generation/openai/exceptions.cjs +2 -2
- package/batteries/generation/openai/types.cjs +1 -1
- package/batteries/generation/openai/validation.cjs +1 -1
- package/batteries/generation/openai.cjs +1 -1
- package/batteries/generation/transformers_js/adapter.cjs +3 -3
- package/batteries/generation/transformers_js/exceptions.cjs +2 -2
- package/batteries/generation/transformers_js/helpers.cjs +1 -1
- package/batteries/generation/transformers_js/types.cjs +1 -1
- package/batteries/generation/transformers_js/validation.cjs +2 -2
- package/batteries/generation/transformers_js.cjs +1 -1
- package/batteries/generation.cjs +1 -1
- package/batteries/isolation/child_process.cjs +3 -3
- package/batteries/isolation/child_process.mjs +1 -1
- package/batteries/isolation.cjs +2 -2
- package/batteries/isolation.mjs +1 -1
- package/batteries/llm/anthropic_messages/adapter.cjs +10 -10
- package/batteries/llm/anthropic_messages/adapter.mjs +6 -6
- package/batteries/llm/anthropic_messages/count_tokens.cjs +4 -4
- package/batteries/llm/anthropic_messages/count_tokens.mjs +1 -1
- package/batteries/llm/anthropic_messages/error_translation.cjs +2 -2
- package/batteries/llm/anthropic_messages/exceptions.cjs +2 -2
- package/batteries/llm/anthropic_messages/helpers.cjs +4 -4
- package/batteries/llm/anthropic_messages/helpers.mjs +3 -3
- package/batteries/llm/anthropic_messages/types.cjs +1 -1
- package/batteries/llm/anthropic_messages/validation.cjs +3 -3
- package/batteries/llm/anthropic_messages/validation.mjs +2 -2
- package/batteries/llm/anthropic_messages.cjs +4 -4
- package/batteries/llm/anthropic_messages.mjs +2 -2
- package/batteries/llm/bedrock_converse/adapter.cjs +165 -24
- package/batteries/llm/bedrock_converse/adapter.cjs.map +1 -1
- package/batteries/llm/bedrock_converse/adapter.mjs +162 -21
- package/batteries/llm/bedrock_converse/adapter.mjs.map +1 -1
- package/batteries/llm/bedrock_converse/exceptions.cjs +2 -2
- package/batteries/llm/bedrock_converse/helpers.cjs +3 -3
- package/batteries/llm/bedrock_converse/helpers.mjs +1 -1
- package/batteries/llm/bedrock_converse/types.cjs +1 -1
- package/batteries/llm/bedrock_converse/validation.cjs +3 -3
- package/batteries/llm/bedrock_converse/validation.mjs +2 -2
- package/batteries/llm/bedrock_converse.cjs +3 -3
- package/batteries/llm/bedrock_converse.mjs +2 -2
- package/batteries/llm/chat_common/exceptions.cjs +2 -2
- package/batteries/llm/claude_code_cli/adapter.cjs +349 -49
- package/batteries/llm/claude_code_cli/adapter.cjs.map +1 -1
- package/batteries/llm/claude_code_cli/adapter.d.ts +125 -0
- package/batteries/llm/claude_code_cli/adapter.mjs +347 -49
- package/batteries/llm/claude_code_cli/adapter.mjs.map +1 -1
- package/batteries/llm/claude_code_cli/exceptions.cjs +13 -2
- package/batteries/llm/claude_code_cli/exceptions.cjs.map +1 -1
- package/batteries/llm/claude_code_cli/exceptions.d.ts +12 -0
- package/batteries/llm/claude_code_cli/exceptions.mjs +11 -1
- package/batteries/llm/claude_code_cli/exceptions.mjs.map +1 -1
- package/batteries/llm/claude_code_cli/helpers.cjs +4 -4
- package/batteries/llm/claude_code_cli/helpers.mjs +3 -3
- package/batteries/llm/claude_code_cli/index.d.ts +3 -2
- package/batteries/llm/claude_code_cli/line_queue.d.ts +39 -0
- package/batteries/llm/claude_code_cli/message_id_state.d.ts +48 -0
- package/batteries/llm/claude_code_cli/types.cjs +1 -1
- package/batteries/llm/claude_code_cli/types.d.ts +112 -2
- package/batteries/llm/claude_code_cli/validation.cjs +7 -3
- package/batteries/llm/claude_code_cli/validation.cjs.map +1 -1
- package/batteries/llm/claude_code_cli/validation.mjs +6 -2
- package/batteries/llm/claude_code_cli/validation.mjs.map +1 -1
- package/batteries/llm/claude_code_cli/wire.cjs +1 -1
- package/batteries/llm/claude_code_cli/wire.cjs.map +1 -1
- package/batteries/llm/claude_code_cli/wire.d.ts +45 -1
- package/batteries/llm/claude_code_cli/wire.mjs.map +1 -1
- package/batteries/llm/claude_code_cli/wrapper.d.ts +5 -4
- package/batteries/llm/claude_code_cli.cjs +5 -2
- package/batteries/llm/claude_code_cli.mjs +4 -3
- package/batteries/llm/gemini_generate_content/adapter.cjs +163 -22
- package/batteries/llm/gemini_generate_content/adapter.cjs.map +1 -1
- package/batteries/llm/gemini_generate_content/adapter.mjs +160 -19
- package/batteries/llm/gemini_generate_content/adapter.mjs.map +1 -1
- package/batteries/llm/gemini_generate_content/exceptions.cjs +2 -2
- package/batteries/llm/gemini_generate_content/helpers.cjs +3 -3
- package/batteries/llm/gemini_generate_content/helpers.mjs +1 -1
- package/batteries/llm/gemini_generate_content/types.cjs +1 -1
- package/batteries/llm/gemini_generate_content/validation.cjs +3 -3
- package/batteries/llm/gemini_generate_content/validation.mjs +2 -2
- package/batteries/llm/gemini_generate_content.cjs +2 -2
- package/batteries/llm/gemini_generate_content.mjs +1 -1
- package/batteries/llm/index.d.ts +1 -1
- package/batteries/llm/litert_lm/adapter.cjs +11 -11
- package/batteries/llm/litert_lm/adapter.mjs +6 -6
- package/batteries/llm/litert_lm/exceptions.cjs +2 -2
- package/batteries/llm/litert_lm/helpers.cjs +7 -7
- package/batteries/llm/litert_lm/helpers.mjs +3 -3
- package/batteries/llm/litert_lm/types.cjs +1 -1
- package/batteries/llm/litert_lm/validation.cjs +4 -4
- package/batteries/llm/litert_lm/validation.mjs +2 -2
- package/batteries/llm/litert_lm.cjs +5 -5
- package/batteries/llm/litert_lm.mjs +1 -1
- package/batteries/llm/ollama/adapter.cjs +9 -9
- package/batteries/llm/ollama/adapter.mjs +6 -6
- package/batteries/llm/ollama/exceptions.cjs +2 -2
- package/batteries/llm/ollama/helpers.cjs +5 -5
- package/batteries/llm/ollama/helpers.mjs +4 -4
- package/batteries/llm/ollama/types.cjs +1 -1
- package/batteries/llm/ollama/validation.cjs +3 -3
- package/batteries/llm/ollama/validation.mjs +2 -2
- package/batteries/llm/ollama.cjs +3 -3
- package/batteries/llm/ollama.mjs +2 -2
- package/batteries/llm/openai_chat_completions/adapter.cjs +9 -9
- package/batteries/llm/openai_chat_completions/adapter.mjs +6 -6
- package/batteries/llm/openai_chat_completions/exceptions.cjs +2 -2
- package/batteries/llm/openai_chat_completions/helpers.cjs +5 -5
- package/batteries/llm/openai_chat_completions/helpers.mjs +4 -4
- package/batteries/llm/openai_chat_completions/types.cjs +1 -1
- package/batteries/llm/openai_chat_completions/validation.cjs +3 -3
- package/batteries/llm/openai_chat_completions/validation.mjs +2 -2
- package/batteries/llm/openai_chat_completions.cjs +3 -3
- package/batteries/llm/openai_chat_completions.mjs +2 -2
- package/batteries/llm/openai_responses/adapter.cjs +9 -9
- package/batteries/llm/openai_responses/adapter.mjs +6 -6
- package/batteries/llm/openai_responses/exceptions.cjs +2 -2
- package/batteries/llm/openai_responses/helpers.cjs +4 -4
- package/batteries/llm/openai_responses/helpers.mjs +3 -3
- package/batteries/llm/openai_responses/types.cjs +1 -1
- package/batteries/llm/openai_responses/validation.cjs +3 -3
- package/batteries/llm/openai_responses/validation.mjs +2 -2
- package/batteries/llm/openai_responses.cjs +3 -3
- package/batteries/llm/openai_responses.mjs +2 -2
- package/batteries/llm/transformers_js/adapter.cjs +11 -11
- package/batteries/llm/transformers_js/adapter.mjs +6 -6
- package/batteries/llm/transformers_js/exceptions.cjs +2 -2
- package/batteries/llm/transformers_js/helpers.cjs +8 -8
- package/batteries/llm/transformers_js/helpers.mjs +3 -3
- package/batteries/llm/transformers_js/model_source.cjs +2 -2
- package/batteries/llm/transformers_js/types.cjs +1 -1
- package/batteries/llm/transformers_js/validation.cjs +4 -4
- package/batteries/llm/transformers_js/validation.mjs +2 -2
- package/batteries/llm/transformers_js.cjs +5 -5
- package/batteries/llm/transformers_js.mjs +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.cjs +10 -10
- package/batteries/llm/webllm_chat_completions/adapter.mjs +6 -6
- package/batteries/llm/webllm_chat_completions/exceptions.cjs +2 -2
- package/batteries/llm/webllm_chat_completions/helpers.cjs +2 -2
- package/batteries/llm/webllm_chat_completions/helpers.mjs +1 -1
- package/batteries/llm/webllm_chat_completions/validation.cjs +3 -3
- package/batteries/llm/webllm_chat_completions/validation.mjs +2 -2
- package/batteries/llm/webllm_chat_completions.cjs +3 -3
- package/batteries/llm/webllm_chat_completions.mjs +2 -2
- package/batteries/llm.cjs +4 -3
- package/batteries/llm.mjs +4 -4
- package/batteries/media/contracts.cjs +2 -2
- package/batteries/media/engines/audio_decode.cjs +3 -3
- package/batteries/media/engines/data.cjs +4 -4
- package/batteries/media/engines/exceljs.cjs +4 -4
- package/batteries/media/engines/execa_executor.cjs +3 -3
- package/batteries/media/engines/fs_workspace.cjs +3 -3
- package/batteries/media/engines/jimp.cjs +3 -3
- package/batteries/media/engines/sharp.cjs +3 -3
- package/batteries/media/engines/sheetjs.cjs +6 -6
- package/batteries/media/engines/sheetjs.cjs.map +1 -1
- package/batteries/media/engines/soffice.cjs +2 -2
- package/batteries/media/engines/tesseract_js.cjs +3 -3
- package/batteries/media/engines/transformers_asr.cjs +3 -3
- package/batteries/media/forge.cjs +8 -8
- package/batteries/media/forge.mjs +4 -4
- package/batteries/media/lint.cjs +2 -2
- package/batteries/media/lint.mjs +1 -1
- package/batteries/media.cjs +6 -6
- package/batteries/orchestration/approval.cjs +2 -2
- package/batteries/orchestration/cells/jexl.cjs +3 -3
- package/batteries/orchestration/cells/jexl.mjs +1 -1
- package/batteries/orchestration/cells/lua.cjs +3 -3
- package/batteries/orchestration/cells/lua.mjs +1 -1
- package/batteries/orchestration/cells/structured.cjs +3 -3
- package/batteries/orchestration/cells/structured.mjs +1 -1
- package/batteries/orchestration/conformance.cjs +2 -2
- package/batteries/orchestration/dispatch_reasoner.cjs +6 -6
- package/batteries/orchestration/dispatch_reasoner.mjs +4 -4
- package/batteries/orchestration/encoding.cjs +2 -2
- package/batteries/orchestration/executor.cjs +4 -4
- package/batteries/orchestration/executor.mjs +2 -2
- package/batteries/orchestration/forge.cjs +5 -5
- package/batteries/orchestration/forge.mjs +3 -3
- package/batteries/orchestration/in_memory.cjs +1 -1
- package/batteries/orchestration/ops.cjs +1 -1
- package/batteries/orchestration/outline.cjs +2 -2
- package/batteries/orchestration/plan.cjs +1 -1
- package/batteries/orchestration/raw.cjs +2 -2
- package/batteries/orchestration/reason.cjs +1 -1
- package/batteries/orchestration/render.cjs +2 -2
- package/batteries/orchestration/runs.cjs +1 -1
- package/batteries/orchestration/templates.cjs +2 -2
- package/batteries/orchestration/types.cjs +1 -1
- package/batteries/orchestration/validation.cjs +5 -5
- package/batteries/orchestration/validation.mjs +2 -2
- package/batteries/orchestration.cjs +6 -6
- package/batteries/orchestration.mjs +4 -4
- package/batteries/sandbox/js.cjs +6 -6
- package/batteries/sandbox/js.mjs +1 -1
- package/batteries/sandbox/node.cjs +4 -4
- package/batteries/sandbox/tools.cjs +2 -2
- package/batteries/sandbox/tools.mjs +1 -1
- package/batteries/sandbox.cjs +11 -11
- package/batteries/sandbox.mjs +4 -4
- package/batteries/skills/conformance.cjs +1 -1
- package/batteries/skills/in_memory.cjs +2 -2
- package/batteries/skills/in_memory.mjs +1 -1
- package/batteries/skills.cjs +13 -13
- package/batteries/skills.mjs +9 -9
- package/batteries/specialists/_shared.cjs +2 -2
- package/batteries/specialists/caption/transformers_js/adapter.cjs +3 -3
- package/batteries/specialists/caption/transformers_js/exceptions.cjs +2 -2
- package/batteries/specialists/caption/transformers_js/types.cjs +1 -1
- package/batteries/specialists/caption/transformers_js/validation.cjs +2 -2
- package/batteries/specialists/caption/transformers_js.cjs +1 -1
- package/batteries/specialists/caption.cjs +1 -1
- package/batteries/specialists/ocr/tesseract_js/adapter.cjs +3 -3
- package/batteries/specialists/ocr/tesseract_js/exceptions.cjs +2 -2
- package/batteries/specialists/ocr/tesseract_js/types.cjs +1 -1
- package/batteries/specialists/ocr/tesseract_js/validation.cjs +2 -2
- package/batteries/specialists/ocr/tesseract_js.cjs +1 -1
- package/batteries/specialists/ocr.cjs +1 -1
- package/batteries/specialists/stt/transformers_js.cjs +2 -2
- package/batteries/specialists/stt/transformers_js.mjs +1 -1
- package/batteries/specialists/stt.cjs +2 -2
- package/batteries/specialists/stt.mjs +1 -1
- package/batteries/specialists.cjs +2 -2
- package/batteries/specialists.mjs +1 -1
- package/batteries/storage/flydrive.cjs +2 -2
- package/batteries/storage/in_memory.cjs +2 -2
- package/batteries/storage/opfs.cjs +2 -2
- package/batteries/storage.cjs +1 -1
- package/batteries/tools/_shared.cjs +4 -4
- package/batteries/tools/_shared.mjs +2 -2
- package/batteries/tools/color.cjs +3 -3
- package/batteries/tools/color.mjs +2 -2
- package/batteries/tools/comparison.cjs +4 -4
- package/batteries/tools/comparison.mjs +2 -2
- package/batteries/tools/data_structure.cjs +4 -4
- package/batteries/tools/data_structure.mjs +2 -2
- package/batteries/tools/datetime_extended.cjs +3 -3
- package/batteries/tools/datetime_extended.mjs +2 -2
- package/batteries/tools/datetime_math.cjs +3 -3
- package/batteries/tools/datetime_math.mjs +2 -2
- package/batteries/tools/encoding.cjs +4 -4
- package/batteries/tools/encoding.mjs +2 -2
- package/batteries/tools/formatting.cjs +4 -4
- package/batteries/tools/formatting.mjs +2 -2
- package/batteries/tools/geo_basics.cjs +3 -3
- package/batteries/tools/geo_basics.mjs +2 -2
- package/batteries/tools/math.cjs +4 -4
- package/batteries/tools/math.mjs +2 -2
- package/batteries/tools/memory.cjs +6 -6
- package/batteries/tools/memory.mjs +4 -4
- package/batteries/tools/parsing.cjs +5 -5
- package/batteries/tools/parsing.mjs +3 -3
- package/batteries/tools/retrievables.cjs +6 -6
- package/batteries/tools/retrievables.mjs +4 -4
- package/batteries/tools/scrapper.cjs +2 -2
- package/batteries/tools/scrapper.mjs +1 -1
- package/batteries/tools/searxng.cjs +2 -2
- package/batteries/tools/searxng.mjs +1 -1
- package/batteries/tools/standing_instructions.cjs +5 -5
- package/batteries/tools/standing_instructions.mjs +3 -3
- package/batteries/tools/statistics.cjs +5 -5
- package/batteries/tools/statistics.mjs +3 -3
- package/batteries/tools/string_processing.cjs +4 -4
- package/batteries/tools/string_processing.mjs +2 -2
- package/batteries/tools/structured_data.cjs +4 -4
- package/batteries/tools/structured_data.mjs +2 -2
- package/batteries/tools/text_analysis.cjs +4 -4
- package/batteries/tools/text_analysis.mjs +3 -3
- package/batteries/tools/text_comparison.cjs +3 -3
- package/batteries/tools/text_comparison.mjs +2 -2
- package/batteries/tools/time.cjs +3 -3
- package/batteries/tools/time.mjs +2 -2
- package/batteries/tools/unit_conversion.cjs +3 -3
- package/batteries/tools/unit_conversion.mjs +2 -2
- package/batteries/tools/web_retrieval.cjs +2 -2
- package/batteries/tools.cjs +3 -3
- package/batteries/tools.mjs +2 -2
- package/batteries/tts/_shared.cjs +1 -1
- package/batteries/tts/native/adapter.cjs +2 -2
- package/batteries/tts/native/exceptions.cjs +2 -2
- package/batteries/tts/native/helpers.cjs +1 -1
- package/batteries/tts/native/types.cjs +1 -1
- package/batteries/tts/native/validation.cjs +2 -2
- package/batteries/tts/native.cjs +1 -1
- package/batteries/tts/transformers_js/adapter.cjs +3 -3
- package/batteries/tts/transformers_js/exceptions.cjs +2 -2
- package/batteries/tts/transformers_js/types.cjs +1 -1
- package/batteries/tts/transformers_js/validation.cjs +2 -2
- package/batteries/tts/transformers_js.cjs +1 -1
- package/batteries/tts.cjs +1 -1
- package/batteries/validation/exceptions.cjs +2 -2
- package/batteries/validation/types.cjs +1 -1
- package/batteries/validation/validation.cjs +1 -1
- package/batteries/validation.cjs +6 -6
- package/batteries/validation.mjs +4 -4
- package/batteries/vector/arangodb.cjs +2 -2
- package/batteries/vector/builder.cjs +1 -1
- package/batteries/vector/chroma.cjs +2 -2
- package/batteries/vector/chroma.mjs +1 -1
- package/batteries/vector/clickhouse.cjs +3 -3
- package/batteries/vector/clickhouse.mjs +1 -1
- package/batteries/vector/cloudflare.cjs +3 -3
- package/batteries/vector/cloudflare.mjs +1 -1
- package/batteries/vector/conformance.cjs +1 -1
- package/batteries/vector/contract.cjs +1 -1
- package/batteries/vector/couchbase.cjs +3 -3
- package/batteries/vector/couchbase.mjs +1 -1
- package/batteries/vector/duckdb.cjs +3 -3
- package/batteries/vector/duckdb.mjs +1 -1
- package/batteries/vector/elasticsearch.cjs +3 -3
- package/batteries/vector/elasticsearch.mjs +1 -1
- package/batteries/vector/exceptions.cjs +2 -2
- package/batteries/vector/factory.cjs +1 -1
- package/batteries/vector/filters.cjs +2 -2
- package/batteries/vector/helpers.cjs +1 -1
- package/batteries/vector/hnswlib.cjs +3 -3
- package/batteries/vector/hnswlib.mjs +1 -1
- package/batteries/vector/in_memory.cjs +2 -2
- package/batteries/vector/in_memory.mjs +1 -1
- package/batteries/vector/lancedb.cjs +3 -3
- package/batteries/vector/lancedb.mjs +1 -1
- package/batteries/vector/mariadb.cjs +3 -3
- package/batteries/vector/mariadb.mjs +1 -1
- package/batteries/vector/meilisearch.cjs +2 -2
- package/batteries/vector/migrate.cjs +2 -2
- package/batteries/vector/milvus.cjs +2 -2
- package/batteries/vector/milvus.mjs +1 -1
- package/batteries/vector/mongodb.cjs +2 -2
- package/batteries/vector/neo4j.cjs +2 -2
- package/batteries/vector/opensearch.cjs +3 -3
- package/batteries/vector/opensearch.mjs +1 -1
- package/batteries/vector/oracle23ai.cjs +3 -3
- package/batteries/vector/oracle23ai.mjs +1 -1
- package/batteries/vector/orama.cjs +2 -2
- package/batteries/vector/orama.mjs +1 -1
- package/batteries/vector/pgvector.cjs +2 -2
- package/batteries/vector/pgvector.mjs +1 -1
- package/batteries/vector/pinecone.cjs +3 -3
- package/batteries/vector/pinecone.mjs +1 -1
- package/batteries/vector/plan.cjs +1 -1
- package/batteries/vector/qdrant.cjs +2 -2
- package/batteries/vector/qdrant.mjs +1 -1
- package/batteries/vector/redis.cjs +3 -3
- package/batteries/vector/redis.mjs +1 -1
- package/batteries/vector/retrievable.cjs +2 -2
- package/batteries/vector/retrievable.mjs +1 -1
- package/batteries/vector/s3vectors.cjs +3 -3
- package/batteries/vector/s3vectors.mjs +1 -1
- package/batteries/vector/schema.cjs +1 -1
- package/batteries/vector/solr.cjs +2 -2
- package/batteries/vector/sqlite_vec.cjs +2 -2
- package/batteries/vector/sqlite_vec.mjs +1 -1
- package/batteries/vector/surrealdb.cjs +2 -2
- package/batteries/vector/types.cjs +1 -1
- package/batteries/vector/typesense.cjs +3 -3
- package/batteries/vector/typesense.mjs +1 -1
- package/batteries/vector/validation.cjs +1 -1
- package/batteries/vector/vector_store_constructor.cjs +1 -1
- package/batteries/vector/vespa.cjs +3 -3
- package/batteries/vector/vespa.mjs +1 -1
- package/batteries/vector/weaviate.cjs +3 -3
- package/batteries/vector/weaviate.mjs +1 -1
- package/batteries/vector.cjs +2 -2
- package/batteries/vector.mjs +1 -1
- package/batteries.cjs +11 -10
- package/batteries.mjs +11 -11
- package/{chat_common-CBqn22t1.js → chat_common-4huaTp6d.cjs} +5 -5
- package/chat_common-4huaTp6d.cjs.map +1 -0
- package/{chat_common-DKw8FDol.mjs → chat_common-D_XGNjcK.mjs} +2 -2
- package/{chat_common-DKw8FDol.mjs.map → chat_common-D_XGNjcK.mjs.map} +1 -1
- package/claude-code-cli-wrapper.cjs +106 -24
- package/claude-code-cli-wrapper.cjs.map +1 -1
- package/claude-code-cli-wrapper.mjs +104 -22
- package/claude-code-cli-wrapper.mjs.map +1 -1
- package/{common-0rLuBEeY.js → common-BiRzOsxe.cjs} +9 -9
- package/common-BiRzOsxe.cjs.map +1 -0
- package/{common-BuVhq_3h.js → common-BuVhq_3h.cjs} +1 -1
- package/common-BuVhq_3h.cjs.map +1 -0
- package/{common-oI1niK9Z.mjs → common-DsLvTGmm.mjs} +7 -7
- package/{common-oI1niK9Z.mjs.map → common-DsLvTGmm.mjs.map} +1 -1
- package/common.cjs +8 -8
- package/common.mjs +7 -7
- package/{conformance-T1qEg8Sv.js → conformance-T1qEg8Sv.cjs} +1 -1
- package/conformance-T1qEg8Sv.cjs.map +1 -0
- package/{dispatch_runner-CKhm-scw.js → dispatch_runner-C5S3KCqH.cjs} +6 -6
- package/dispatch_runner-C5S3KCqH.cjs.map +1 -0
- package/{dispatch_runner-BZDXUe0G.mjs → dispatch_runner-DDH_dGPU.mjs} +4 -4
- package/{dispatch_runner-BZDXUe0G.mjs.map → dispatch_runner-DDH_dGPU.mjs.map} +1 -1
- package/dispatch_runner.cjs +2 -2
- package/dispatch_runner.mjs +1 -1
- package/{ecmascript-DmrNI2Wo.js → ecmascript-BGr_0Dwn.cjs} +6 -6
- package/ecmascript-BGr_0Dwn.cjs.map +1 -0
- package/{ecmascript-B9Z2C24U.mjs → ecmascript-CWLZ7bCX.mjs} +5 -5
- package/{ecmascript-B9Z2C24U.mjs.map → ecmascript-CWLZ7bCX.mjs.map} +1 -1
- package/{error_translation-BCa4wxUL.js → error_translation-D8Ea1_th.cjs} +2 -2
- package/error_translation-D8Ea1_th.cjs.map +1 -0
- package/{escape-COeB923i.js → escape-C12OWStb.cjs} +3 -3
- package/escape-C12OWStb.cjs.map +1 -0
- package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs +2 -2
- package/eslint/rules/no_model_in_tool_handler.cjs +2 -2
- package/eslint/rules/require_string_empty_disposition.cjs +2 -2
- package/eslint/rules/require_validator_any_required.cjs +2 -2
- package/eslint/rules/thought_payload_requires_replay_tag.cjs +2 -2
- package/eslint/rules/token_encoding_requires_context_window.cjs +2 -2
- package/eslint/rules.cjs +1 -1
- package/eslint.cjs +3 -3
- package/eslint.mjs +2 -2
- package/{exceptions-Dlw1Jr6E.js → exceptions-Bc1s_ld5.cjs} +2 -2
- package/exceptions-Bc1s_ld5.cjs.map +1 -0
- package/{exceptions-BY1RQNVP.js → exceptions-BwGzlXoz.cjs} +2 -2
- package/exceptions-BwGzlXoz.cjs.map +1 -0
- package/{exceptions-DrHnAGQz.js → exceptions-DrHnAGQz.cjs} +1 -1
- package/exceptions-DrHnAGQz.cjs.map +1 -0
- package/exceptions.cjs +3 -3
- package/exceptions.mjs +1 -1
- package/factories.cjs +2 -2
- package/forge.cjs +3 -3
- package/forge.mjs +2 -2
- package/{formats-DZVuqZUN.js → formats-DZVuqZUN.cjs} +1 -1
- package/formats-DZVuqZUN.cjs.map +1 -0
- package/{fs_node-WwUEiuo6.js → fs_node-XvgZtNJV.cjs} +2 -2
- package/fs_node-XvgZtNJV.cjs.map +1 -0
- package/{function_serializer-ChL2I8Kq.js → function_serializer-D1Kyicai.cjs} +3 -3
- package/function_serializer-D1Kyicai.cjs.map +1 -0
- package/{gpu_budget-BBIUyLoj.js → gpu_budget-BBIUyLoj.cjs} +1 -1
- package/gpu_budget-BBIUyLoj.cjs.map +1 -0
- package/{guards-05Uq3J4M.js → guards-5-XmJgD2.cjs} +2 -2
- package/guards-5-XmJgD2.cjs.map +1 -0
- package/guards.cjs +10 -10
- package/guards.mjs +7 -7
- package/{helpers-CObtMmAZ.js → helpers-BPi_iwxv.cjs} +4 -4
- package/helpers-BPi_iwxv.cjs.map +1 -0
- package/{helpers-mbn_EsDV.mjs → helpers-D47G8WQb.mjs} +3 -3
- package/{helpers-mbn_EsDV.mjs.map → helpers-D47G8WQb.mjs.map} +1 -1
- package/index.cjs +13 -13
- package/index.mjs +10 -10
- package/{isolation-7Jrcucgc.js → isolation-B2FgKbap.cjs} +5 -5
- package/isolation-B2FgKbap.cjs.map +1 -0
- package/{isolation-CO0NiK8R.mjs → isolation-BRGpiU-K.mjs} +2 -2
- package/{isolation-CO0NiK8R.mjs.map → isolation-BRGpiU-K.mjs.map} +1 -1
- package/lib/helpers/bignum.cjs +1 -1
- package/lib/utils/audio.cjs +1 -1
- package/lib/utils/retry.cjs +1 -1
- package/{lifecycle-vYQJ2rmf.js → lifecycle-vYQJ2rmf.cjs} +1 -1
- package/lifecycle-vYQJ2rmf.cjs.map +1 -0
- package/{manifest-D8UTRohY.mjs → manifest-B5bWMHgj.mjs} +2 -2
- package/{manifest-D8UTRohY.mjs.map → manifest-B5bWMHgj.mjs.map} +1 -1
- package/{manifest-iMAmSDay.js → manifest-Chjh-3s1.cjs} +4 -4
- package/manifest-Chjh-3s1.cjs.map +1 -0
- package/mcp/adk-docs-corpus.json +2 -2
- package/package.json +490 -490
- package/{patch-BXX9Q0FM.js → patch-BXX9Q0FM.cjs} +1 -1
- package/patch-BXX9Q0FM.cjs.map +1 -0
- package/{predicates-CM27Z3TF.mjs → predicates-2dZQ82LY.mjs} +2 -2
- package/{predicates-CM27Z3TF.mjs.map → predicates-2dZQ82LY.mjs.map} +1 -1
- package/{predicates-f3wvKYT8.js → predicates-C9jl2QPZ.cjs} +3 -3
- package/predicates-C9jl2QPZ.cjs.map +1 -0
- package/{retrievable-BTwjmPnl.js → retrievable-ReauMJxJ.cjs} +5 -5
- package/retrievable-ReauMJxJ.cjs.map +1 -0
- package/{retrievable-CXTAUuuv.mjs → retrievable-mFgC1aty.mjs} +3 -3
- package/{retrievable-CXTAUuuv.mjs.map → retrievable-mFgC1aty.mjs.map} +1 -1
- package/{sandbox-utils-DLCceTeU.js → sandbox-utils-D12AZhWE.cjs} +2 -2
- package/sandbox-utils-D12AZhWE.cjs.map +1 -0
- package/{scrapper-CJexXXK-.js → scrapper-BsEY0Wo6.cjs} +7 -7
- package/scrapper-BsEY0Wo6.cjs.map +1 -0
- package/{scrapper-DiQ5FfDL.mjs → scrapper-bShwZxKP.mjs} +5 -5
- package/{scrapper-DiQ5FfDL.mjs.map → scrapper-bShwZxKP.mjs.map} +1 -1
- package/{searxng-BFTJ6rTE.mjs → searxng-CAY-bOMl.mjs} +5 -5
- package/{searxng-BFTJ6rTE.mjs.map → searxng-CAY-bOMl.mjs.map} +1 -1
- package/{searxng-DzlGZG4V.js → searxng-CLF0vBMT.cjs} +7 -7
- package/searxng-CLF0vBMT.cjs.map +1 -0
- package/{server-CnUZcn6e.js → server-CkVjzQaC.cjs} +2 -2
- package/server-CkVjzQaC.cjs.map +1 -0
- package/server.json +2 -2
- package/{shell-quote-CIuPmePF.js → shell-quote-BUxBTn3M.cjs} +2 -2
- package/shell-quote-BUxBTn3M.cjs.map +1 -0
- package/shims.cjs +2 -2
- package/skills/adk-assembly/SKILL.md +2 -2
- package/{spooled_artifact-Bw_7swIp.mjs → spooled_artifact-B710Rb0d.mjs} +731 -731
- package/spooled_artifact-B710Rb0d.mjs.map +1 -0
- package/{spooled_artifact-BpcesRBv.js → spooled_artifact-CFjf6ULg.cjs} +733 -733
- package/spooled_artifact-CFjf6ULg.cjs.map +1 -0
- package/spooled_artifact.cjs +3 -3
- package/spooled_artifact.mjs +2 -2
- package/{spooled_markdown_artifact-vd6eNtIP.mjs → spooled_markdown_artifact-1C4mmi73.mjs} +3 -3
- package/{spooled_markdown_artifact-vd6eNtIP.mjs.map → spooled_markdown_artifact-1C4mmi73.mjs.map} +1 -1
- package/{spooled_markdown_artifact-wJPnE8Ij.js → spooled_markdown_artifact-PWppwnPQ.cjs} +5 -5
- package/spooled_markdown_artifact-PWppwnPQ.cjs.map +1 -0
- package/{thought-CxSaF6Xf.mjs → thought-BKXwUZoq.mjs} +3 -3
- package/{thought-CxSaF6Xf.mjs.map → thought-BKXwUZoq.mjs.map} +1 -1
- package/{thought-Dg_4UZxg.js → thought-D5fJsxBW.cjs} +5 -5
- package/thought-D5fJsxBW.cjs.map +1 -0
- package/{tokenizable-BMZuGWRd.js → tokenizable-DDIdXbJN.cjs} +31 -31
- package/tokenizable-DDIdXbJN.cjs.map +1 -0
- package/{tokenizable-VB4Av8GF.mjs → tokenizable-xPXj1AQX.mjs} +30 -30
- package/{tokenizable-VB4Av8GF.mjs.map → tokenizable-xPXj1AQX.mjs.map} +1 -1
- package/{tool_call-Fs_Uh5wQ.js → tool_call-CDV5pW13.cjs} +5 -5
- package/tool_call-CDV5pW13.cjs.map +1 -0
- package/{tool_call-Cfaj-6zK.mjs → tool_call-D-LqMvpU.mjs} +3 -3
- package/{tool_call-Cfaj-6zK.mjs.map → tool_call-D-LqMvpU.mjs.map} +1 -1
- package/{tool_parsers-csSBFWob.js → tool_parsers-8_qO0a_F.cjs} +2 -2
- package/tool_parsers-8_qO0a_F.cjs.map +1 -0
- package/{tools-rJvfktHR.js → tools-CACuuMV4.cjs} +9 -9
- package/tools-CACuuMV4.cjs.map +1 -0
- package/{tools-D0MBDh2R.mjs → tools-CvCMdAd7.mjs} +6 -6
- package/{tools-D0MBDh2R.mjs.map → tools-CvCMdAd7.mjs.map} +1 -1
- package/{toon-BXPdJRz7.js → toon-B7Q9RWJF.cjs} +7 -7
- package/toon-B7Q9RWJF.cjs.map +1 -0
- package/{toon-BSTQnHed.mjs → toon-CCjuuzd_.mjs} +6 -6
- package/{toon-BSTQnHed.mjs.map → toon-CCjuuzd_.mjs.map} +1 -1
- package/{transformers_js-p3lAkHFH.mjs → transformers_js-BR2Ov0Su.mjs} +2 -2
- package/{transformers_js-p3lAkHFH.mjs.map → transformers_js-BR2Ov0Su.mjs.map} +1 -1
- package/{transformers_js-C050gRfd.js → transformers_js-DM01eAzh.cjs} +4 -4
- package/transformers_js-DM01eAzh.cjs.map +1 -0
- package/{turn_runner-BHHD6h77.mjs → turn_runner-BgPw9uqb.mjs} +4 -4
- package/{turn_runner-BHHD6h77.mjs.map → turn_runner-BgPw9uqb.mjs.map} +1 -1
- package/{turn_runner-DhLI7OTH.js → turn_runner-CP2zxSlu.cjs} +6 -6
- package/turn_runner-CP2zxSlu.cjs.map +1 -0
- package/turn_runner.cjs +2 -2
- package/turn_runner.mjs +1 -1
- package/{type_guards-BAhiOypL-C2eOOyxU.js → type_guards-BAhiOypL-C2eOOyxU.cjs} +1 -1
- package/{type_guards-BAhiOypL-C2eOOyxU.js.map → type_guards-BAhiOypL-C2eOOyxU.cjs.map} +1 -1
- package/{type_guards-DuKwiYgg.js → type_guards-BWTKysPt.cjs} +2 -2
- package/{types-DrSosVaM.js → types-DWOiL208.cjs} +4 -4
- package/types-DWOiL208.cjs.map +1 -0
- package/types.cjs +1 -1
- package/{validate-CkQI-48O.js → validate-tUm9MY8y.cjs} +3 -3
- package/validate-tUm9MY8y.cjs.map +1 -0
- package/{xlsx-B0sTpEC2.js → xlsx-Dtql4S-9.cjs} +2 -2
- package/xlsx-Dtql4S-9.cjs.map +1 -0
- package/{xlsx.zahl-ZIcUQVv8.js → xlsx.zahl-C9pM7cyt.cjs} +2 -2
- package/xlsx.zahl-C9pM7cyt.cjs.map +1 -0
- package/{xml-CYseDztH.mjs → xml-BqTTIFhv.mjs} +6 -6
- package/{xml-CYseDztH.mjs.map → xml-BqTTIFhv.mjs.map} +1 -1
- package/{xml-CNmgj5Qq.js → xml-viE54OTe.cjs} +7 -7
- package/xml-viE54OTe.cjs.map +1 -0
- package/{yaml-BPBoiOjx.mjs → yaml-B1So-pUR.mjs} +6 -6
- package/{yaml-BPBoiOjx.mjs.map → yaml-B1So-pUR.mjs.map} +1 -1
- package/{yaml-CaoIJyRe.js → yaml-cGhhPyZq.cjs} +7 -7
- package/yaml-cGhhPyZq.cjs.map +1 -0
- package/arg_specs-iYmIM3wI.js.map +0 -1
- package/artifact_methods-Cg0go7Q4.mjs +0 -1
- package/artifact_methods-SKgM322C.js +0 -1
- package/chat_common-CBqn22t1.js.map +0 -1
- package/common-0rLuBEeY.js.map +0 -1
- package/common-BuVhq_3h.js.map +0 -1
- package/conformance-T1qEg8Sv.js.map +0 -1
- package/dispatch_runner-CKhm-scw.js.map +0 -1
- package/ecmascript-DmrNI2Wo.js.map +0 -1
- package/error_translation-BCa4wxUL.js.map +0 -1
- package/escape-COeB923i.js.map +0 -1
- package/exceptions-BY1RQNVP.js.map +0 -1
- package/exceptions-Dlw1Jr6E.js.map +0 -1
- package/exceptions-DrHnAGQz.js.map +0 -1
- package/formats-DZVuqZUN.js.map +0 -1
- package/fs_node-WwUEiuo6.js.map +0 -1
- package/function_serializer-ChL2I8Kq.js.map +0 -1
- package/gpu_budget-BBIUyLoj.js.map +0 -1
- package/guards-05Uq3J4M.js.map +0 -1
- package/helpers-CObtMmAZ.js.map +0 -1
- package/isolation-7Jrcucgc.js.map +0 -1
- package/lifecycle-vYQJ2rmf.js.map +0 -1
- package/manifest-iMAmSDay.js.map +0 -1
- package/patch-BXX9Q0FM.js.map +0 -1
- package/predicates-f3wvKYT8.js.map +0 -1
- package/retrievable-BTwjmPnl.js.map +0 -1
- package/sandbox-utils-DLCceTeU.js.map +0 -1
- package/scrapper-CJexXXK-.js.map +0 -1
- package/searxng-DzlGZG4V.js.map +0 -1
- package/server-CnUZcn6e.js.map +0 -1
- package/shell-quote-CIuPmePF.js.map +0 -1
- package/spooled_artifact-BpcesRBv.js.map +0 -1
- package/spooled_artifact-Bw_7swIp.mjs.map +0 -1
- package/spooled_markdown_artifact-wJPnE8Ij.js.map +0 -1
- package/thought-Dg_4UZxg.js.map +0 -1
- package/tokenizable-BMZuGWRd.js.map +0 -1
- package/tool_call-Fs_Uh5wQ.js.map +0 -1
- package/tool_parsers-csSBFWob.js.map +0 -1
- package/tools-rJvfktHR.js.map +0 -1
- package/toon-BXPdJRz7.js.map +0 -1
- package/transformers_js-C050gRfd.js.map +0 -1
- package/turn_runner-DhLI7OTH.js.map +0 -1
- package/types-DrSosVaM.js.map +0 -1
- package/validate-CkQI-48O.js.map +0 -1
- package/xlsx-B0sTpEC2.js.map +0 -1
- package/xlsx.zahl-ZIcUQVv8.js.map +0 -1
- package/xml-CNmgj5Qq.js.map +0 -1
- package/yaml-CaoIJyRe.js.map +0 -1
- /package/{chunk-Cek0wNdY.js → chunk-Cek0wNdY.cjs} +0 -0
|
@@ -1,532 +1,538 @@
|
|
|
1
|
-
const require_chunk = require("./chunk-Cek0wNdY.
|
|
2
|
-
const require_exceptions = require("./exceptions-DrHnAGQz.
|
|
3
|
-
const require_guards = require("./guards-
|
|
4
|
-
const require_tokenizable = require("./tokenizable-
|
|
1
|
+
const require_chunk = require("./chunk-Cek0wNdY.cjs");
|
|
2
|
+
const require_exceptions = require("./exceptions-DrHnAGQz.cjs");
|
|
3
|
+
const require_guards = require("./guards-5-XmJgD2.cjs");
|
|
4
|
+
const require_tokenizable = require("./tokenizable-DDIdXbJN.cjs");
|
|
5
5
|
let _nhtio_validation = require("@nhtio/validation");
|
|
6
|
+
let luxon = require("luxon");
|
|
7
|
+
let js_sha256 = require("js-sha256");
|
|
6
8
|
let dset = require("dset");
|
|
7
9
|
let klona = require("klona");
|
|
8
10
|
let dlv = require("dlv");
|
|
9
11
|
dlv = require_chunk.__toESM(dlv);
|
|
10
|
-
|
|
11
|
-
let js_sha256 = require("js-sha256");
|
|
12
|
-
//#region src/lib/classes/registry.ts
|
|
12
|
+
//#region src/lib/classes/tool_registry.ts
|
|
13
13
|
/**
|
|
14
|
-
* A
|
|
14
|
+
* A mutable, turn-scoped collection of {@link @nhtio/adk!Tool} instances.
|
|
15
15
|
*
|
|
16
16
|
* @remarks
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* Each `TurnRunner.run()` call constructs a fresh `ToolRegistry` from the runner's configured
|
|
18
|
+
* baseline tools, so middleware edits are isolated to the current turn and cannot bleed across
|
|
19
|
+
* concurrent or subsequent turns.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* `Tool` instances are immutable, so `all()` returns a fresh array without deep-cloning.
|
|
22
|
+
*
|
|
23
|
+
* `register()` throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} if a tool with the same name is already
|
|
24
|
+
* present — pass `overwrite: true` to replace it explicitly.
|
|
25
|
+
*
|
|
26
|
+
* Tools can be **hidden** — registered and callable, but excluded from the default tool list
|
|
27
|
+
* rendered to the model. This is useful for discovery patterns where an agent has a tool that
|
|
28
|
+
* enumerates available tools, and the model picks one to call by name in a subsequent iteration.
|
|
29
|
+
* Hidden state is a property of the registry, not the tool: the same tool can be visible in one
|
|
30
|
+
* registry and hidden in another. See {@link hide}, {@link visible}, {@link hidden}.
|
|
23
31
|
*/
|
|
24
|
-
var
|
|
25
|
-
#
|
|
32
|
+
var ToolRegistry = class ToolRegistry {
|
|
33
|
+
#tools;
|
|
34
|
+
#hidden;
|
|
26
35
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
36
|
+
* Returns `true` if `value` is a {@link ToolRegistry} instance.
|
|
37
|
+
*
|
|
38
|
+
* @param value - The value to test.
|
|
39
|
+
* @returns `true` when `value` is a {@link ToolRegistry} instance.
|
|
29
40
|
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
this.#store = initial ? (0, klona.klona)(initial) : {};
|
|
41
|
+
static isToolRegistry(value) {
|
|
42
|
+
return require_guards.isInstanceOf(value, "ToolRegistry", ToolRegistry);
|
|
33
43
|
}
|
|
34
44
|
/**
|
|
35
|
-
*
|
|
45
|
+
* @param tools - Optional initial tools. Insertion order is preserved. Duplicate names throw
|
|
46
|
+
* {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} — ensure each tool has a unique name.
|
|
47
|
+
* @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when two tools in `tools` share a name.
|
|
48
|
+
*/
|
|
49
|
+
constructor(tools) {
|
|
50
|
+
this.#tools = /* @__PURE__ */ new Map();
|
|
51
|
+
this.#hidden = /* @__PURE__ */ new Set();
|
|
52
|
+
for (const tool of tools ?? []) this.register(tool);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Adds a tool to the registry.
|
|
56
|
+
*
|
|
57
|
+
* @param tool - The tool to register.
|
|
58
|
+
* @param overwrite - When `true`, silently replaces an existing tool with the same name.
|
|
59
|
+
* Defaults to `false`.
|
|
60
|
+
* @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when a tool with the same name is already registered
|
|
61
|
+
* and `overwrite` is not `true`.
|
|
62
|
+
*/
|
|
63
|
+
register(tool, overwrite) {
|
|
64
|
+
if (this.#tools.has(tool.name) && !overwrite) throw new require_tokenizable.E_TOOL_ALREADY_REGISTERED();
|
|
65
|
+
this.#tools.set(tool.name, tool);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Removes the tool with the given name from the registry.
|
|
36
69
|
*
|
|
37
70
|
* @remarks
|
|
38
|
-
*
|
|
71
|
+
* Also removes the name from the hidden set if present. No-ops if no tool with that name is
|
|
72
|
+
* registered.
|
|
39
73
|
*
|
|
40
|
-
* @param
|
|
41
|
-
* @returns `true` when `value` is a {@link Registry} instance.
|
|
74
|
+
* @param name - The name of the tool to remove.
|
|
42
75
|
*/
|
|
43
|
-
|
|
44
|
-
|
|
76
|
+
unregister(name) {
|
|
77
|
+
this.#tools.delete(name);
|
|
78
|
+
this.#hidden.delete(name);
|
|
45
79
|
}
|
|
46
80
|
/**
|
|
47
|
-
*
|
|
81
|
+
* Returns the tool registered under `name`, or `undefined` if not present.
|
|
48
82
|
*
|
|
49
|
-
* @
|
|
50
|
-
|
|
83
|
+
* @param name - The tool name to look up.
|
|
84
|
+
*/
|
|
85
|
+
get(name) {
|
|
86
|
+
return this.#tools.get(name);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Returns `true` if a tool with the given name is registered.
|
|
51
90
|
*
|
|
52
|
-
* @
|
|
53
|
-
* @param key - Dot-delimited path into the store (e.g. `"user.name"`).
|
|
54
|
-
* @param defaultValue - Fallback returned when the path resolves to `undefined`.
|
|
55
|
-
* @returns A deep clone of the stored value cast to `T`, or `defaultValue` when the path is absent.
|
|
91
|
+
* @param name - The tool name to test.
|
|
56
92
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return "undefined" === typeof value ? defaultValue : value;
|
|
93
|
+
has(name) {
|
|
94
|
+
return this.#tools.has(name);
|
|
60
95
|
}
|
|
61
96
|
/**
|
|
62
|
-
*
|
|
97
|
+
* Returns a fresh array of all registered tools in insertion order.
|
|
63
98
|
*
|
|
64
99
|
* @remarks
|
|
65
|
-
*
|
|
66
|
-
*
|
|
100
|
+
* Includes both visible and hidden tools. Use {@link visible} to get only non-hidden tools, or
|
|
101
|
+
* {@link hidden} to get only hidden tools.
|
|
67
102
|
*
|
|
68
|
-
* @
|
|
69
|
-
* @param value - Value to store at the path.
|
|
103
|
+
* Since {@link @nhtio/adk!Tool} instances are immutable, no deep-cloning is needed.
|
|
70
104
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
105
|
+
all() {
|
|
106
|
+
return Array.from(this.#tools.values());
|
|
73
107
|
}
|
|
74
108
|
/**
|
|
75
|
-
* Returns
|
|
109
|
+
* Returns a fresh array of registered tools that are **not** hidden, in insertion order.
|
|
76
110
|
*
|
|
77
111
|
* @remarks
|
|
78
|
-
*
|
|
79
|
-
*
|
|
112
|
+
* This is the accessor LLM batteries should use when building the tool list for the model.
|
|
113
|
+
* Hidden tools are still callable (they resolve via {@link get}) but are excluded from the
|
|
114
|
+
* rendered tool definitions.
|
|
115
|
+
*/
|
|
116
|
+
visible() {
|
|
117
|
+
return this.all().filter((t) => !this.#hidden.has(t.name));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Returns a fresh array of registered tools that **are** hidden, in insertion order.
|
|
80
121
|
*
|
|
81
|
-
* @
|
|
82
|
-
*
|
|
122
|
+
* @remarks
|
|
123
|
+
* The converse of {@link visible}. Useful for discovery tools that enumerate all available
|
|
124
|
+
* tools, and for propagating hidden state across {@link merge}.
|
|
83
125
|
*/
|
|
84
|
-
|
|
85
|
-
return
|
|
126
|
+
hidden() {
|
|
127
|
+
return this.all().filter((t) => this.#hidden.has(t.name));
|
|
86
128
|
}
|
|
87
129
|
/**
|
|
88
|
-
*
|
|
130
|
+
* Marks one or more registered tools as hidden.
|
|
89
131
|
*
|
|
90
132
|
* @remarks
|
|
91
|
-
*
|
|
92
|
-
*
|
|
133
|
+
* Hidden tools remain registered and callable via {@link get}, but are excluded from
|
|
134
|
+
* {@link visible} (and therefore from the LLM tool list). No-ops for any name that is not
|
|
135
|
+
* currently registered — the end result (the tool is not visible) matches the intent.
|
|
93
136
|
*
|
|
94
|
-
* @
|
|
137
|
+
* @param names - One or more tool names to hide.
|
|
95
138
|
*/
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
const keys = [];
|
|
99
|
-
const isPlainRecord = (value) => {
|
|
100
|
-
if (!require_guards.isObject(value)) return false;
|
|
101
|
-
const prototype = Object.getPrototypeOf(value);
|
|
102
|
-
return prototype === Object.prototype || prototype === null;
|
|
103
|
-
};
|
|
104
|
-
const walk = (value, segments) => {
|
|
105
|
-
if (!isPlainRecord(value)) {
|
|
106
|
-
if (segments.length > 0) keys.push(segments.join("."));
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
for (const [segment, child] of Object.entries(value)) walk(child, [...segments, segment]);
|
|
110
|
-
};
|
|
111
|
-
walk(store, []);
|
|
112
|
-
return keys;
|
|
139
|
+
hide(...names) {
|
|
140
|
+
for (const name of names) this.#hidden.add(name);
|
|
113
141
|
}
|
|
114
142
|
/**
|
|
115
|
-
*
|
|
143
|
+
* Unmarks one or more tools as hidden, making them visible again.
|
|
116
144
|
*
|
|
117
|
-
* @
|
|
145
|
+
* @remarks
|
|
146
|
+
* No-ops for any name that is not currently hidden.
|
|
147
|
+
*
|
|
148
|
+
* @param names - One or more tool names to unhide.
|
|
118
149
|
*/
|
|
119
|
-
|
|
120
|
-
|
|
150
|
+
unhide(...names) {
|
|
151
|
+
for (const name of names) this.#hidden.delete(name);
|
|
121
152
|
}
|
|
122
153
|
/**
|
|
123
|
-
*
|
|
154
|
+
* Replaces the entire hidden set with the given tool names.
|
|
124
155
|
*
|
|
125
156
|
* @remarks
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
157
|
+
* Any previously hidden tool not in `names` becomes visible. Names that are not registered are
|
|
158
|
+
* silently ignored — they are added to the set but have no effect until a tool with that name
|
|
159
|
+
* is registered.
|
|
129
160
|
*
|
|
130
|
-
* @
|
|
161
|
+
* @param names - The complete set of tool names to hide.
|
|
131
162
|
*/
|
|
132
|
-
|
|
133
|
-
|
|
163
|
+
setHidden(...names) {
|
|
164
|
+
this.#hidden = new Set(names);
|
|
134
165
|
}
|
|
135
166
|
/**
|
|
136
|
-
*
|
|
167
|
+
* Unhides every tool in the registry.
|
|
168
|
+
*/
|
|
169
|
+
clearHidden() {
|
|
170
|
+
this.#hidden.clear();
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Removes every tool whose {@link @nhtio/adk!Tool.ephemeral} flag is `true`.
|
|
137
174
|
*
|
|
138
|
-
* @
|
|
139
|
-
*
|
|
175
|
+
* @remarks
|
|
176
|
+
* Also removes pruned tool names from the hidden set. Synchronous and idempotent — calling it
|
|
177
|
+
* twice in a row is a no-op the second time. The canonical caller is
|
|
178
|
+
* {@link ToolRegistry.bindContext}, which schedules this method to run at
|
|
179
|
+
* {@link @nhtio/adk!DispatchContext.ack}. Non-ephemeral tools are left untouched.
|
|
140
180
|
*/
|
|
141
|
-
|
|
142
|
-
|
|
181
|
+
pruneEphemeral() {
|
|
182
|
+
for (const [name, tool] of this.#tools) if (tool.ephemeral) {
|
|
183
|
+
this.#tools.delete(name);
|
|
184
|
+
this.#hidden.delete(name);
|
|
185
|
+
}
|
|
143
186
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
* @
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
187
|
+
/**
|
|
188
|
+
* Binds this registry to a {@link @nhtio/adk!DispatchContext} so that {@link pruneEphemeral} runs
|
|
189
|
+
* automatically when the context is acked.
|
|
190
|
+
*
|
|
191
|
+
* @remarks
|
|
192
|
+
* The handler does NOT fire on {@link @nhtio/adk!DispatchContext.nack} — failed executor runs leave
|
|
193
|
+
* any forged tools in place so the consumer can inspect what was registered when debugging the
|
|
194
|
+
* failure. Subscriptions are short-lived and die with the context regardless.
|
|
195
|
+
*
|
|
196
|
+
* ARTIFACT READERS ARE FORGED BY THE CORE. As of the core-forge change, the `DispatchRunner` forges
|
|
197
|
+
* artifact-reader tools from prior-turn `SpooledArtifact` results into `ctx.tools` (and calls
|
|
198
|
+
* `ctx.tools.bindContext(ctx)`) once per iteration, BEFORE the input pipeline — so a battery executor no
|
|
199
|
+
* longer forges or binds; it reads the already-forged `ctx.tools` for both representation (rendering the
|
|
200
|
+
* tool declarations) and resolution (looking up an incoming call by name). The lifecycle is unchanged:
|
|
201
|
+
* ephemeral readers are still pruned on `ack`, and the core re-forges each iteration (prune-then-forge) so
|
|
202
|
+
* the `callId` enum never goes stale.
|
|
203
|
+
*
|
|
204
|
+
* `bindContext` remains the public seam for a CUSTOM consumer that forges its own ephemeral tools outside
|
|
205
|
+
* the core path. If you forge into a long-lived registry yourself, bind it (or prune manually) or the
|
|
206
|
+
* ephemeral tools accumulate and later `forgeTools(ctx)` calls see a stale `callId` enum. The pattern for a
|
|
207
|
+
* hand-rolled forge is:
|
|
208
|
+
*
|
|
209
|
+
* ```ts
|
|
210
|
+
* // Custom forge (the core already does this for artifact readers on ctx.tools):
|
|
211
|
+
* const forged = SpooledArtifact.forgeTools(ctx)
|
|
212
|
+
* for (const tool of forged.all()) ctx.tools.register(tool, true)
|
|
213
|
+
* ctx.tools.bindContext(ctx) // prune the ephemeral readers when the dispatch acks
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* @param ctx - The execution context whose `ack` event should trigger pruning.
|
|
217
|
+
* @returns An unsubscribe function — calling it before `ctx.ack()` prevents pruning. Rarely
|
|
218
|
+
* useful outside of tests.
|
|
219
|
+
*
|
|
220
|
+
* @see {@link @nhtio/adk!SpooledArtifact.forgeTools}
|
|
221
|
+
* @see {@link @nhtio/adk!DispatchContext.onAck}
|
|
222
|
+
*/
|
|
223
|
+
bindContext(ctx) {
|
|
224
|
+
return ctx.onAck(() => this.pruneEphemeral());
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Combines multiple {@link ToolRegistry} instances into a fresh registry without mutating any
|
|
228
|
+
* input.
|
|
229
|
+
*
|
|
230
|
+
* @remarks
|
|
231
|
+
* Iteration is left-to-right across `registries` and then in each registry's insertion order.
|
|
232
|
+
* Collisions are resolved by consulting the **incoming** tool's {@link @nhtio/adk!Tool.onCollision} first:
|
|
233
|
+
*
|
|
234
|
+
* - `'replace'` (per-tool): the incoming tool wins, replacing the existing entry.
|
|
235
|
+
* - `'keep'` (per-tool): the existing entry wins; the incoming tool is dropped.
|
|
236
|
+
* - `'throw'` (per-tool, the default): fall back to the merge-level `options.onCollision`.
|
|
237
|
+
*
|
|
238
|
+
* The merge-level `options.onCollision` defaults to `'throw'`, which mirrors {@link register}.
|
|
239
|
+
*
|
|
240
|
+
* The result is a brand-new registry; no input is mutated and no event subscription is
|
|
241
|
+
* propagated. Each `Tool`'s `ephemeral` flag carries through unchanged — the flag lives on the
|
|
242
|
+
* tool, not the registry, so `bindContext(ctx)` on the merged registry will prune the forged
|
|
243
|
+
* tools as expected.
|
|
244
|
+
*
|
|
245
|
+
* Hidden state is also propagated: a tool that is hidden in any source registry remains hidden
|
|
246
|
+
* in the merged result, provided it survives collision resolution.
|
|
247
|
+
*
|
|
248
|
+
* @param registries - Registries to merge, in priority order (left-to-right insertion).
|
|
249
|
+
* @param options - Merge-level collision policy. Defaults to `{ onCollision: 'throw' }`.
|
|
250
|
+
* @returns A fresh {@link ToolRegistry} containing the resolved union of all inputs.
|
|
251
|
+
* @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when the resolved collision policy is `'throw'`
|
|
252
|
+
* and a collision occurs.
|
|
253
|
+
*/
|
|
254
|
+
static merge(registries, options) {
|
|
255
|
+
const policy = options?.onCollision ?? "throw";
|
|
256
|
+
const merged = new ToolRegistry();
|
|
257
|
+
for (const registry of registries) {
|
|
258
|
+
for (const tool of registry.all()) {
|
|
259
|
+
if (!merged.get(tool.name)) {
|
|
260
|
+
merged.register(tool);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const incomingPolicy = tool.onCollision;
|
|
264
|
+
if (incomingPolicy === "replace") {
|
|
265
|
+
merged.register(tool, true);
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (incomingPolicy === "keep") continue;
|
|
269
|
+
if (policy === "replace") {
|
|
270
|
+
merged.register(tool, true);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (policy === "keep") continue;
|
|
274
|
+
throw new require_tokenizable.E_TOOL_ALREADY_REGISTERED();
|
|
275
|
+
}
|
|
276
|
+
for (const tool of registry.hidden()) if (merged.has(tool.name)) merged.hide(tool.name);
|
|
277
|
+
}
|
|
278
|
+
return merged;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Serialise this ToolRegistry into an `@nhtio/encoder` snapshot.
|
|
282
|
+
*
|
|
283
|
+
* @remarks
|
|
284
|
+
* Emits the live {@link @nhtio/adk!Tool} instances (the encoder recurses into each — so every tool's
|
|
285
|
+
* handler-closure caveat from {@link Tool.[ENCODE_METHOD]} applies) plus the hidden-set names. Both
|
|
286
|
+
* {@link @nhtio/adk!Tool} and {@link @nhtio/adk!ArtifactTool} entries round-trip to their correct
|
|
287
|
+
* subtype. Round-trips via {@link ToolRegistry.[DECODE_METHOD]}.
|
|
288
|
+
*
|
|
289
|
+
* @returns A `{ tools, hidden }` snapshot.
|
|
290
|
+
*/
|
|
291
|
+
[require_tokenizable.ENCODE_METHOD]() {
|
|
292
|
+
return {
|
|
293
|
+
tools: this.all(),
|
|
294
|
+
hidden: this.hidden().map((tool) => tool.name)
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Reconstruct a {@link ToolRegistry} from a {@link ToolRegistry.[ENCODE_METHOD]} snapshot.
|
|
299
|
+
*
|
|
300
|
+
* @param data - The snapshot produced by {@link ToolRegistry.[ENCODE_METHOD]}.
|
|
301
|
+
* @returns A fresh {@link ToolRegistry} with the same tools and hidden set.
|
|
302
|
+
*/
|
|
303
|
+
static [require_tokenizable.DECODE_METHOD](data) {
|
|
304
|
+
const snapshot = data;
|
|
305
|
+
const registry = new ToolRegistry(snapshot.tools);
|
|
306
|
+
registry.setHidden(...snapshot.hidden);
|
|
307
|
+
return registry;
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
//#endregion
|
|
311
|
+
//#region src/lib/utils/canonical_json.ts
|
|
199
312
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
313
|
+
* Canonical `JSON.stringify` that sorts object keys recursively so that semantically-equal
|
|
314
|
+
* objects produce identical strings.
|
|
202
315
|
*
|
|
203
316
|
* @remarks
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
317
|
+
* Used wherever the ADK derives a stable identity from a structured value — for example,
|
|
318
|
+
* `Tool.executor` computing the `callId` for `ToolExecutionStart`/`End` events, and the
|
|
319
|
+
* `reportToolCall` executor helper computing the `checksum` field on `TurnToolCallContent`.
|
|
320
|
+
* Both code paths hash `canonicalStringify({ tool, args })` so that argument key order does not
|
|
321
|
+
* affect the resulting identifier.
|
|
207
322
|
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*/
|
|
211
|
-
var implementsSpooledArtifactConstructor = (value) => {
|
|
212
|
-
return require_exceptions.passesSchema(spooledArtifactConstructorSchema, value);
|
|
213
|
-
};
|
|
214
|
-
/**
|
|
215
|
-
* Creates the validator fragment for a resolver returning a spooled-artifact constructor.
|
|
323
|
+
* Arrays are serialised in their declared order (order is meaningful for an array). Object keys
|
|
324
|
+
* are sorted with `Array.prototype.sort()`'s default lexicographic comparator.
|
|
216
325
|
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
* share exactly the same validation behaviour.
|
|
326
|
+
* @param value - The value to serialise.
|
|
327
|
+
* @returns A canonical JSON string representation of `value`.
|
|
220
328
|
*/
|
|
221
|
-
|
|
222
|
-
if (typeof value !== "
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
return helpers.error("any.invalid");
|
|
228
|
-
}
|
|
229
|
-
return implementsSpooledArtifactConstructor(resolved) ? value : helpers.error("any.invalid");
|
|
230
|
-
});
|
|
329
|
+
function canonicalStringify(value) {
|
|
330
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
331
|
+
if (Array.isArray(value)) return "[" + value.map((v) => canonicalStringify(v)).join(",") + "]";
|
|
332
|
+
const obj = value;
|
|
333
|
+
return "{" + Object.keys(obj).sort().map((k) => JSON.stringify(k) + ":" + canonicalStringify(obj[k])).join(",") + "}";
|
|
334
|
+
}
|
|
231
335
|
//#endregion
|
|
232
|
-
//#region src/lib/classes/
|
|
233
|
-
/**
|
|
234
|
-
* Validator schema for a {@link RawTool}.
|
|
235
|
-
*/
|
|
236
|
-
var rawToolSchema = _nhtio_validation.validator.object({
|
|
237
|
-
name: _nhtio_validation.validator.string().required(),
|
|
238
|
-
description: _nhtio_validation.validator.string().required(),
|
|
239
|
-
inputSchema: _nhtio_validation.validator.any().custom((value, helpers) => {
|
|
240
|
-
if (_nhtio_validation.validator.isSchema(value) && value.type === "object") return value;
|
|
241
|
-
return helpers.error("any.invalid");
|
|
242
|
-
}).required(),
|
|
243
|
-
handler: _nhtio_validation.validator.function().required(),
|
|
244
|
-
artifactConstructor: artifactConstructorResolverSchema().optional(),
|
|
245
|
-
meta: _nhtio_validation.validator.object().pattern(_nhtio_validation.validator.string(), _nhtio_validation.validator.any()).default({}),
|
|
246
|
-
ephemeral: _nhtio_validation.validator.boolean().default(false),
|
|
247
|
-
trusted: _nhtio_validation.validator.boolean().default(false),
|
|
248
|
-
onCollision: _nhtio_validation.validator.string().valid("throw", "replace", "keep").default("throw")
|
|
249
|
-
});
|
|
336
|
+
//#region src/lib/classes/registry.ts
|
|
250
337
|
/**
|
|
251
|
-
* A
|
|
252
|
-
* description, input schema, execution handler, and the {@link @nhtio/adk!SpooledArtifact} subclass that
|
|
253
|
-
* wraps its serialised output.
|
|
254
|
-
*
|
|
255
|
-
* @typeParam A - The {@link @nhtio/adk!SpooledArtifact} subtype this tool's results should be wrapped in.
|
|
256
|
-
* Defaults to {@link @nhtio/adk!SpooledArtifact}.
|
|
338
|
+
* A controlled-mutation key-value store with dot-path access and deep-clone isolation.
|
|
257
339
|
*
|
|
258
340
|
* @remarks
|
|
259
|
-
* The
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
* `.description()`, `.note()`, `.example()` etc. once, and that information is available in both
|
|
263
|
-
* contexts without duplication.
|
|
264
|
-
*
|
|
265
|
-
* The handler is private — invoke it only through `executor(ctx)` which validates args, fires
|
|
266
|
-
* observability events (with a stable `callId` derived from the tool name and arguments), and
|
|
267
|
-
* wraps handler errors in {@link @nhtio/adk!E_TOOL_DOWNSTREAM_ERROR}. The handler returns serialised bytes
|
|
268
|
-
* (`string | Uint8Array`); persistence is the consumer's responsibility.
|
|
341
|
+
* The registry enforces a safe read/write contract: callers never hold a live reference into
|
|
342
|
+
* the internal store. Every value that enters (`set`) or leaves (`get`, `all`) is deep-cloned
|
|
343
|
+
* via `klona`, so mutations to a retrieved value cannot affect stored state and vice versa.
|
|
269
344
|
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* on the tool instance; the consumer reads it when assembling persisted records.
|
|
345
|
+
* Keys are dot-delimited paths (e.g. `"user.profile.name"`), resolved via `dlv` for reads and
|
|
346
|
+
* `dset` for writes; intermediate objects are created automatically on write.
|
|
273
347
|
*/
|
|
274
|
-
var
|
|
348
|
+
var Registry = class Registry {
|
|
349
|
+
#store;
|
|
275
350
|
/**
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
* @remarks
|
|
279
|
-
* Reusable fragment for any schema that needs to validate or nest a tool entry
|
|
280
|
-
* (e.g. `TurnRunnerConfig.tools`).
|
|
351
|
+
* @param initial - Optional plain object to seed the registry. Deep-cloned on construction.
|
|
352
|
+
* @throws {@link @nhtio/adk!E_INVALID_INITIAL_REGISTRY_VALUE} when `initial` is defined but not a plain object.
|
|
281
353
|
*/
|
|
282
|
-
|
|
354
|
+
constructor(initial) {
|
|
355
|
+
if ("undefined" !== typeof initial && !require_guards.isObject(initial)) throw new require_tokenizable.E_INVALID_INITIAL_REGISTRY_VALUE();
|
|
356
|
+
this.#store = initial ? (0, klona.klona)(initial) : {};
|
|
357
|
+
}
|
|
283
358
|
/**
|
|
284
|
-
* Returns `true` if `value` is a {@link
|
|
359
|
+
* Returns `true` if `value` is a {@link Registry} instance.
|
|
360
|
+
*
|
|
361
|
+
* @remarks
|
|
362
|
+
* Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety.
|
|
285
363
|
*
|
|
286
364
|
* @param value - The value to test.
|
|
287
|
-
* @returns `true` when `value` is a {@link
|
|
365
|
+
* @returns `true` when `value` is a {@link Registry} instance.
|
|
288
366
|
*/
|
|
289
|
-
static
|
|
290
|
-
return require_guards.isInstanceOf(value, "
|
|
367
|
+
static isRegistry(value) {
|
|
368
|
+
return require_guards.isInstanceOf(value, "Registry", Registry);
|
|
291
369
|
}
|
|
292
|
-
#name;
|
|
293
|
-
#description;
|
|
294
|
-
#inputSchema;
|
|
295
|
-
#handler;
|
|
296
|
-
#artifactConstructor;
|
|
297
|
-
#meta;
|
|
298
|
-
#ephemeral;
|
|
299
|
-
#trusted;
|
|
300
|
-
#onCollision;
|
|
301
370
|
/**
|
|
302
|
-
*
|
|
303
|
-
*
|
|
371
|
+
* Retrieves the value at `key`, returning `defaultValue` if the path is absent.
|
|
372
|
+
*
|
|
373
|
+
* @remarks
|
|
374
|
+
* The returned value is a deep clone — mutating it will not affect the stored state.
|
|
375
|
+
*
|
|
376
|
+
* @typeParam T - Expected type of the value at `key`.
|
|
377
|
+
* @param key - Dot-delimited path into the store (e.g. `"user.name"`).
|
|
378
|
+
* @param defaultValue - Fallback returned when the path resolves to `undefined`.
|
|
379
|
+
* @returns A deep clone of the stored value cast to `T`, or `defaultValue` when the path is absent.
|
|
304
380
|
*/
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
resolved = require_exceptions.validateOrThrow(rawToolSchema, raw, true);
|
|
309
|
-
} catch (err) {
|
|
310
|
-
throw new require_tokenizable.E_INVALID_INITIAL_TOOL_VALUE({ cause: require_guards.isError(err) ? err : void 0 });
|
|
311
|
-
}
|
|
312
|
-
this.#name = resolved.name;
|
|
313
|
-
this.#description = resolved.description;
|
|
314
|
-
this.#inputSchema = resolved.inputSchema;
|
|
315
|
-
this.#handler = resolved.handler;
|
|
316
|
-
this.#artifactConstructor = resolved.artifactConstructor;
|
|
317
|
-
this.#meta = new Registry(resolved.meta);
|
|
318
|
-
this.#ephemeral = resolved.ephemeral;
|
|
319
|
-
this.#trusted = resolved.trusted;
|
|
320
|
-
this.#onCollision = resolved.onCollision;
|
|
321
|
-
Object.defineProperties(this, {
|
|
322
|
-
name: {
|
|
323
|
-
get: () => this.#name,
|
|
324
|
-
enumerable: true,
|
|
325
|
-
configurable: false
|
|
326
|
-
},
|
|
327
|
-
description: {
|
|
328
|
-
get: () => this.#description,
|
|
329
|
-
enumerable: true,
|
|
330
|
-
configurable: false
|
|
331
|
-
},
|
|
332
|
-
inputSchema: {
|
|
333
|
-
get: () => this.#inputSchema,
|
|
334
|
-
enumerable: true,
|
|
335
|
-
configurable: false
|
|
336
|
-
},
|
|
337
|
-
artifactConstructor: {
|
|
338
|
-
get: () => this.#artifactConstructor,
|
|
339
|
-
enumerable: true,
|
|
340
|
-
configurable: false
|
|
341
|
-
},
|
|
342
|
-
meta: {
|
|
343
|
-
get: () => this.#meta,
|
|
344
|
-
enumerable: true,
|
|
345
|
-
configurable: false
|
|
346
|
-
},
|
|
347
|
-
ephemeral: {
|
|
348
|
-
get: () => this.#ephemeral,
|
|
349
|
-
enumerable: true,
|
|
350
|
-
configurable: false
|
|
351
|
-
},
|
|
352
|
-
trusted: {
|
|
353
|
-
get: () => this.#trusted,
|
|
354
|
-
enumerable: true,
|
|
355
|
-
configurable: false
|
|
356
|
-
},
|
|
357
|
-
onCollision: {
|
|
358
|
-
get: () => this.#onCollision,
|
|
359
|
-
enumerable: true,
|
|
360
|
-
configurable: false
|
|
361
|
-
}
|
|
362
|
-
});
|
|
381
|
+
get(key, defaultValue) {
|
|
382
|
+
const value = (0, dlv.default)((0, klona.klona)(this.#store), key);
|
|
383
|
+
return "undefined" === typeof value ? defaultValue : value;
|
|
363
384
|
}
|
|
364
385
|
/**
|
|
365
|
-
*
|
|
386
|
+
* Sets the value at `key`, creating intermediate objects as needed.
|
|
366
387
|
*
|
|
367
388
|
* @remarks
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
* in the tool call loop, not a downstream failure.
|
|
389
|
+
* The stored value is isolated from the caller — mutating `value` after this call will not
|
|
390
|
+
* affect what is held in the registry.
|
|
371
391
|
*
|
|
372
|
-
* @param
|
|
373
|
-
* @
|
|
374
|
-
* @throws {@link @nhtio/adk!E_INVALID_TOOL_ARGS} when `args` does not satisfy the input schema.
|
|
392
|
+
* @param key - Dot-delimited path into the store (e.g. `"user.name"`).
|
|
393
|
+
* @param value - Value to store at the path.
|
|
375
394
|
*/
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
return await require_exceptions.asyncValidateOrThrow(this.#inputSchema, args);
|
|
379
|
-
} catch (err) {
|
|
380
|
-
if (require_guards.isInstanceOf(err, "ValidationException", require_exceptions.ValidationException)) throw new require_tokenizable.E_INVALID_TOOL_ARGS({ cause: err });
|
|
381
|
-
throw err;
|
|
382
|
-
}
|
|
395
|
+
set(key, value) {
|
|
396
|
+
(0, dset.dset)(this.#store, key, value);
|
|
383
397
|
}
|
|
384
398
|
/**
|
|
385
|
-
* Returns
|
|
399
|
+
* Returns `true` if the registry has a value at `key`, `false` otherwise.
|
|
386
400
|
*
|
|
387
401
|
* @remarks
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
* (3) emits `toolExecutionStart` on the context (with the computed `callId`), (4) calls the
|
|
391
|
-
* handler, (5) emits `toolExecutionEnd` (with the same `callId`), (6) wraps any handler error
|
|
392
|
-
* in {@link @nhtio/adk!E_TOOL_DOWNSTREAM_ERROR} before re-throwing.
|
|
402
|
+
* A key resolving to `undefined` is treated as absent — same convention as {@link Registry.get}'s
|
|
403
|
+
* `defaultValue` fallback. No clone is performed; this is a pure existence check.
|
|
393
404
|
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
405
|
+
* @param key - Dot-delimited path into the store (e.g. `"user.name"`).
|
|
406
|
+
* @returns `true` when the path resolves to a value other than `undefined`.
|
|
407
|
+
*/
|
|
408
|
+
has(key) {
|
|
409
|
+
return "undefined" !== typeof (0, dlv.default)(this.#store, key);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Returns all leaf dot-paths present in the registry.
|
|
400
413
|
*
|
|
401
|
-
*
|
|
414
|
+
* @remarks
|
|
415
|
+
* The store is deep-cloned before traversal. Plain objects are walked recursively with path
|
|
416
|
+
* segments joined by dots; arrays, primitives, `null`, and class instances are treated as leaves.
|
|
402
417
|
*
|
|
403
|
-
* @
|
|
404
|
-
* @returns An async function `(args) => Promise<string | Uint8Array | SpooledArtifact | Media | Media[]>`.
|
|
405
|
-
* A `SpooledArtifact` is a result the HANDLER built (streamed to storage and wrapped itself); a
|
|
406
|
-
* wrap-site passes it through unwrapped rather than re-spooling it. `string`/`Uint8Array` are the
|
|
407
|
-
* opposite case — bytes the consumer must still store and wrap.
|
|
418
|
+
* @returns A string array of dot-delimited paths to leaf values in the store.
|
|
408
419
|
*/
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
args: validatedArgs,
|
|
422
|
-
startedAt
|
|
423
|
-
});
|
|
424
|
-
try {
|
|
425
|
-
const result = await this.#handler(validatedArgs, ctx, this.#meta);
|
|
426
|
-
const endedAt = luxon.DateTime.now();
|
|
427
|
-
ctx.emitToolExecutionEnd({
|
|
428
|
-
toolName: this.#name,
|
|
429
|
-
turnId: ctx.id,
|
|
430
|
-
callId,
|
|
431
|
-
startedAt,
|
|
432
|
-
endedAt,
|
|
433
|
-
durationMs: endedAt.diff(startedAt).milliseconds,
|
|
434
|
-
isError: false
|
|
435
|
-
});
|
|
436
|
-
return result;
|
|
437
|
-
} catch (err) {
|
|
438
|
-
const endedAt = luxon.DateTime.now();
|
|
439
|
-
ctx.emitToolExecutionEnd({
|
|
440
|
-
toolName: this.#name,
|
|
441
|
-
turnId: ctx.id,
|
|
442
|
-
callId,
|
|
443
|
-
startedAt,
|
|
444
|
-
endedAt,
|
|
445
|
-
durationMs: endedAt.diff(startedAt).milliseconds,
|
|
446
|
-
isError: true
|
|
447
|
-
});
|
|
448
|
-
throw new require_tokenizable.E_TOOL_DOWNSTREAM_ERROR({ cause: require_guards.isError(err) ? err : void 0 });
|
|
420
|
+
keys() {
|
|
421
|
+
const store = (0, klona.klona)(this.#store);
|
|
422
|
+
const keys = [];
|
|
423
|
+
const isPlainRecord = (value) => {
|
|
424
|
+
if (!require_guards.isObject(value)) return false;
|
|
425
|
+
const prototype = Object.getPrototypeOf(value);
|
|
426
|
+
return prototype === Object.prototype || prototype === null;
|
|
427
|
+
};
|
|
428
|
+
const walk = (value, segments) => {
|
|
429
|
+
if (!isPlainRecord(value)) {
|
|
430
|
+
if (segments.length > 0) keys.push(segments.join("."));
|
|
431
|
+
return;
|
|
449
432
|
}
|
|
433
|
+
for (const [segment, child] of Object.entries(value)) walk(child, [...segments, segment]);
|
|
450
434
|
};
|
|
435
|
+
walk(store, []);
|
|
436
|
+
return keys;
|
|
451
437
|
}
|
|
452
438
|
/**
|
|
453
|
-
* Returns a
|
|
454
|
-
*
|
|
455
|
-
* @remarks
|
|
456
|
-
* The `inputSchema` property is the result of calling `.describe()` on the raw schema — a plain
|
|
457
|
-
* object carrying all the annotation metadata (descriptions, notes, examples, types) without any
|
|
458
|
-
* validator functions. Use this to build provider-specific LLM tool definitions.
|
|
439
|
+
* Returns a deep clone of the entire store contents.
|
|
459
440
|
*
|
|
460
|
-
* @returns
|
|
441
|
+
* @returns A plain object snapshot of all stored key-value pairs.
|
|
461
442
|
*/
|
|
462
|
-
|
|
463
|
-
return
|
|
464
|
-
name: this.#name,
|
|
465
|
-
description: this.#description,
|
|
466
|
-
inputSchema: this.#inputSchema.describe()
|
|
467
|
-
};
|
|
443
|
+
all() {
|
|
444
|
+
return (0, klona.klona)(this.#store);
|
|
468
445
|
}
|
|
469
446
|
/**
|
|
470
|
-
* Serialise this
|
|
447
|
+
* Serialise this Registry into an `@nhtio/encoder` snapshot.
|
|
471
448
|
*
|
|
472
449
|
* @remarks
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
* - **`inputSchema`** — delegated to `@nhtio/validation`'s `encode()`, which captures the full schema
|
|
477
|
-
* description plus its library version into a compact string; decode rebuilds the live `Schema`.
|
|
478
|
-
* - **`handler` / `artifactConstructor`** — emitted as **functions**. The encoder's `FunctionSerializer`
|
|
479
|
-
* serialises them by **source text** (`fn.toString()`). This is the sharp edge: a handler that
|
|
480
|
-
* closes over `ctx`, service clients, or config loses those bindings on decode — only the source
|
|
481
|
-
* survives, and the captured variables read back as `undefined`. A `.bind()`-ed or native handler
|
|
482
|
-
* cannot be serialised at all and the encoder throws. Tools are rarely serialised in practice; when
|
|
483
|
-
* they are, write handlers that reconstruct their dependencies inside the body rather than closing
|
|
484
|
-
* over them.
|
|
450
|
+
* The snapshot is a deep clone of the store ({@link Registry.all}). Leaf values that are themselves
|
|
451
|
+
* registered encodable instances round-trip; anything the encoder cannot serialise throws at encode
|
|
452
|
+
* time (standard encoder behaviour). Round-trips via {@link Registry.[DECODE_METHOD]}.
|
|
485
453
|
*
|
|
486
|
-
* @returns A
|
|
454
|
+
* @returns A deep-cloned plain-object snapshot of the store.
|
|
487
455
|
*/
|
|
488
456
|
[require_tokenizable.ENCODE_METHOD]() {
|
|
489
|
-
return
|
|
490
|
-
name: this.#name,
|
|
491
|
-
description: this.#description,
|
|
492
|
-
inputSchema: (0, _nhtio_validation.encode)(this.#inputSchema),
|
|
493
|
-
handler: this.#handler,
|
|
494
|
-
artifactConstructor: this.#artifactConstructor,
|
|
495
|
-
meta: this.#meta.all(),
|
|
496
|
-
ephemeral: this.#ephemeral,
|
|
497
|
-
trusted: this.#trusted,
|
|
498
|
-
onCollision: this.#onCollision
|
|
499
|
-
};
|
|
457
|
+
return this.all();
|
|
500
458
|
}
|
|
501
459
|
/**
|
|
502
|
-
* Reconstruct a {@link
|
|
503
|
-
*
|
|
504
|
-
* @remarks
|
|
505
|
-
* Rebuilds the live `Schema` via `@nhtio/validation`'s `decode()`, then re-validates through the
|
|
506
|
-
* constructor. The rehydrated `handler` carries only its source text — see
|
|
507
|
-
* {@link Tool.[ENCODE_METHOD]} for the closure caveat.
|
|
460
|
+
* Reconstruct a {@link Registry} from a {@link Registry.[ENCODE_METHOD]} snapshot.
|
|
508
461
|
*
|
|
509
|
-
* @param data - The snapshot produced by {@link
|
|
510
|
-
* @returns A
|
|
462
|
+
* @param data - The store snapshot produced by {@link Registry.[ENCODE_METHOD]}.
|
|
463
|
+
* @returns A fresh {@link Registry} seeded with the snapshot.
|
|
511
464
|
*/
|
|
512
465
|
static [require_tokenizable.DECODE_METHOD](data) {
|
|
513
|
-
|
|
514
|
-
return new Tool({
|
|
515
|
-
...snapshot,
|
|
516
|
-
inputSchema: (0, _nhtio_validation.decode)(snapshot.inputSchema)
|
|
517
|
-
});
|
|
466
|
+
return new Registry(data);
|
|
518
467
|
}
|
|
519
468
|
};
|
|
520
469
|
//#endregion
|
|
521
|
-
//#region src/lib/
|
|
470
|
+
//#region src/lib/contracts/spooled_artifact_constructor.ts
|
|
471
|
+
var ARTIFACT_METHODS = [
|
|
472
|
+
"head",
|
|
473
|
+
"tail",
|
|
474
|
+
"grep",
|
|
475
|
+
"cat",
|
|
476
|
+
"byteLength",
|
|
477
|
+
"lineCount",
|
|
478
|
+
"estimateTokens"
|
|
479
|
+
];
|
|
522
480
|
/**
|
|
523
|
-
* Validator schema
|
|
481
|
+
* Validator schema used to validate a {@link SpooledArtifactConstructorLike} value.
|
|
524
482
|
*
|
|
525
483
|
* @remarks
|
|
526
|
-
*
|
|
527
|
-
*
|
|
484
|
+
* Because the validator is invoked at validate-time (not at module-load), it is safe to inspect
|
|
485
|
+
* the constructor's prototype here. The check is duck-typed: the value must be a function whose
|
|
486
|
+
* `prototype` carries every canonical artifact instance method (`head`, `tail`, `grep`, `cat`,
|
|
487
|
+
* `byteLength`, `lineCount`, `estimateTokens`). This mirrors {@link spoolReaderSchema}'s
|
|
488
|
+
* cross-realm-safe duck-type pattern — `instanceof SpooledArtifact` would be tighter but would
|
|
489
|
+
* force a value-import of the class and reopen the module cycle.
|
|
528
490
|
*/
|
|
529
|
-
var
|
|
491
|
+
var spooledArtifactConstructorSchema = _nhtio_validation.validator.any().required().custom((value, helpers) => {
|
|
492
|
+
if (typeof value !== "function") return helpers.error("any.invalid");
|
|
493
|
+
const proto = value.prototype;
|
|
494
|
+
if (proto === void 0 || proto === null) return helpers.error("any.invalid");
|
|
495
|
+
if (ARTIFACT_METHODS.every((m) => typeof proto[m] === "function")) return value;
|
|
496
|
+
return helpers.error("any.invalid");
|
|
497
|
+
});
|
|
498
|
+
/**
|
|
499
|
+
* Returns `true` if `value` is a constructor whose prototype carries every canonical
|
|
500
|
+
* {@link @nhtio/adk!SpooledArtifact} instance method.
|
|
501
|
+
*
|
|
502
|
+
* @remarks
|
|
503
|
+
* Duck-typed; does not use `instanceof SpooledArtifact`. Used by the `Tool.artifactConstructor`
|
|
504
|
+
* resolver validator and any other site that needs to recognise a `SpooledArtifact`-like
|
|
505
|
+
* constructor without pulling the class into its module-load graph.
|
|
506
|
+
*
|
|
507
|
+
* @param value - The value to test.
|
|
508
|
+
* @returns `true` when `value` is a `SpooledArtifact`-shaped constructor.
|
|
509
|
+
*/
|
|
510
|
+
var implementsSpooledArtifactConstructor = (value) => {
|
|
511
|
+
return require_exceptions.passesSchema(spooledArtifactConstructorSchema, value);
|
|
512
|
+
};
|
|
513
|
+
/**
|
|
514
|
+
* Creates the validator fragment for a resolver returning a spooled-artifact constructor.
|
|
515
|
+
*
|
|
516
|
+
* The resolver is invoked during validation, then its result is checked with the canonical
|
|
517
|
+
* cross-realm-safe constructor guard. Keeping this fragment here makes `Tool` and `Retrievable`
|
|
518
|
+
* share exactly the same validation behaviour.
|
|
519
|
+
*/
|
|
520
|
+
var artifactConstructorResolverSchema = () => _nhtio_validation.validator.any().custom((value, helpers) => {
|
|
521
|
+
if (typeof value !== "function") return helpers.error("any.invalid");
|
|
522
|
+
let resolved;
|
|
523
|
+
try {
|
|
524
|
+
resolved = value();
|
|
525
|
+
} catch {
|
|
526
|
+
return helpers.error("any.invalid");
|
|
527
|
+
}
|
|
528
|
+
return implementsSpooledArtifactConstructor(resolved) ? value : helpers.error("any.invalid");
|
|
529
|
+
});
|
|
530
|
+
//#endregion
|
|
531
|
+
//#region src/lib/classes/tool.ts
|
|
532
|
+
/**
|
|
533
|
+
* Validator schema for a {@link RawTool}.
|
|
534
|
+
*/
|
|
535
|
+
var rawToolSchema = _nhtio_validation.validator.object({
|
|
530
536
|
name: _nhtio_validation.validator.string().required(),
|
|
531
537
|
description: _nhtio_validation.validator.string().required(),
|
|
532
538
|
inputSchema: _nhtio_validation.validator.any().custom((value, helpers) => {
|
|
@@ -534,404 +540,398 @@ var rawArtifactToolSchema = _nhtio_validation.validator.object({
|
|
|
534
540
|
return helpers.error("any.invalid");
|
|
535
541
|
}).required(),
|
|
536
542
|
handler: _nhtio_validation.validator.function().required(),
|
|
543
|
+
artifactConstructor: artifactConstructorResolverSchema().optional(),
|
|
537
544
|
meta: _nhtio_validation.validator.object().pattern(_nhtio_validation.validator.string(), _nhtio_validation.validator.any()).default({}),
|
|
538
545
|
ephemeral: _nhtio_validation.validator.boolean().default(false),
|
|
539
546
|
trusted: _nhtio_validation.validator.boolean().default(false),
|
|
540
|
-
onCollision: _nhtio_validation.validator.string().valid("throw", "replace", "keep").default("throw")
|
|
541
|
-
artifactConstructor: _nhtio_validation.validator.any().forbidden()
|
|
547
|
+
onCollision: _nhtio_validation.validator.string().valid("throw", "replace", "keep").default("throw")
|
|
542
548
|
});
|
|
543
549
|
/**
|
|
544
|
-
* A
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
* @remarks
|
|
549
|
-
* `ArtifactTool` is the canonical producer for **forged artifact-query tools** — the tools
|
|
550
|
-
* `SpooledArtifact.forgeTools(ctx)` emits so the model can `head`, `tail`, `grep`, `json_get`,
|
|
551
|
-
* `md_headings` (etc.) an artifact that is already in `ctx.turnToolCalls`.
|
|
552
|
-
*
|
|
553
|
-
* The difference from {@link @nhtio/adk!Tool} is structural, not stylistic:
|
|
554
|
-
*
|
|
555
|
-
* - A normal `Tool`'s handler returns bytes the ADK wraps in a fresh `SpooledArtifact`.
|
|
556
|
-
* The artifact lands in `ToolCall.results`, joins `ctx.turnToolCalls`, and is itself a
|
|
557
|
-
* first-class queryable artifact in the turn.
|
|
558
|
-
* - An `ArtifactTool`'s handler returns a string that is **already the model-visible answer**
|
|
559
|
-
* to a query against an existing artifact. The ADK wraps it in a `Tokenizable` rather
|
|
560
|
-
* than a `SpooledArtifact`; nothing new is queryable on its own. Subsequent
|
|
561
|
-
* `forgeTools(ctx)` calls exclude `ToolCall`s produced by an `ArtifactTool` from the
|
|
562
|
-
* `callId` enum (via the `ToolCall.fromArtifactTool` marker) — this is the structural fix
|
|
563
|
-
* that breaks the otherwise-recursive grep-on-the-grep-result loop.
|
|
550
|
+
* A tool definition that serves as the single source of truth for a callable tool: its name,
|
|
551
|
+
* description, input schema, execution handler, and the {@link @nhtio/adk!SpooledArtifact} subclass that
|
|
552
|
+
* wraps its serialised output.
|
|
564
553
|
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
*/
|
|
568
|
-
var ArtifactTool = class ArtifactTool extends Tool {
|
|
569
|
-
/**
|
|
570
|
-
* Validator schema that accepts a {@link RawArtifactTool} object.
|
|
571
|
-
*
|
|
572
|
-
* @remarks
|
|
573
|
-
* Differs from {@link @nhtio/adk!Tool.schema} by forbidding `artifactConstructor` — wrapping is
|
|
574
|
-
* exactly the thing this class opts out of. Typed identically to {@link @nhtio/adk!Tool.schema} so the
|
|
575
|
-
* subclass relationship `class ArtifactTool extends Tool` remains structurally sound; the
|
|
576
|
-
* runtime validation rules still differ as declared by `rawArtifactToolSchema`.
|
|
577
|
-
*/
|
|
578
|
-
static schema = rawArtifactToolSchema;
|
|
579
|
-
/**
|
|
580
|
-
* Returns `true` if `value` is an {@link ArtifactTool} instance.
|
|
581
|
-
*
|
|
582
|
-
* @remarks
|
|
583
|
-
* Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances
|
|
584
|
-
* created in a different module copy or VM context.
|
|
585
|
-
*
|
|
586
|
-
* @param value - The value to test.
|
|
587
|
-
* @returns `true` when `value` is an {@link ArtifactTool} instance.
|
|
588
|
-
*/
|
|
589
|
-
static isArtifactTool(value) {
|
|
590
|
-
return require_guards.isInstanceOf(value, "ArtifactTool", ArtifactTool);
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* @param raw - Raw tool input validated against {@link ArtifactTool.schema}.
|
|
594
|
-
*
|
|
595
|
-
* @throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_VALUE} when `raw` does not satisfy
|
|
596
|
-
* {@link ArtifactTool.schema} (most commonly, when `artifactConstructor` is supplied — it is
|
|
597
|
-
* explicitly forbidden on this class) or when the base {@link @nhtio/adk!Tool} constructor rejects the
|
|
598
|
-
* input for any reason.
|
|
599
|
-
*/
|
|
600
|
-
constructor(raw) {
|
|
601
|
-
try {
|
|
602
|
-
require_exceptions.validateOrThrow(rawArtifactToolSchema, raw, true);
|
|
603
|
-
} catch (err) {
|
|
604
|
-
if (require_guards.isInstanceOf(err, "ValidationException", require_exceptions.ValidationException)) throw new require_tokenizable.E_INVALID_INITIAL_TOOL_VALUE({ cause: err });
|
|
605
|
-
throw err;
|
|
606
|
-
}
|
|
607
|
-
super(raw);
|
|
608
|
-
}
|
|
609
|
-
/**
|
|
610
|
-
* Serialise this ArtifactTool into an `@nhtio/encoder` snapshot.
|
|
611
|
-
*
|
|
612
|
-
* @remarks
|
|
613
|
-
* Reuses the base {@link Tool.[ENCODE_METHOD]} (function-serialised `handler`, validation-encoded
|
|
614
|
-
* `inputSchema`, plain config) and strips `artifactConstructor` — which {@link ArtifactTool.schema}
|
|
615
|
-
* forbids. The handler's closure caveat from {@link Tool.[ENCODE_METHOD]} applies here too.
|
|
616
|
-
*
|
|
617
|
-
* @returns A {@link RawArtifactTool}-shaped snapshot (with `inputSchema` as an encoded string).
|
|
618
|
-
*/
|
|
619
|
-
[require_tokenizable.ENCODE_METHOD]() {
|
|
620
|
-
const base = super[require_tokenizable.ENCODE_METHOD]();
|
|
621
|
-
delete base.artifactConstructor;
|
|
622
|
-
return base;
|
|
623
|
-
}
|
|
624
|
-
/**
|
|
625
|
-
* Reconstruct an {@link ArtifactTool} from an {@link ArtifactTool.[ENCODE_METHOD]} snapshot.
|
|
626
|
-
*
|
|
627
|
-
* @param data - The snapshot produced by {@link ArtifactTool.[ENCODE_METHOD]}.
|
|
628
|
-
* @returns A fully-validated {@link ArtifactTool}.
|
|
629
|
-
*/
|
|
630
|
-
static [require_tokenizable.DECODE_METHOD](data) {
|
|
631
|
-
const snapshot = data;
|
|
632
|
-
return new ArtifactTool({
|
|
633
|
-
...snapshot,
|
|
634
|
-
inputSchema: (0, _nhtio_validation.decode)(snapshot.inputSchema)
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
};
|
|
638
|
-
//#endregion
|
|
639
|
-
//#region src/lib/classes/tool_registry.ts
|
|
640
|
-
/**
|
|
641
|
-
* A mutable, turn-scoped collection of {@link @nhtio/adk!Tool} instances.
|
|
554
|
+
* @typeParam A - The {@link @nhtio/adk!SpooledArtifact} subtype this tool's results should be wrapped in.
|
|
555
|
+
* Defaults to {@link @nhtio/adk!SpooledArtifact}.
|
|
642
556
|
*
|
|
643
557
|
* @remarks
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
558
|
+
* The `inputSchema` is a `@nhtio/validation` schema. It is used at runtime to validate incoming
|
|
559
|
+
* arguments before the handler is called, and its `.describe()` output provides all the metadata
|
|
560
|
+
* needed to build a provider-specific LLM tool definition — annotate the schema with
|
|
561
|
+
* `.description()`, `.note()`, `.example()` etc. once, and that information is available in both
|
|
562
|
+
* contexts without duplication.
|
|
649
563
|
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
564
|
+
* The handler is private — invoke it only through `executor(ctx)` which validates args, fires
|
|
565
|
+
* observability events (with a stable `callId` derived from the tool name and arguments), and
|
|
566
|
+
* wraps handler errors in {@link @nhtio/adk!E_TOOL_DOWNSTREAM_ERROR}. The handler returns serialised bytes
|
|
567
|
+
* (`string | Uint8Array`); persistence is the consumer's responsibility.
|
|
652
568
|
*
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
*
|
|
656
|
-
* Hidden state is a property of the registry, not the tool: the same tool can be visible in one
|
|
657
|
-
* registry and hidden in another. See {@link hide}, {@link visible}, {@link hidden}.
|
|
569
|
+
* `artifactConstructor` is the {@link @nhtio/adk!SpooledArtifact} subclass the consumer should use when
|
|
570
|
+
* wrapping the handler's output into a `ToolCall.results` field. The author declares it once
|
|
571
|
+
* on the tool instance; the consumer reads it when assembling persisted records.
|
|
658
572
|
*/
|
|
659
|
-
var
|
|
660
|
-
#tools;
|
|
661
|
-
#hidden;
|
|
662
|
-
/**
|
|
663
|
-
* Returns `true` if `value` is a {@link ToolRegistry} instance.
|
|
664
|
-
*
|
|
665
|
-
* @param value - The value to test.
|
|
666
|
-
* @returns `true` when `value` is a {@link ToolRegistry} instance.
|
|
667
|
-
*/
|
|
668
|
-
static isToolRegistry(value) {
|
|
669
|
-
return require_guards.isInstanceOf(value, "ToolRegistry", ToolRegistry);
|
|
670
|
-
}
|
|
671
|
-
/**
|
|
672
|
-
* @param tools - Optional initial tools. Insertion order is preserved. Duplicate names throw
|
|
673
|
-
* {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} — ensure each tool has a unique name.
|
|
674
|
-
* @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when two tools in `tools` share a name.
|
|
675
|
-
*/
|
|
676
|
-
constructor(tools) {
|
|
677
|
-
this.#tools = /* @__PURE__ */ new Map();
|
|
678
|
-
this.#hidden = /* @__PURE__ */ new Set();
|
|
679
|
-
for (const tool of tools ?? []) this.register(tool);
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
|
-
* Adds a tool to the registry.
|
|
683
|
-
*
|
|
684
|
-
* @param tool - The tool to register.
|
|
685
|
-
* @param overwrite - When `true`, silently replaces an existing tool with the same name.
|
|
686
|
-
* Defaults to `false`.
|
|
687
|
-
* @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when a tool with the same name is already registered
|
|
688
|
-
* and `overwrite` is not `true`.
|
|
689
|
-
*/
|
|
690
|
-
register(tool, overwrite) {
|
|
691
|
-
if (this.#tools.has(tool.name) && !overwrite) throw new require_tokenizable.E_TOOL_ALREADY_REGISTERED();
|
|
692
|
-
this.#tools.set(tool.name, tool);
|
|
693
|
-
}
|
|
573
|
+
var Tool = class Tool {
|
|
694
574
|
/**
|
|
695
|
-
*
|
|
575
|
+
* Validator schema that accepts a {@link RawTool} object.
|
|
696
576
|
*
|
|
697
577
|
* @remarks
|
|
698
|
-
*
|
|
699
|
-
*
|
|
700
|
-
*
|
|
701
|
-
* @param name - The name of the tool to remove.
|
|
578
|
+
* Reusable fragment for any schema that needs to validate or nest a tool entry
|
|
579
|
+
* (e.g. `TurnRunnerConfig.tools`).
|
|
702
580
|
*/
|
|
703
|
-
|
|
704
|
-
this.#tools.delete(name);
|
|
705
|
-
this.#hidden.delete(name);
|
|
706
|
-
}
|
|
581
|
+
static schema = rawToolSchema;
|
|
707
582
|
/**
|
|
708
|
-
* Returns
|
|
583
|
+
* Returns `true` if `value` is a {@link Tool} instance.
|
|
709
584
|
*
|
|
710
|
-
* @param
|
|
585
|
+
* @param value - The value to test.
|
|
586
|
+
* @returns `true` when `value` is a {@link Tool} instance.
|
|
711
587
|
*/
|
|
712
|
-
|
|
713
|
-
return
|
|
588
|
+
static isTool(value) {
|
|
589
|
+
return require_guards.isInstanceOf(value, "Tool", Tool);
|
|
714
590
|
}
|
|
591
|
+
#name;
|
|
592
|
+
#description;
|
|
593
|
+
#inputSchema;
|
|
594
|
+
#handler;
|
|
595
|
+
#artifactConstructor;
|
|
596
|
+
#meta;
|
|
597
|
+
#ephemeral;
|
|
598
|
+
#trusted;
|
|
599
|
+
#onCollision;
|
|
715
600
|
/**
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
* @param name - The tool name to test.
|
|
601
|
+
* @param raw - The raw tool input validated against `rawToolSchema`.
|
|
602
|
+
* @throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_VALUE} when `raw` does not satisfy the schema.
|
|
719
603
|
*/
|
|
720
|
-
|
|
721
|
-
|
|
604
|
+
constructor(raw) {
|
|
605
|
+
let resolved;
|
|
606
|
+
try {
|
|
607
|
+
resolved = require_exceptions.validateOrThrow(rawToolSchema, raw, true);
|
|
608
|
+
} catch (err) {
|
|
609
|
+
throw new require_tokenizable.E_INVALID_INITIAL_TOOL_VALUE({ cause: require_guards.isError(err) ? err : void 0 });
|
|
610
|
+
}
|
|
611
|
+
this.#name = resolved.name;
|
|
612
|
+
this.#description = resolved.description;
|
|
613
|
+
this.#inputSchema = resolved.inputSchema;
|
|
614
|
+
this.#handler = resolved.handler;
|
|
615
|
+
this.#artifactConstructor = resolved.artifactConstructor;
|
|
616
|
+
this.#meta = new Registry(resolved.meta);
|
|
617
|
+
this.#ephemeral = resolved.ephemeral;
|
|
618
|
+
this.#trusted = resolved.trusted;
|
|
619
|
+
this.#onCollision = resolved.onCollision;
|
|
620
|
+
Object.defineProperties(this, {
|
|
621
|
+
name: {
|
|
622
|
+
get: () => this.#name,
|
|
623
|
+
enumerable: true,
|
|
624
|
+
configurable: false
|
|
625
|
+
},
|
|
626
|
+
description: {
|
|
627
|
+
get: () => this.#description,
|
|
628
|
+
enumerable: true,
|
|
629
|
+
configurable: false
|
|
630
|
+
},
|
|
631
|
+
inputSchema: {
|
|
632
|
+
get: () => this.#inputSchema,
|
|
633
|
+
enumerable: true,
|
|
634
|
+
configurable: false
|
|
635
|
+
},
|
|
636
|
+
artifactConstructor: {
|
|
637
|
+
get: () => this.#artifactConstructor,
|
|
638
|
+
enumerable: true,
|
|
639
|
+
configurable: false
|
|
640
|
+
},
|
|
641
|
+
meta: {
|
|
642
|
+
get: () => this.#meta,
|
|
643
|
+
enumerable: true,
|
|
644
|
+
configurable: false
|
|
645
|
+
},
|
|
646
|
+
ephemeral: {
|
|
647
|
+
get: () => this.#ephemeral,
|
|
648
|
+
enumerable: true,
|
|
649
|
+
configurable: false
|
|
650
|
+
},
|
|
651
|
+
trusted: {
|
|
652
|
+
get: () => this.#trusted,
|
|
653
|
+
enumerable: true,
|
|
654
|
+
configurable: false
|
|
655
|
+
},
|
|
656
|
+
onCollision: {
|
|
657
|
+
get: () => this.#onCollision,
|
|
658
|
+
enumerable: true,
|
|
659
|
+
configurable: false
|
|
660
|
+
}
|
|
661
|
+
});
|
|
722
662
|
}
|
|
723
663
|
/**
|
|
724
|
-
*
|
|
664
|
+
* Validates `args` against the tool's input schema asynchronously.
|
|
725
665
|
*
|
|
726
666
|
* @remarks
|
|
727
|
-
*
|
|
728
|
-
* {@link
|
|
667
|
+
* Async to support schemas with external validators (e.g. database lookups, API calls).
|
|
668
|
+
* A validation failure throws {@link @nhtio/adk!E_INVALID_TOOL_ARGS} — this indicates a programming error
|
|
669
|
+
* in the tool call loop, not a downstream failure.
|
|
729
670
|
*
|
|
730
|
-
*
|
|
671
|
+
* @param args - The arguments to validate.
|
|
672
|
+
* @returns The validated (and coerced) arguments.
|
|
673
|
+
* @throws {@link @nhtio/adk!E_INVALID_TOOL_ARGS} when `args` does not satisfy the input schema.
|
|
731
674
|
*/
|
|
732
|
-
|
|
733
|
-
|
|
675
|
+
async validate(args) {
|
|
676
|
+
try {
|
|
677
|
+
return await require_exceptions.asyncValidateOrThrow(this.#inputSchema, args);
|
|
678
|
+
} catch (err) {
|
|
679
|
+
if (require_guards.isInstanceOf(err, "ValidationException", require_exceptions.ValidationException)) throw new require_tokenizable.E_INVALID_TOOL_ARGS({ cause: err });
|
|
680
|
+
throw err;
|
|
681
|
+
}
|
|
734
682
|
}
|
|
735
683
|
/**
|
|
736
|
-
* Returns a
|
|
684
|
+
* Returns a bound executor function for this tool against the given turn context.
|
|
737
685
|
*
|
|
738
686
|
* @remarks
|
|
739
|
-
*
|
|
740
|
-
*
|
|
741
|
-
*
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
return this.all().filter((t) => !this.#hidden.has(t.name));
|
|
745
|
-
}
|
|
746
|
-
/**
|
|
747
|
-
* Returns a fresh array of registered tools that **are** hidden, in insertion order.
|
|
687
|
+
* The executor: (1) computes a stable `callId` as `sha256(canonicalStringify({tool, args}))`
|
|
688
|
+
* over the **raw, pre-validation args**, (2) validates `args` via {@link Tool.validate},
|
|
689
|
+
* (3) emits `toolExecutionStart` on the context (with the computed `callId`), (4) calls the
|
|
690
|
+
* handler, (5) emits `toolExecutionEnd` (with the same `callId`), (6) wraps any handler error
|
|
691
|
+
* in {@link @nhtio/adk!E_TOOL_DOWNSTREAM_ERROR} before re-throwing.
|
|
748
692
|
*
|
|
749
|
-
*
|
|
750
|
-
*
|
|
751
|
-
*
|
|
693
|
+
* The handler usually returns serialised bytes (`string | Uint8Array`) — persistence is then the
|
|
694
|
+
* consumer's concern, and {@link Tool.artifactConstructor} is the class a wrap-site uses when
|
|
695
|
+
* wrapping those bytes into a `ToolCall.results` field. **A handler may instead return a
|
|
696
|
+
* {@link @nhtio/adk!SpooledArtifact} it built itself** (streaming into storage and wrapping the
|
|
697
|
+
* reader), in which case wrap-sites pass it through untouched and `artifactConstructor` does not
|
|
698
|
+
* apply — the returned instance's own class is what artifact-tool forging reads.
|
|
699
|
+
*
|
|
700
|
+
* Pattern mirrors `Middleware.runner()` — call once per turn, reuse the returned function.
|
|
701
|
+
*
|
|
702
|
+
* @param ctx - The active turn context. Provides emit functions and turn ID.
|
|
703
|
+
* @returns An async function `(args) => Promise<string | Uint8Array | SpooledArtifact | Media | Media[]>`.
|
|
704
|
+
* A `SpooledArtifact` is a result the HANDLER built (streamed to storage and wrapped itself); a
|
|
705
|
+
* wrap-site passes it through unwrapped rather than re-spooling it. `string`/`Uint8Array` are the
|
|
706
|
+
* opposite case — bytes the consumer must still store and wrap.
|
|
752
707
|
*/
|
|
753
|
-
|
|
754
|
-
return
|
|
708
|
+
executor(ctx) {
|
|
709
|
+
return async (args) => {
|
|
710
|
+
const callId = (0, js_sha256.sha256)(canonicalStringify({
|
|
711
|
+
tool: this.#name,
|
|
712
|
+
args
|
|
713
|
+
}));
|
|
714
|
+
const validatedArgs = await this.validate(args);
|
|
715
|
+
const startedAt = luxon.DateTime.now();
|
|
716
|
+
ctx.emitToolExecutionStart({
|
|
717
|
+
toolName: this.#name,
|
|
718
|
+
turnId: ctx.id,
|
|
719
|
+
callId,
|
|
720
|
+
args: validatedArgs,
|
|
721
|
+
startedAt
|
|
722
|
+
});
|
|
723
|
+
try {
|
|
724
|
+
const result = await this.#handler(validatedArgs, ctx, this.#meta);
|
|
725
|
+
const endedAt = luxon.DateTime.now();
|
|
726
|
+
ctx.emitToolExecutionEnd({
|
|
727
|
+
toolName: this.#name,
|
|
728
|
+
turnId: ctx.id,
|
|
729
|
+
callId,
|
|
730
|
+
startedAt,
|
|
731
|
+
endedAt,
|
|
732
|
+
durationMs: endedAt.diff(startedAt).milliseconds,
|
|
733
|
+
isError: false
|
|
734
|
+
});
|
|
735
|
+
return result;
|
|
736
|
+
} catch (err) {
|
|
737
|
+
const endedAt = luxon.DateTime.now();
|
|
738
|
+
ctx.emitToolExecutionEnd({
|
|
739
|
+
toolName: this.#name,
|
|
740
|
+
turnId: ctx.id,
|
|
741
|
+
callId,
|
|
742
|
+
startedAt,
|
|
743
|
+
endedAt,
|
|
744
|
+
durationMs: endedAt.diff(startedAt).milliseconds,
|
|
745
|
+
isError: true
|
|
746
|
+
});
|
|
747
|
+
throw new require_tokenizable.E_TOOL_DOWNSTREAM_ERROR({ cause: require_guards.isError(err) ? err : void 0 });
|
|
748
|
+
}
|
|
749
|
+
};
|
|
755
750
|
}
|
|
756
751
|
/**
|
|
757
|
-
*
|
|
752
|
+
* Returns a fully serialisable snapshot of this tool's definition.
|
|
758
753
|
*
|
|
759
754
|
* @remarks
|
|
760
|
-
*
|
|
761
|
-
*
|
|
762
|
-
*
|
|
755
|
+
* The `inputSchema` property is the result of calling `.describe()` on the raw schema — a plain
|
|
756
|
+
* object carrying all the annotation metadata (descriptions, notes, examples, types) without any
|
|
757
|
+
* validator functions. Use this to build provider-specific LLM tool definitions.
|
|
763
758
|
*
|
|
764
|
-
* @
|
|
759
|
+
* @returns `{ name, description, inputSchema }` where `inputSchema` is the schema description.
|
|
765
760
|
*/
|
|
766
|
-
|
|
767
|
-
|
|
761
|
+
describe() {
|
|
762
|
+
return {
|
|
763
|
+
name: this.#name,
|
|
764
|
+
description: this.#description,
|
|
765
|
+
inputSchema: this.#inputSchema.describe()
|
|
766
|
+
};
|
|
768
767
|
}
|
|
769
768
|
/**
|
|
770
|
-
*
|
|
769
|
+
* Serialise this Tool into an `@nhtio/encoder` snapshot.
|
|
771
770
|
*
|
|
772
771
|
* @remarks
|
|
773
|
-
*
|
|
772
|
+
* Three halves with different serialisation strategies:
|
|
774
773
|
*
|
|
775
|
-
*
|
|
774
|
+
* - **Plain config** (`name`, `description`, `meta`, flags) — emitted verbatim.
|
|
775
|
+
* - **`inputSchema`** — delegated to `@nhtio/validation`'s `encode()`, which captures the full schema
|
|
776
|
+
* description plus its library version into a compact string; decode rebuilds the live `Schema`.
|
|
777
|
+
* - **`handler` / `artifactConstructor`** — emitted as **functions**. The encoder's `FunctionSerializer`
|
|
778
|
+
* serialises them by **source text** (`fn.toString()`). This is the sharp edge: a handler that
|
|
779
|
+
* closes over `ctx`, service clients, or config loses those bindings on decode — only the source
|
|
780
|
+
* survives, and the captured variables read back as `undefined`. A `.bind()`-ed or native handler
|
|
781
|
+
* cannot be serialised at all and the encoder throws. Tools are rarely serialised in practice; when
|
|
782
|
+
* they are, write handlers that reconstruct their dependencies inside the body rather than closing
|
|
783
|
+
* over them.
|
|
784
|
+
*
|
|
785
|
+
* @returns A {@link RawTool}-shaped snapshot (with `inputSchema` as an encoded string).
|
|
776
786
|
*/
|
|
777
|
-
|
|
778
|
-
|
|
787
|
+
[require_tokenizable.ENCODE_METHOD]() {
|
|
788
|
+
return {
|
|
789
|
+
name: this.#name,
|
|
790
|
+
description: this.#description,
|
|
791
|
+
inputSchema: (0, _nhtio_validation.encode)(this.#inputSchema),
|
|
792
|
+
handler: this.#handler,
|
|
793
|
+
artifactConstructor: this.#artifactConstructor,
|
|
794
|
+
meta: this.#meta.all(),
|
|
795
|
+
ephemeral: this.#ephemeral,
|
|
796
|
+
trusted: this.#trusted,
|
|
797
|
+
onCollision: this.#onCollision
|
|
798
|
+
};
|
|
779
799
|
}
|
|
780
800
|
/**
|
|
781
|
-
*
|
|
801
|
+
* Reconstruct a {@link Tool} from a {@link Tool.[ENCODE_METHOD]} snapshot.
|
|
782
802
|
*
|
|
783
803
|
* @remarks
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
*
|
|
804
|
+
* Rebuilds the live `Schema` via `@nhtio/validation`'s `decode()`, then re-validates through the
|
|
805
|
+
* constructor. The rehydrated `handler` carries only its source text — see
|
|
806
|
+
* {@link Tool.[ENCODE_METHOD]} for the closure caveat.
|
|
787
807
|
*
|
|
788
|
-
* @param
|
|
789
|
-
|
|
790
|
-
setHidden(...names) {
|
|
791
|
-
this.#hidden = new Set(names);
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* Unhides every tool in the registry.
|
|
808
|
+
* @param data - The snapshot produced by {@link Tool.[ENCODE_METHOD]}.
|
|
809
|
+
* @returns A fully-validated {@link Tool}.
|
|
795
810
|
*/
|
|
796
|
-
|
|
797
|
-
|
|
811
|
+
static [require_tokenizable.DECODE_METHOD](data) {
|
|
812
|
+
const snapshot = data;
|
|
813
|
+
return new Tool({
|
|
814
|
+
...snapshot,
|
|
815
|
+
inputSchema: (0, _nhtio_validation.decode)(snapshot.inputSchema)
|
|
816
|
+
});
|
|
798
817
|
}
|
|
818
|
+
};
|
|
819
|
+
//#endregion
|
|
820
|
+
//#region src/lib/classes/artifact_tool.ts
|
|
821
|
+
/**
|
|
822
|
+
* Validator schema for a {@link RawArtifactTool}.
|
|
823
|
+
*
|
|
824
|
+
* @remarks
|
|
825
|
+
* Mirrors the base tool schema but explicitly forbids `artifactConstructor` — the entire
|
|
826
|
+
* point of `ArtifactTool` is to opt out of `SpooledArtifact` wrapping.
|
|
827
|
+
*/
|
|
828
|
+
var rawArtifactToolSchema = _nhtio_validation.validator.object({
|
|
829
|
+
name: _nhtio_validation.validator.string().required(),
|
|
830
|
+
description: _nhtio_validation.validator.string().required(),
|
|
831
|
+
inputSchema: _nhtio_validation.validator.any().custom((value, helpers) => {
|
|
832
|
+
if (_nhtio_validation.validator.isSchema(value) && value.type === "object") return value;
|
|
833
|
+
return helpers.error("any.invalid");
|
|
834
|
+
}).required(),
|
|
835
|
+
handler: _nhtio_validation.validator.function().required(),
|
|
836
|
+
meta: _nhtio_validation.validator.object().pattern(_nhtio_validation.validator.string(), _nhtio_validation.validator.any()).default({}),
|
|
837
|
+
ephemeral: _nhtio_validation.validator.boolean().default(false),
|
|
838
|
+
trusted: _nhtio_validation.validator.boolean().default(false),
|
|
839
|
+
onCollision: _nhtio_validation.validator.string().valid("throw", "replace", "keep").default("throw"),
|
|
840
|
+
artifactConstructor: _nhtio_validation.validator.any().forbidden()
|
|
841
|
+
});
|
|
842
|
+
/**
|
|
843
|
+
* A {@link @nhtio/adk!Tool} subclass whose handler return value is wrapped directly in a
|
|
844
|
+
* {@link @nhtio/adk!Tokenizable} (not a {@link @nhtio/adk!SpooledArtifact}) when it
|
|
845
|
+
* lands on `ToolCall.results`.
|
|
846
|
+
*
|
|
847
|
+
* @remarks
|
|
848
|
+
* `ArtifactTool` is the canonical producer for **forged artifact-query tools** — the tools
|
|
849
|
+
* `SpooledArtifact.forgeTools(ctx)` emits so the model can `head`, `tail`, `grep`, `json_get`,
|
|
850
|
+
* `md_headings` (etc.) an artifact that is already in `ctx.turnToolCalls`.
|
|
851
|
+
*
|
|
852
|
+
* The difference from {@link @nhtio/adk!Tool} is structural, not stylistic:
|
|
853
|
+
*
|
|
854
|
+
* - A normal `Tool`'s handler returns bytes the ADK wraps in a fresh `SpooledArtifact`.
|
|
855
|
+
* The artifact lands in `ToolCall.results`, joins `ctx.turnToolCalls`, and is itself a
|
|
856
|
+
* first-class queryable artifact in the turn.
|
|
857
|
+
* - An `ArtifactTool`'s handler returns a string that is **already the model-visible answer**
|
|
858
|
+
* to a query against an existing artifact. The ADK wraps it in a `Tokenizable` rather
|
|
859
|
+
* than a `SpooledArtifact`; nothing new is queryable on its own. Subsequent
|
|
860
|
+
* `forgeTools(ctx)` calls exclude `ToolCall`s produced by an `ArtifactTool` from the
|
|
861
|
+
* `callId` enum (via the `ToolCall.fromArtifactTool` marker) — this is the structural fix
|
|
862
|
+
* that breaks the otherwise-recursive grep-on-the-grep-result loop.
|
|
863
|
+
*
|
|
864
|
+
* Consumers who want to build their own artifact-query tools (e.g. for a domain-specific
|
|
865
|
+
* spooled subclass not shipped by the ADK) should extend or instantiate this class.
|
|
866
|
+
*/
|
|
867
|
+
var ArtifactTool = class ArtifactTool extends Tool {
|
|
799
868
|
/**
|
|
800
|
-
*
|
|
869
|
+
* Validator schema that accepts a {@link RawArtifactTool} object.
|
|
801
870
|
*
|
|
802
871
|
* @remarks
|
|
803
|
-
*
|
|
804
|
-
*
|
|
805
|
-
*
|
|
806
|
-
*
|
|
872
|
+
* Differs from {@link @nhtio/adk!Tool.schema} by forbidding `artifactConstructor` — wrapping is
|
|
873
|
+
* exactly the thing this class opts out of. Typed identically to {@link @nhtio/adk!Tool.schema} so the
|
|
874
|
+
* subclass relationship `class ArtifactTool extends Tool` remains structurally sound; the
|
|
875
|
+
* runtime validation rules still differ as declared by `rawArtifactToolSchema`.
|
|
807
876
|
*/
|
|
808
|
-
|
|
809
|
-
for (const [name, tool] of this.#tools) if (tool.ephemeral) {
|
|
810
|
-
this.#tools.delete(name);
|
|
811
|
-
this.#hidden.delete(name);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
877
|
+
static schema = rawArtifactToolSchema;
|
|
814
878
|
/**
|
|
815
|
-
*
|
|
816
|
-
* automatically when the context is acked.
|
|
879
|
+
* Returns `true` if `value` is an {@link ArtifactTool} instance.
|
|
817
880
|
*
|
|
818
881
|
* @remarks
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
* failure. Subscriptions are short-lived and die with the context regardless.
|
|
822
|
-
*
|
|
823
|
-
* ARTIFACT READERS ARE FORGED BY THE CORE. As of the core-forge change, the `DispatchRunner` forges
|
|
824
|
-
* artifact-reader tools from prior-turn `SpooledArtifact` results into `ctx.tools` (and calls
|
|
825
|
-
* `ctx.tools.bindContext(ctx)`) once per iteration, BEFORE the input pipeline — so a battery executor no
|
|
826
|
-
* longer forges or binds; it reads the already-forged `ctx.tools` for both representation (rendering the
|
|
827
|
-
* tool declarations) and resolution (looking up an incoming call by name). The lifecycle is unchanged:
|
|
828
|
-
* ephemeral readers are still pruned on `ack`, and the core re-forges each iteration (prune-then-forge) so
|
|
829
|
-
* the `callId` enum never goes stale.
|
|
830
|
-
*
|
|
831
|
-
* `bindContext` remains the public seam for a CUSTOM consumer that forges its own ephemeral tools outside
|
|
832
|
-
* the core path. If you forge into a long-lived registry yourself, bind it (or prune manually) or the
|
|
833
|
-
* ephemeral tools accumulate and later `forgeTools(ctx)` calls see a stale `callId` enum. The pattern for a
|
|
834
|
-
* hand-rolled forge is:
|
|
835
|
-
*
|
|
836
|
-
* ```ts
|
|
837
|
-
* // Custom forge (the core already does this for artifact readers on ctx.tools):
|
|
838
|
-
* const forged = SpooledArtifact.forgeTools(ctx)
|
|
839
|
-
* for (const tool of forged.all()) ctx.tools.register(tool, true)
|
|
840
|
-
* ctx.tools.bindContext(ctx) // prune the ephemeral readers when the dispatch acks
|
|
841
|
-
* ```
|
|
842
|
-
*
|
|
843
|
-
* @param ctx - The execution context whose `ack` event should trigger pruning.
|
|
844
|
-
* @returns An unsubscribe function — calling it before `ctx.ack()` prevents pruning. Rarely
|
|
845
|
-
* useful outside of tests.
|
|
882
|
+
* Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances
|
|
883
|
+
* created in a different module copy or VM context.
|
|
846
884
|
*
|
|
847
|
-
* @
|
|
848
|
-
* @
|
|
885
|
+
* @param value - The value to test.
|
|
886
|
+
* @returns `true` when `value` is an {@link ArtifactTool} instance.
|
|
849
887
|
*/
|
|
850
|
-
|
|
851
|
-
return
|
|
888
|
+
static isArtifactTool(value) {
|
|
889
|
+
return require_guards.isInstanceOf(value, "ArtifactTool", ArtifactTool);
|
|
852
890
|
}
|
|
853
891
|
/**
|
|
854
|
-
*
|
|
855
|
-
* input.
|
|
856
|
-
*
|
|
857
|
-
* @remarks
|
|
858
|
-
* Iteration is left-to-right across `registries` and then in each registry's insertion order.
|
|
859
|
-
* Collisions are resolved by consulting the **incoming** tool's {@link @nhtio/adk!Tool.onCollision} first:
|
|
860
|
-
*
|
|
861
|
-
* - `'replace'` (per-tool): the incoming tool wins, replacing the existing entry.
|
|
862
|
-
* - `'keep'` (per-tool): the existing entry wins; the incoming tool is dropped.
|
|
863
|
-
* - `'throw'` (per-tool, the default): fall back to the merge-level `options.onCollision`.
|
|
864
|
-
*
|
|
865
|
-
* The merge-level `options.onCollision` defaults to `'throw'`, which mirrors {@link register}.
|
|
866
|
-
*
|
|
867
|
-
* The result is a brand-new registry; no input is mutated and no event subscription is
|
|
868
|
-
* propagated. Each `Tool`'s `ephemeral` flag carries through unchanged — the flag lives on the
|
|
869
|
-
* tool, not the registry, so `bindContext(ctx)` on the merged registry will prune the forged
|
|
870
|
-
* tools as expected.
|
|
871
|
-
*
|
|
872
|
-
* Hidden state is also propagated: a tool that is hidden in any source registry remains hidden
|
|
873
|
-
* in the merged result, provided it survives collision resolution.
|
|
892
|
+
* @param raw - Raw tool input validated against {@link ArtifactTool.schema}.
|
|
874
893
|
*
|
|
875
|
-
* @
|
|
876
|
-
*
|
|
877
|
-
*
|
|
878
|
-
*
|
|
879
|
-
* and a collision occurs.
|
|
894
|
+
* @throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_VALUE} when `raw` does not satisfy
|
|
895
|
+
* {@link ArtifactTool.schema} (most commonly, when `artifactConstructor` is supplied — it is
|
|
896
|
+
* explicitly forbidden on this class) or when the base {@link @nhtio/adk!Tool} constructor rejects the
|
|
897
|
+
* input for any reason.
|
|
880
898
|
*/
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
merged.register(tool);
|
|
888
|
-
continue;
|
|
889
|
-
}
|
|
890
|
-
const incomingPolicy = tool.onCollision;
|
|
891
|
-
if (incomingPolicy === "replace") {
|
|
892
|
-
merged.register(tool, true);
|
|
893
|
-
continue;
|
|
894
|
-
}
|
|
895
|
-
if (incomingPolicy === "keep") continue;
|
|
896
|
-
if (policy === "replace") {
|
|
897
|
-
merged.register(tool, true);
|
|
898
|
-
continue;
|
|
899
|
-
}
|
|
900
|
-
if (policy === "keep") continue;
|
|
901
|
-
throw new require_tokenizable.E_TOOL_ALREADY_REGISTERED();
|
|
902
|
-
}
|
|
903
|
-
for (const tool of registry.hidden()) if (merged.has(tool.name)) merged.hide(tool.name);
|
|
899
|
+
constructor(raw) {
|
|
900
|
+
try {
|
|
901
|
+
require_exceptions.validateOrThrow(rawArtifactToolSchema, raw, true);
|
|
902
|
+
} catch (err) {
|
|
903
|
+
if (require_guards.isInstanceOf(err, "ValidationException", require_exceptions.ValidationException)) throw new require_tokenizable.E_INVALID_INITIAL_TOOL_VALUE({ cause: err });
|
|
904
|
+
throw err;
|
|
904
905
|
}
|
|
905
|
-
|
|
906
|
+
super(raw);
|
|
906
907
|
}
|
|
907
908
|
/**
|
|
908
|
-
* Serialise this
|
|
909
|
+
* Serialise this ArtifactTool into an `@nhtio/encoder` snapshot.
|
|
909
910
|
*
|
|
910
911
|
* @remarks
|
|
911
|
-
*
|
|
912
|
-
*
|
|
913
|
-
*
|
|
914
|
-
* subtype. Round-trips via {@link ToolRegistry.[DECODE_METHOD]}.
|
|
912
|
+
* Reuses the base {@link Tool.[ENCODE_METHOD]} (function-serialised `handler`, validation-encoded
|
|
913
|
+
* `inputSchema`, plain config) and strips `artifactConstructor` — which {@link ArtifactTool.schema}
|
|
914
|
+
* forbids. The handler's closure caveat from {@link Tool.[ENCODE_METHOD]} applies here too.
|
|
915
915
|
*
|
|
916
|
-
* @returns A
|
|
916
|
+
* @returns A {@link RawArtifactTool}-shaped snapshot (with `inputSchema` as an encoded string).
|
|
917
917
|
*/
|
|
918
918
|
[require_tokenizable.ENCODE_METHOD]() {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
};
|
|
919
|
+
const base = super[require_tokenizable.ENCODE_METHOD]();
|
|
920
|
+
delete base.artifactConstructor;
|
|
921
|
+
return base;
|
|
923
922
|
}
|
|
924
923
|
/**
|
|
925
|
-
* Reconstruct
|
|
924
|
+
* Reconstruct an {@link ArtifactTool} from an {@link ArtifactTool.[ENCODE_METHOD]} snapshot.
|
|
926
925
|
*
|
|
927
|
-
* @param data - The snapshot produced by {@link
|
|
928
|
-
* @returns A
|
|
926
|
+
* @param data - The snapshot produced by {@link ArtifactTool.[ENCODE_METHOD]}.
|
|
927
|
+
* @returns A fully-validated {@link ArtifactTool}.
|
|
929
928
|
*/
|
|
930
929
|
static [require_tokenizable.DECODE_METHOD](data) {
|
|
931
930
|
const snapshot = data;
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
931
|
+
return new ArtifactTool({
|
|
932
|
+
...snapshot,
|
|
933
|
+
inputSchema: (0, _nhtio_validation.decode)(snapshot.inputSchema)
|
|
934
|
+
});
|
|
935
935
|
}
|
|
936
936
|
};
|
|
937
937
|
//#endregion
|
|
@@ -1727,4 +1727,4 @@ Object.defineProperty(exports, "resolveSpoolReader", {
|
|
|
1727
1727
|
}
|
|
1728
1728
|
});
|
|
1729
1729
|
|
|
1730
|
-
//# sourceMappingURL=spooled_artifact-
|
|
1730
|
+
//# sourceMappingURL=spooled_artifact-CFjf6ULg.cjs.map
|