@nhtio/adk 1.20260604.0 → 1.20260607.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 +261 -0
- package/adk-mcp.mjs +1 -1
- package/batteries/embeddings/openai/adapter.cjs +1 -1
- package/batteries/embeddings/openai/adapter.mjs +1 -1
- package/batteries/embeddings/webllm/adapter.cjs +1 -1
- package/batteries/embeddings/webllm/adapter.mjs +1 -1
- package/batteries/index.d.ts +1 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs +6 -6
- package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/adapter.mjs +6 -6
- package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/helpers.cjs +2 -2
- package/batteries/llm/openai_chat_completions/helpers.mjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.cjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/validation.mjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.cjs +6 -6
- package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.mjs +6 -6
- package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/validation.cjs +2 -2
- package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -1
- package/batteries/llm/webllm_chat_completions/validation.mjs +2 -2
- package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -1
- package/batteries/storage/flydrive.cjs +1 -1
- package/batteries/storage/flydrive.mjs +2 -2
- package/batteries/storage/in_memory.cjs +1 -1
- package/batteries/storage/in_memory.mjs +1 -1
- package/batteries/storage/opfs.cjs +1 -1
- package/batteries/storage/opfs.mjs +1 -1
- package/batteries/tools/color.cjs +2 -2
- package/batteries/tools/color.mjs +2 -2
- package/batteries/tools/comparison.cjs +3 -3
- package/batteries/tools/comparison.mjs +3 -3
- package/batteries/tools/data_structure.cjs +3 -3
- package/batteries/tools/data_structure.mjs +3 -3
- package/batteries/tools/datetime_extended.cjs +2 -2
- package/batteries/tools/datetime_extended.mjs +2 -2
- package/batteries/tools/datetime_math.cjs +2 -2
- package/batteries/tools/datetime_math.mjs +2 -2
- package/batteries/tools/encoding.cjs +3 -3
- package/batteries/tools/encoding.mjs +3 -3
- package/batteries/tools/formatting.cjs +3 -3
- package/batteries/tools/formatting.mjs +3 -3
- package/batteries/tools/geo_basics.cjs +2 -2
- package/batteries/tools/geo_basics.mjs +2 -2
- package/batteries/tools/math/index.d.ts +16 -5
- package/batteries/tools/math.cjs +340 -22
- package/batteries/tools/math.cjs.map +1 -1
- package/batteries/tools/math.mjs +338 -21
- package/batteries/tools/math.mjs.map +1 -1
- package/batteries/tools/memory.cjs +5 -5
- package/batteries/tools/memory.mjs +5 -5
- package/batteries/tools/parsing.cjs +4 -4
- package/batteries/tools/parsing.mjs +4 -4
- package/batteries/tools/retrievables.cjs +4 -4
- package/batteries/tools/retrievables.mjs +4 -4
- package/batteries/tools/standing_instructions.cjs +4 -4
- package/batteries/tools/standing_instructions.mjs +4 -4
- package/batteries/tools/statistics.cjs +4 -4
- package/batteries/tools/statistics.mjs +4 -4
- package/batteries/tools/string_processing.cjs +3 -3
- package/batteries/tools/string_processing.mjs +3 -3
- package/batteries/tools/structured_data.cjs +3 -3
- package/batteries/tools/structured_data.mjs +3 -3
- package/batteries/tools/text_analysis.cjs +3 -3
- package/batteries/tools/text_analysis.mjs +3 -3
- package/batteries/tools/text_comparison.cjs +2 -2
- package/batteries/tools/text_comparison.mjs +2 -2
- package/batteries/tools/time.cjs +2 -2
- package/batteries/tools/time.mjs +2 -2
- package/batteries/tools/unit_conversion.cjs +2 -2
- package/batteries/tools/unit_conversion.mjs +2 -2
- package/batteries/vector/arangodb/index.d.ts +38 -0
- package/batteries/vector/arangodb.cjs +257 -0
- package/batteries/vector/arangodb.cjs.map +1 -0
- package/batteries/vector/arangodb.mjs +255 -0
- package/batteries/vector/arangodb.mjs.map +1 -0
- package/batteries/vector/builder.cjs +297 -0
- package/batteries/vector/builder.cjs.map +1 -0
- package/batteries/vector/builder.d.ts +87 -0
- package/batteries/vector/builder.mjs +294 -0
- package/batteries/vector/builder.mjs.map +1 -0
- package/batteries/vector/chroma/index.d.ts +32 -0
- package/batteries/vector/chroma.cjs +305 -0
- package/batteries/vector/chroma.cjs.map +1 -0
- package/batteries/vector/chroma.mjs +302 -0
- package/batteries/vector/chroma.mjs.map +1 -0
- package/batteries/vector/clickhouse/index.d.ts +39 -0
- package/batteries/vector/clickhouse.cjs +246 -0
- package/batteries/vector/clickhouse.cjs.map +1 -0
- package/batteries/vector/clickhouse.mjs +244 -0
- package/batteries/vector/clickhouse.mjs.map +1 -0
- package/batteries/vector/cloudflare/index.d.ts +43 -0
- package/batteries/vector/cloudflare.cjs +397 -0
- package/batteries/vector/cloudflare.cjs.map +1 -0
- package/batteries/vector/cloudflare.mjs +395 -0
- package/batteries/vector/cloudflare.mjs.map +1 -0
- package/batteries/vector/conformance/index.d.ts +15 -0
- package/batteries/vector/conformance.cjs +209 -0
- package/batteries/vector/conformance.cjs.map +1 -0
- package/batteries/vector/conformance.mjs +205 -0
- package/batteries/vector/conformance.mjs.map +1 -0
- package/batteries/vector/contract.cjs +42 -0
- package/batteries/vector/contract.cjs.map +1 -0
- package/batteries/vector/contract.d.ts +39 -0
- package/batteries/vector/contract.mjs +40 -0
- package/batteries/vector/contract.mjs.map +1 -0
- package/batteries/vector/couchbase/index.d.ts +49 -0
- package/batteries/vector/couchbase.cjs +401 -0
- package/batteries/vector/couchbase.cjs.map +1 -0
- package/batteries/vector/couchbase.mjs +399 -0
- package/batteries/vector/couchbase.mjs.map +1 -0
- package/batteries/vector/duckdb/index.d.ts +33 -0
- package/batteries/vector/duckdb.cjs +218 -0
- package/batteries/vector/duckdb.cjs.map +1 -0
- package/batteries/vector/duckdb.mjs +216 -0
- package/batteries/vector/duckdb.mjs.map +1 -0
- package/batteries/vector/elasticsearch/index.d.ts +43 -0
- package/batteries/vector/elasticsearch.cjs +306 -0
- package/batteries/vector/elasticsearch.cjs.map +1 -0
- package/batteries/vector/elasticsearch.mjs +303 -0
- package/batteries/vector/elasticsearch.mjs.map +1 -0
- package/batteries/vector/exceptions.cjs +126 -0
- package/batteries/vector/exceptions.cjs.map +1 -0
- package/batteries/vector/exceptions.d.ts +142 -0
- package/batteries/vector/exceptions.mjs +107 -0
- package/batteries/vector/exceptions.mjs.map +1 -0
- package/batteries/vector/factory.cjs +28 -0
- package/batteries/vector/factory.cjs.map +1 -0
- package/batteries/vector/factory.d.ts +38 -0
- package/batteries/vector/factory.mjs +25 -0
- package/batteries/vector/factory.mjs.map +1 -0
- package/batteries/vector/filters.cjs +107 -0
- package/batteries/vector/filters.cjs.map +1 -0
- package/batteries/vector/filters.d.ts +34 -0
- package/batteries/vector/filters.mjs +99 -0
- package/batteries/vector/filters.mjs.map +1 -0
- package/batteries/vector/helpers.cjs +23 -0
- package/batteries/vector/helpers.cjs.map +1 -0
- package/batteries/vector/helpers.d.ts +12 -0
- package/batteries/vector/helpers.mjs +17 -0
- package/batteries/vector/helpers.mjs.map +1 -0
- package/batteries/vector/hnswlib/index.d.ts +35 -0
- package/batteries/vector/hnswlib.cjs +237 -0
- package/batteries/vector/hnswlib.cjs.map +1 -0
- package/batteries/vector/hnswlib.mjs +235 -0
- package/batteries/vector/hnswlib.mjs.map +1 -0
- package/batteries/vector/in_memory/index.d.ts +23 -0
- package/batteries/vector/in_memory.cjs +178 -0
- package/batteries/vector/in_memory.cjs.map +1 -0
- package/batteries/vector/in_memory.mjs +176 -0
- package/batteries/vector/in_memory.mjs.map +1 -0
- package/batteries/vector/index.d.ts +18 -0
- package/batteries/vector/lancedb/index.d.ts +34 -0
- package/batteries/vector/lancedb.cjs +224 -0
- package/batteries/vector/lancedb.cjs.map +1 -0
- package/batteries/vector/lancedb.mjs +222 -0
- package/batteries/vector/lancedb.mjs.map +1 -0
- package/batteries/vector/mariadb/index.d.ts +39 -0
- package/batteries/vector/mariadb.cjs +228 -0
- package/batteries/vector/mariadb.cjs.map +1 -0
- package/batteries/vector/mariadb.mjs +226 -0
- package/batteries/vector/mariadb.mjs.map +1 -0
- package/batteries/vector/meilisearch/index.d.ts +36 -0
- package/batteries/vector/meilisearch.cjs +242 -0
- package/batteries/vector/meilisearch.cjs.map +1 -0
- package/batteries/vector/meilisearch.mjs +240 -0
- package/batteries/vector/meilisearch.mjs.map +1 -0
- package/batteries/vector/migrate.cjs +54 -0
- package/batteries/vector/migrate.cjs.map +1 -0
- package/batteries/vector/migrate.d.ts +30 -0
- package/batteries/vector/migrate.mjs +52 -0
- package/batteries/vector/migrate.mjs.map +1 -0
- package/batteries/vector/milvus/index.d.ts +35 -0
- package/batteries/vector/milvus.cjs +357 -0
- package/batteries/vector/milvus.cjs.map +1 -0
- package/batteries/vector/milvus.mjs +354 -0
- package/batteries/vector/milvus.mjs.map +1 -0
- package/batteries/vector/mongodb/index.d.ts +46 -0
- package/batteries/vector/mongodb.cjs +270 -0
- package/batteries/vector/mongodb.cjs.map +1 -0
- package/batteries/vector/mongodb.mjs +268 -0
- package/batteries/vector/mongodb.mjs.map +1 -0
- package/batteries/vector/neo4j/index.d.ts +38 -0
- package/batteries/vector/neo4j.cjs +231 -0
- package/batteries/vector/neo4j.cjs.map +1 -0
- package/batteries/vector/neo4j.mjs +229 -0
- package/batteries/vector/neo4j.mjs.map +1 -0
- package/batteries/vector/opensearch/index.d.ts +46 -0
- package/batteries/vector/opensearch.cjs +316 -0
- package/batteries/vector/opensearch.cjs.map +1 -0
- package/batteries/vector/opensearch.mjs +313 -0
- package/batteries/vector/opensearch.mjs.map +1 -0
- package/batteries/vector/oracle23ai/index.d.ts +45 -0
- package/batteries/vector/oracle23ai.cjs +340 -0
- package/batteries/vector/oracle23ai.cjs.map +1 -0
- package/batteries/vector/oracle23ai.mjs +338 -0
- package/batteries/vector/oracle23ai.mjs.map +1 -0
- package/batteries/vector/orama/index.d.ts +23 -0
- package/batteries/vector/orama.cjs +272 -0
- package/batteries/vector/orama.cjs.map +1 -0
- package/batteries/vector/orama.mjs +270 -0
- package/batteries/vector/orama.mjs.map +1 -0
- package/batteries/vector/pgvector/index.d.ts +43 -0
- package/batteries/vector/pgvector.cjs +411 -0
- package/batteries/vector/pgvector.cjs.map +1 -0
- package/batteries/vector/pgvector.mjs +408 -0
- package/batteries/vector/pgvector.mjs.map +1 -0
- package/batteries/vector/pinecone/index.d.ts +38 -0
- package/batteries/vector/pinecone.cjs +415 -0
- package/batteries/vector/pinecone.cjs.map +1 -0
- package/batteries/vector/pinecone.mjs +412 -0
- package/batteries/vector/pinecone.mjs.map +1 -0
- package/batteries/vector/plan.cjs +2 -0
- package/batteries/vector/plan.d.ts +65 -0
- package/batteries/vector/plan.mjs +0 -0
- package/batteries/vector/qdrant/index.d.ts +34 -0
- package/batteries/vector/qdrant.cjs +286 -0
- package/batteries/vector/qdrant.cjs.map +1 -0
- package/batteries/vector/qdrant.mjs +284 -0
- package/batteries/vector/qdrant.mjs.map +1 -0
- package/batteries/vector/redis/index.d.ts +44 -0
- package/batteries/vector/redis.cjs +391 -0
- package/batteries/vector/redis.cjs.map +1 -0
- package/batteries/vector/redis.mjs +388 -0
- package/batteries/vector/redis.mjs.map +1 -0
- package/batteries/vector/retrievable.cjs +69 -0
- package/batteries/vector/retrievable.cjs.map +1 -0
- package/batteries/vector/retrievable.mjs +67 -0
- package/batteries/vector/retrievable.mjs.map +1 -0
- package/batteries/vector/retrievable_glue.d.ts +24 -0
- package/batteries/vector/s3vectors/index.d.ts +52 -0
- package/batteries/vector/s3vectors.cjs +438 -0
- package/batteries/vector/s3vectors.cjs.map +1 -0
- package/batteries/vector/s3vectors.mjs +436 -0
- package/batteries/vector/s3vectors.mjs.map +1 -0
- package/batteries/vector/schema.cjs +96 -0
- package/batteries/vector/schema.cjs.map +1 -0
- package/batteries/vector/schema.d.ts +40 -0
- package/batteries/vector/schema.mjs +93 -0
- package/batteries/vector/schema.mjs.map +1 -0
- package/batteries/vector/solr/index.d.ts +36 -0
- package/batteries/vector/solr.cjs +230 -0
- package/batteries/vector/solr.cjs.map +1 -0
- package/batteries/vector/solr.mjs +228 -0
- package/batteries/vector/solr.mjs.map +1 -0
- package/batteries/vector/sqlite_vec/index.d.ts +30 -0
- package/batteries/vector/sqlite_vec.cjs +318 -0
- package/batteries/vector/sqlite_vec.cjs.map +1 -0
- package/batteries/vector/sqlite_vec.mjs +316 -0
- package/batteries/vector/sqlite_vec.mjs.map +1 -0
- package/batteries/vector/surrealdb/index.d.ts +37 -0
- package/batteries/vector/surrealdb.cjs +230 -0
- package/batteries/vector/surrealdb.cjs.map +1 -0
- package/batteries/vector/surrealdb.mjs +228 -0
- package/batteries/vector/surrealdb.mjs.map +1 -0
- package/batteries/vector/types.cjs +2 -0
- package/batteries/vector/types.d.ts +100 -0
- package/batteries/vector/types.mjs +0 -0
- package/batteries/vector/typesense/index.d.ts +38 -0
- package/batteries/vector/typesense.cjs +272 -0
- package/batteries/vector/typesense.cjs.map +1 -0
- package/batteries/vector/typesense.mjs +270 -0
- package/batteries/vector/typesense.mjs.map +1 -0
- package/batteries/vector/validation.cjs +90 -0
- package/batteries/vector/validation.cjs.map +1 -0
- package/batteries/vector/validation.d.ts +18 -0
- package/batteries/vector/validation.mjs +83 -0
- package/batteries/vector/validation.mjs.map +1 -0
- package/batteries/vector/vector_store_constructor.cjs +56 -0
- package/batteries/vector/vector_store_constructor.cjs.map +1 -0
- package/batteries/vector/vector_store_constructor.d.ts +30 -0
- package/batteries/vector/vector_store_constructor.mjs +53 -0
- package/batteries/vector/vector_store_constructor.mjs.map +1 -0
- package/batteries/vector/vespa/index.d.ts +39 -0
- package/batteries/vector/vespa.cjs +423 -0
- package/batteries/vector/vespa.cjs.map +1 -0
- package/batteries/vector/vespa.mjs +421 -0
- package/batteries/vector/vespa.mjs.map +1 -0
- package/batteries/vector/weaviate/index.d.ts +57 -0
- package/batteries/vector/weaviate.cjs +325 -0
- package/batteries/vector/weaviate.cjs.map +1 -0
- package/batteries/vector/weaviate.mjs +322 -0
- package/batteries/vector/weaviate.mjs.map +1 -0
- package/batteries/vector.cjs +63 -0
- package/batteries/vector.mjs +14 -0
- package/batteries.cjs +62 -0
- package/batteries.mjs +15 -1
- package/{chunk-kRvK8_k2.mjs → chunk-Bpcn9VDT.mjs} +5 -1
- package/{common-lMrnzoyn.mjs → common-BT0nfCi9.mjs} +8 -8
- package/{common-lMrnzoyn.mjs.map → common-BT0nfCi9.mjs.map} +1 -1
- package/{common-D_e5zYsG.js → common-Cj8TaQ9U.js} +8 -8
- package/{common-D_e5zYsG.js.map → common-Cj8TaQ9U.js.map} +1 -1
- package/common.cjs +7 -7
- package/common.mjs +7 -7
- package/{dispatch_runner-CpuyATj1.js → dispatch_runner-BHBNupqp.js} +2 -2
- package/dispatch_runner-BHBNupqp.js.map +1 -0
- package/{dispatch_runner-CDF3X0nv.mjs → dispatch_runner-DPcS7Y_M.mjs} +2 -2
- package/dispatch_runner-DPcS7Y_M.mjs.map +1 -0
- package/dispatch_runner.cjs +1 -1
- package/dispatch_runner.mjs +1 -1
- package/forge.cjs +4 -4
- package/forge.mjs +4 -4
- package/guards.cjs +8 -8
- package/guards.mjs +8 -8
- package/index.cjs +12 -12
- package/index.mjs +12 -12
- package/lib/classes/tool_registry.d.ts +70 -4
- package/mcp/adk-docs-corpus.json +1 -1
- package/package.json +424 -88
- package/skills/adk-assembly/SKILL.md +2 -2
- package/{spooled_artifact-B8gIIn9h.js → spooled_artifact-BTq6Nzfy.js} +4 -4
- package/spooled_artifact-BTq6Nzfy.js.map +1 -0
- package/{spooled_artifact-CWoKUDEm.mjs → spooled_artifact-CHoZgWwI.mjs} +4 -4
- package/spooled_artifact-CHoZgWwI.mjs.map +1 -0
- package/spooled_artifact.cjs +2 -2
- package/spooled_artifact.mjs +2 -2
- package/{spooled_markdown_artifact-DQX0RCdI.js → spooled_markdown_artifact-CALSDxIx.js} +3 -3
- package/{spooled_markdown_artifact-DQX0RCdI.js.map → spooled_markdown_artifact-CALSDxIx.js.map} +1 -1
- package/{spooled_markdown_artifact-CNle4jXN.mjs → spooled_markdown_artifact-Ci5UL7l4.mjs} +3 -3
- package/{spooled_markdown_artifact-CNle4jXN.mjs.map → spooled_markdown_artifact-Ci5UL7l4.mjs.map} +1 -1
- package/src/types/evaluatex.d.ts +31 -0
- package/{thought-BD6AkkOr.js → thought-BbwhJ1wb.js} +4 -4
- package/thought-BbwhJ1wb.js.map +1 -0
- package/{thought-B_P8LiB6.mjs → thought-D34QQZZ9.mjs} +4 -4
- package/thought-D34QQZZ9.mjs.map +1 -0
- package/{tool-CRZSUcdP.mjs → tool-CMhaDRNd.mjs} +3 -3
- package/tool-CMhaDRNd.mjs.map +1 -0
- package/{tool-CX9vNHAw.js → tool-CVyZkFC7.js} +3 -3
- package/tool-CVyZkFC7.js.map +1 -0
- package/{tool_call-BUeMuCc6.mjs → tool_call-CV5qVNlb.mjs} +3 -3
- package/{tool_call-BUeMuCc6.mjs.map → tool_call-CV5qVNlb.mjs.map} +1 -1
- package/{tool_call--7ti-frB.js → tool_call-Db68hB7y.js} +3 -3
- package/{tool_call--7ti-frB.js.map → tool_call-Db68hB7y.js.map} +1 -1
- package/{tool_registry-BGHg6KTq.mjs → tool_registry-D1pSSlsd.mjs} +109 -22
- package/tool_registry-D1pSSlsd.mjs.map +1 -0
- package/{tool_registry-CtCQ4Xoz.js → tool_registry-DYUYqXvo.js} +109 -22
- package/tool_registry-DYUYqXvo.js.map +1 -0
- package/{turn_runner-BJTtAORU.js → turn_runner-DqWHNP80.js} +5 -5
- package/turn_runner-DqWHNP80.js.map +1 -0
- package/{turn_runner-C02LZHjt.mjs → turn_runner-fg1Wc3dK.mjs} +5 -5
- package/turn_runner-fg1Wc3dK.mjs.map +1 -0
- package/turn_runner.cjs +1 -1
- package/turn_runner.mjs +1 -1
- package/dispatch_runner-CDF3X0nv.mjs.map +0 -1
- package/dispatch_runner-CpuyATj1.js.map +0 -1
- package/spooled_artifact-B8gIIn9h.js.map +0 -1
- package/spooled_artifact-CWoKUDEm.mjs.map +0 -1
- package/thought-BD6AkkOr.js.map +0 -1
- package/thought-B_P8LiB6.mjs.map +0 -1
- package/tool-CRZSUcdP.mjs.map +0 -1
- package/tool-CX9vNHAw.js.map +0 -1
- package/tool_registry-BGHg6KTq.mjs.map +0 -1
- package/tool_registry-CtCQ4Xoz.js.map +0 -1
- package/turn_runner-BJTtAORU.js.map +0 -1
- package/turn_runner-C02LZHjt.mjs.map +0 -1
package/thought-BD6AkkOr.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"thought-BD6AkkOr.js","names":["#identifier","#representation","#id","#content","#confidence","#importance","#createdAt","#updatedAt","#id","#role","#content","#attachments","#identity","#createdAt","#updatedAt","#id","#content","#identity","#payload","#replayCompatibility","#createdAt","#updatedAt"],"sources":["../src/lib/classes/identity.ts","../src/lib/classes/memory.ts","../src/lib/classes/message.ts","../src/lib/classes/thought.ts"],"sourcesContent":["import { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_IDENTITY_VALUE } from '../exceptions/runtime'\n\n/**\n * Plain input object supplied to {@link Identity} at construction time.\n *\n * @remarks\n * Validated against `rawIdentitySchema` before the `Identity` instance is created.\n */\nexport interface RawIdentity {\n /**\n * The system-facing identifier for this participant.\n *\n * @remarks\n * Used internally to correlate messages to a specific participant — e.g. a database ID or\n * a username. Never sent to the model directly; use `representation` for that.\n */\n identifier: string | number\n /**\n * How this participant should be presented to the model.\n *\n * @remarks\n * Accepts a plain string or an existing {@link @nhtio/adk!Tokenizable} instance. This is what the model\n * sees when it needs to distinguish between participants of the same role.\n */\n representation: string | Tokenizable\n}\n\n/**\n * A fully-resolved {@link RawIdentity} where `representation` has been normalised to a\n * {@link @nhtio/adk!Tokenizable} instance.\n *\n * @remarks\n * Used internally by the {@link Identity} constructor to assign private fields with\n * guaranteed types.\n */\ninterface ResolvedIdentity {\n identifier: string | number\n representation: Tokenizable\n}\n\n/**\n * Validator schema used to validate a {@link RawIdentity} before constructing an {@link Identity}.\n *\n * @remarks\n * Validates both fields of {@link RawIdentity}:\n * - `identifier` — required string or number.\n * - `representation` — required string or {@link @nhtio/adk!Tokenizable}, via {@link @nhtio/adk!Tokenizable.schema}.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_IDENTITY_VALUE} (via the {@link Identity} constructor) when\n * validation fails.\n */\nconst rawIdentitySchema = validator.object<RawIdentity>({\n identifier: validator.alternatives(validator.string(), validator.number()).required(),\n representation: Tokenizable.schema.required(),\n})\n\n/**\n * An immutable, validated participant identity attached to a {@link @nhtio/adk!Message}.\n *\n * @remarks\n * Carries two distinct representations of the same participant: `identifier` is the\n * system-facing key (e.g. a database ID) used to correlate messages programmatically;\n * `representation` is what the model sees when it needs to distinguish between participants\n * sharing the same role. The `representation` is always a {@link @nhtio/adk!Tokenizable} so token cost\n * can be estimated inline.\n */\nexport class Identity {\n /**\n * Validator schema that accepts a {@link RawIdentity} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest an identity — for example,\n * as a required field inside a message schema.\n */\n public static schema = rawIdentitySchema\n\n /**\n * Returns `true` if `value` is an {@link Identity} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is an {@link Identity} instance.\n */\n public static isIdentity(value: unknown): value is Identity {\n return isInstanceOf(value, 'Identity', Identity)\n }\n\n /**\n * The system-facing identifier for this participant — never sent to the model directly.\n */\n declare readonly identifier: string | number\n\n /**\n * How this participant is presented to the model, as a {@link @nhtio/adk!Tokenizable} for inline\n * token estimation.\n */\n declare readonly representation: Tokenizable\n\n #identifier: string | number\n #representation: Tokenizable\n\n /**\n * @param raw - The raw identity input validated against `rawIdentitySchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_IDENTITY_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawIdentity) {\n let resolved: ResolvedIdentity\n try {\n resolved = validateOrThrow<ResolvedIdentity>(rawIdentitySchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_IDENTITY_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#identifier = resolved.identifier\n this.#representation = Tokenizable.isTokenizable(resolved.representation)\n ? resolved.representation\n : new Tokenizable(resolved.representation)\n\n Object.defineProperties(this, {\n identifier: {\n get: () => this.#identifier,\n enumerable: true,\n configurable: false,\n },\n representation: {\n get: () => this.#representation,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n","import { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_MEMORY_VALUE } from '../exceptions/runtime'\nimport type { DateTime } from 'luxon'\n\n/**\n * Plain input object supplied to {@link Memory} at construction time.\n *\n * @remarks\n * Validated against `rawMemorySchema` before the `Memory` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n */\nexport interface RawMemory {\n /** Stable unique identifier for this memory entry. */\n id: string\n /** The memory content as a plain string or an existing {@link @nhtio/adk!Tokenizable} instance. */\n content: string | Tokenizable\n /** Confidence score in the range `[0, 1]` — how certain the agent is that this memory is accurate. */\n confidence: number\n /** Importance score in the range `[0, 1]` — how much weight this memory should carry during retrieval. */\n importance: number\n /** When this memory was first recorded. */\n createdAt: string | number | Date | DateTime\n /** When this memory was last modified. */\n updatedAt: string | number | Date | DateTime\n}\n\n/**\n * A fully-resolved {@link RawMemory} where all fields have been validated and temporal values\n * normalised to Luxon `DateTime` instances.\n *\n * @remarks\n * This is the shape returned by `rawMemorySchema` after validation — used internally by the\n * {@link Memory} constructor to assign private fields with guaranteed types.\n */\ninterface ResolvedMemory {\n id: string\n content: Tokenizable\n confidence: number\n importance: number\n createdAt: DateTime\n updatedAt: DateTime\n}\n\n/**\n * Validator schema used to validate a {@link RawMemory} before constructing a {@link Memory}.\n *\n * @remarks\n * Validates all six fields of {@link RawMemory}:\n * - `id` — required non-empty string.\n * - `content` — required string or {@link @nhtio/adk!Tokenizable}, via {@link @nhtio/adk!Tokenizable.schema}.\n * - `confidence` — required number in `[0, 1]`.\n * - `importance` — required number in `[0, 1]`.\n * - `createdAt` / `updatedAt` — required datetime-parseable values, normalised to `DateTime`.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_MEMORY_VALUE} (via the {@link Memory} constructor) when\n * validation fails.\n */\nconst rawMemorySchema = validator.object<RawMemory>({\n id: validator.string().required(),\n content: Tokenizable.schema.required(),\n confidence: validator.number().min(0).max(1).required(),\n importance: validator.number().min(0).max(1).required(),\n createdAt: validator.datetime().required(),\n updatedAt: validator.datetime().required(),\n})\n\n/**\n * An immutable, validated memory entry held by the agent.\n *\n * @remarks\n * Constructed from a {@link RawMemory} via `rawMemorySchema`. All temporal fields are\n * normalised to Luxon `DateTime` instances at construction time. The `content` field is\n * always a {@link @nhtio/adk!Tokenizable} so callers can estimate token cost without an additional\n * wrapping step.\n */\nexport class Memory {\n /**\n * Validator schema that accepts a {@link RawMemory} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a memory entry — for\n * example, a collection schema that holds an array of memories.\n */\n public static schema = rawMemorySchema\n\n /**\n * Returns `true` if `value` is a {@link Memory} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Memory} instance.\n */\n public static isMemory(value: unknown): value is Memory {\n return isInstanceOf(value, 'Memory', Memory)\n }\n /** Stable unique identifier for this memory entry. */\n declare readonly id: string\n /** The memory content as a {@link @nhtio/adk!Tokenizable} for inline token estimation. */\n declare readonly content: Tokenizable\n /** Confidence score in the range `[0, 1]`. */\n declare readonly confidence: number\n /** Importance score in the range `[0, 1]`. */\n declare readonly importance: number\n /** When this memory was first recorded. */\n declare readonly createdAt: DateTime\n /** When this memory was last modified. */\n declare readonly updatedAt: DateTime\n\n #id: string\n #content: Tokenizable\n #confidence: number\n #importance: number\n #createdAt: DateTime\n #updatedAt: DateTime\n\n /**\n * @param raw - The raw memory input validated against `rawMemorySchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_MEMORY_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawMemory) {\n let resolved: ResolvedMemory\n try {\n resolved = validateOrThrow<ResolvedMemory>(rawMemorySchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_MEMORY_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#id = resolved.id\n this.#content = Tokenizable.isTokenizable(resolved.content)\n ? resolved.content\n : new Tokenizable(resolved.content)\n this.#confidence = resolved.confidence\n this.#importance = resolved.importance\n this.#createdAt = resolved.createdAt\n this.#updatedAt = resolved.updatedAt\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n content: {\n get: () => this.#content,\n enumerable: true,\n configurable: false,\n },\n confidence: {\n get: () => this.#confidence,\n enumerable: true,\n configurable: false,\n },\n importance: {\n get: () => this.#importance,\n enumerable: true,\n configurable: false,\n },\n createdAt: {\n get: () => this.#createdAt,\n enumerable: true,\n configurable: false,\n },\n updatedAt: {\n get: () => this.#updatedAt,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n","import { Media } from './media'\nimport { Identity } from './identity'\nimport { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_MESSAGE_VALUE } from '../exceptions/runtime'\nimport type { DateTime } from 'luxon'\nimport type { RawIdentity } from './identity'\n\n/**\n * The roles a {@link Message} author can hold.\n *\n * @remarks\n * Restricted to `user` and `assistant` — system instructions, developer directives, and\n * tool results are handled separately and never appear in the persisted message history.\n */\nexport type MessageRole = 'user' | 'assistant'\n\n/**\n * Plain input object supplied to {@link Message} at construction time.\n *\n * @remarks\n * Validated against `rawMessageSchema` before the `Message` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n *\n * At least one of `content` or `attachments` (non-empty) must be present — a message with\n * neither throws {@link @nhtio/adk!E_INVALID_INITIAL_MESSAGE_VALUE}.\n */\nexport interface RawMessage {\n /** Stable unique identifier for this message. */\n id: string\n /** Whether this message is from the human participant or the model. */\n role: MessageRole\n /**\n * The message content as a plain string or an existing {@link @nhtio/adk!Tokenizable} instance.\n *\n * @remarks\n * Optional — but required when `attachments` is absent or empty. The cross-field rule on\n * `rawMessageSchema` enforces that at least one of `content` or `attachments` is present.\n */\n content?: string | Tokenizable\n /**\n * Media attachments carried by this message — images, audio, video, documents.\n *\n * @remarks\n * Optional and symmetric across roles: both `user` and `assistant` messages may carry\n * attachments. Each attachment carries its own `trustTier` and `modalityHazard`, which the\n * renderer uses to wrap the asset in its own trust envelope independent of the message\n * envelope. How a renderer orders text vs attachments in the on-the-wire content array is\n * a renderer-policy concern, not a contract of {@link Message}.\n */\n attachments?: Media[]\n /**\n * The identity of the participant who authored this message.\n *\n * @remarks\n * Optional. When omitted, the `role` value is used as both the system-facing `identifier`\n * and the model-facing `representation`. Three accepted forms when provided:\n * - A plain `string` — used as both `identifier` and `representation`.\n * - A {@link @nhtio/adk!RawIdentity} object — validated and wrapped into an {@link @nhtio/adk!Identity}.\n * - An existing {@link @nhtio/adk!Identity} instance — passed through unchanged.\n */\n identity?: string | RawIdentity | Identity\n /** When this message was created. */\n createdAt: string | number | Date | DateTime\n /** When this message was last modified. */\n updatedAt: string | number | Date | DateTime\n}\n\n/**\n * A fully-resolved {@link RawMessage} where temporal fields have been normalised to Luxon\n * `DateTime` instances and `identity` is a validated {@link @nhtio/adk!Identity}.\n *\n * @remarks\n * Used internally by the {@link Message} constructor to assign private fields with\n * guaranteed types.\n */\ninterface ResolvedMessage {\n id: string\n role: MessageRole\n content?: Tokenizable\n attachments: Media[]\n identity: string | RawIdentity | Identity\n createdAt: DateTime\n updatedAt: DateTime\n}\n\n/**\n * Validator schema used to validate a {@link RawMessage} before constructing a {@link Message}.\n *\n * @remarks\n * Validates all fields of {@link RawMessage}:\n * - `id` — required non-empty string.\n * - `role` — required; must be `'user'` or `'assistant'`.\n * - `content` — optional string or {@link @nhtio/adk!Tokenizable}, via {@link @nhtio/adk!Tokenizable.schema}.\n * - `attachments` — optional array of {@link @nhtio/adk!Media} instances. Defaults to `[]`.\n * - At least one of `content` or `attachments` must be present and non-empty; a message with\n * neither is invalid.\n * - `identity` — required string, {@link @nhtio/adk!RawIdentity}, or {@link @nhtio/adk!Identity}; a plain string is\n * mapped to both `identifier` and `representation` automatically.\n * - `createdAt` / `updatedAt` — required datetime-parseable values, normalised to `DateTime`.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_MESSAGE_VALUE} (via the {@link Message} constructor) when\n * validation fails.\n */\nconst rawMessageSchema = validator\n .object<RawMessage>({\n id: validator.string().required(),\n role: validator.string().valid('user', 'assistant').required(),\n content: Tokenizable.schema.optional(),\n attachments: validator\n .array()\n .items(\n validator.any().custom((value, helpers) => {\n if (Media.isMedia(value)) return value\n return helpers.error('any.invalid')\n })\n )\n .default([]),\n identity: validator\n .alternatives(validator.string(), Identity.schema)\n .default(validator.ref('role')),\n createdAt: validator.datetime().required(),\n updatedAt: validator.datetime().required(),\n })\n .custom((value, helpers) => {\n const resolved = value as ResolvedMessage\n const hasContent = resolved.content !== undefined && resolved.content !== null\n const hasAttachments = Array.isArray(resolved.attachments) && resolved.attachments.length > 0\n if (!hasContent && !hasAttachments) {\n return helpers.error('any.invalid')\n }\n return resolved\n })\n\n/**\n * An immutable, validated conversation message from a human participant or the model.\n *\n * @remarks\n * Covers only `user` and `assistant` roles — system instructions, developer directives, and\n * tool results are not represented here. Constructed from a {@link RawMessage} via\n * `rawMessageSchema`. Temporal fields are normalised to Luxon `DateTime` instances at\n * construction time. Both `content` and `identity.representation` are {@link @nhtio/adk!Tokenizable} so\n * token cost can be estimated inline.\n *\n * A message may carry `content` (text), `attachments` (media), or both. The cross-field rule\n * on `rawMessageSchema` enforces that at least one is present. Downstream code that reaches\n * for `message.content` must handle the attachments-only case where `content` is `undefined`.\n */\nexport class Message {\n /**\n * Validator schema that accepts a {@link RawMessage} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a message entry — for\n * example, a collection schema that holds an array of messages.\n */\n public static schema = rawMessageSchema\n\n /**\n * Returns `true` if `value` is a {@link Message} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Message} instance.\n */\n public static isMessage(value: unknown): value is Message {\n return isInstanceOf(value, 'Message', Message)\n }\n\n /** Stable unique identifier for this message. */\n declare readonly id: string\n /** Whether this message is from the human participant or the model. */\n declare readonly role: MessageRole\n /**\n * The message content as a {@link @nhtio/adk!Tokenizable} for inline token estimation, or `undefined`\n * for attachments-only messages.\n *\n * @remarks\n * `undefined` when the message was constructed with only `attachments`. Render code that\n * needs the text portion must guard for the missing case rather than blindly calling\n * `message.content.toString()`.\n */\n declare readonly content: Tokenizable | undefined\n /**\n * Media attachments carried by this message.\n *\n * @remarks\n * Always defined as a frozen array — empty when the message has no attachments. Both\n * `user` and `assistant` messages may carry attachments. Each entry carries its own\n * `trustTier` and `modalityHazard`; the renderer wraps each in its own trust envelope\n * independent of the message envelope.\n */\n declare readonly attachments: ReadonlyArray<Media>\n /** The identity of the participant who authored this message. */\n declare readonly identity: Identity\n /** When this message was created. */\n declare readonly createdAt: DateTime\n /** When this message was last modified. */\n declare readonly updatedAt: DateTime\n\n #id: string\n #role: MessageRole\n #content: Tokenizable | undefined\n #attachments: ReadonlyArray<Media>\n #identity: Identity\n #createdAt: DateTime\n #updatedAt: DateTime\n\n /**\n * @param raw - The raw message input validated against `rawMessageSchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_MESSAGE_VALUE} when `raw` does not satisfy the schema —\n * including the cross-field rule that at least one of `content` or `attachments` must be\n * present and non-empty.\n */\n constructor(raw: RawMessage) {\n let resolved: ResolvedMessage\n try {\n resolved = validateOrThrow<ResolvedMessage>(rawMessageSchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_MESSAGE_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#id = resolved.id\n this.#role = resolved.role\n this.#content =\n resolved.content === undefined || resolved.content === null\n ? undefined\n : Tokenizable.isTokenizable(resolved.content)\n ? resolved.content\n : new Tokenizable(resolved.content)\n this.#attachments = Object.freeze([...(resolved.attachments ?? [])])\n const rawIdentity = resolved.identity\n this.#identity = Identity.isIdentity(rawIdentity)\n ? rawIdentity\n : typeof rawIdentity === 'string'\n ? new Identity({ identifier: rawIdentity, representation: rawIdentity })\n : new Identity(rawIdentity)\n this.#createdAt = resolved.createdAt\n this.#updatedAt = resolved.updatedAt\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n role: {\n get: () => this.#role,\n enumerable: true,\n configurable: false,\n },\n content: {\n get: () => this.#content,\n enumerable: true,\n configurable: false,\n },\n attachments: {\n get: () => this.#attachments,\n enumerable: true,\n configurable: false,\n },\n identity: {\n get: () => this.#identity,\n enumerable: true,\n configurable: false,\n },\n createdAt: {\n get: () => this.#createdAt,\n enumerable: true,\n configurable: false,\n },\n updatedAt: {\n get: () => this.#updatedAt,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n","import { Identity } from './identity'\nimport { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_THOUGHT_VALUE } from '../exceptions/runtime'\nimport type { DateTime } from 'luxon'\nimport type { RawIdentity } from './identity'\n\n/**\n * Plain input object supplied to {@link Thought} at construction time.\n *\n * @remarks\n * Validated against `rawThoughtSchema` before the `Thought` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n */\nexport interface RawThought {\n /** Stable unique identifier for this thought. */\n id: string\n /** The reasoning content as a plain string or an existing {@link @nhtio/adk!Tokenizable} instance. */\n content: string | Tokenizable\n /**\n * The identity of the agent who produced this thought.\n *\n * @remarks\n * Required in multi-agent conversations to attribute reasoning traces to a specific agent.\n * Three accepted forms when provided:\n * - A plain `string` — used as both `identifier` and `representation`.\n * - A {@link @nhtio/adk!RawIdentity} object — validated and wrapped into an {@link @nhtio/adk!Identity}.\n * - An existing {@link @nhtio/adk!Identity} instance — passed through unchanged.\n *\n * When omitted, defaults to `'assistant'` (both `identifier` and `representation`).\n */\n identity?: string | RawIdentity | Identity\n /**\n * Optional vendor-opaque payload that round-trips back to a matching model wire.\n *\n * @remarks\n * Carries anything the ADK cannot interpret but a specific provider can — for example,\n * an Anthropic Messages thinking-block `signature`, an OpenAI Responses\n * `ResponseReasoningItem.encrypted_content` blob, a DeepSeek server-side reasoning handle,\n * or an MCP-mediated reasoning item.\n *\n * When present, an LLM battery MUST treat the thought as **opaque-mode**: do NOT inline\n * `content` through the plain `<thought>` envelope; serialise `payload` back to the wire in\n * whichever shape the matching {@link RawThought.replayCompatibility} identifier specifies.\n * The plain-text `content` is kept alongside for token-accounting and human/observer\n * inspection — it is not the thing the model sees.\n *\n * Cross-field invariant: a present `payload` REQUIRES a present {@link RawThought.replayCompatibility}.\n * A `payload` without `replayCompatibility` is malformed (the ADK has no way to know\n * which adapter can consume it) and {@link Thought.schema} rejects with\n * {@link @nhtio/adk!E_INVALID_INITIAL_THOUGHT_VALUE}.\n *\n * @defaultValue `undefined`\n */\n payload?: unknown\n /**\n * Optional free-form identifier describing which adapter wire-shape this thought can be\n * safely replayed into.\n *\n * @remarks\n * Examples (none of these are reserved by the ADK — they are consumer conventions):\n * - `'plain-text'` — replayable into every LLM battery\n * - `'anthropic-messages-thinking-v1'`\n * - `'openai-responses-reasoning-item-v1'`\n * - `'deepseek-reasoning-handle-v1'`\n *\n * LLM batteries declare via constructor option which tags they can safely replay; matching\n * opaque thoughts are routed to the wire's typed reasoning channel where it exists, or to a\n * documented side-channel key on the request body where the wire has none. Non-matching\n * opaque thoughts are elided from the current dispatch but NOT removed from\n * `ctx.turnThoughts` — they remain in context so a subsequent dispatch to a different\n * adapter that DOES declare the matching tag can pick them up.\n *\n * Plain-text thoughts (`payload === undefined` AND `replayCompatibility === undefined`, or\n * explicit `replayCompatibility: 'plain-text'`) are always replayable.\n *\n * A `replayCompatibility` without a `payload` is allowed — it documents intent (\"this\n * plain-text thought is only meaningful to a specific fine-tuned variant\") without\n * requiring an opaque blob.\n *\n * @defaultValue `undefined`\n */\n replayCompatibility?: string\n /** When this thought was recorded. */\n createdAt: string | number | Date | DateTime\n /** When this thought was last modified. */\n updatedAt: string | number | Date | DateTime\n}\n\n/**\n * A fully-resolved {@link RawThought} where temporal fields have been normalised to Luxon\n * `DateTime` instances.\n *\n * @remarks\n * Used internally by the {@link Thought} constructor to assign private fields with\n * guaranteed types.\n */\ninterface ResolvedThought {\n id: string\n content: Tokenizable\n identity: string | RawIdentity | Identity\n payload?: unknown\n replayCompatibility?: string\n createdAt: DateTime\n updatedAt: DateTime\n}\n\n/**\n * Validator schema used to validate a {@link RawThought} before constructing a {@link Thought}.\n *\n * @remarks\n * Validates all fields of {@link RawThought}:\n * - `id` — required non-empty string.\n * - `content` — required string or {@link @nhtio/adk!Tokenizable}, via {@link @nhtio/adk!Tokenizable.schema}.\n * - `identity` — optional string, {@link @nhtio/adk!RawIdentity}, or {@link @nhtio/adk!Identity}; defaults to\n * `'assistant'` when omitted.\n * - `createdAt` / `updatedAt` — required datetime-parseable values, normalised to `DateTime`.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_THOUGHT_VALUE} (via the {@link Thought} constructor) when\n * validation fails.\n */\nconst rawThoughtSchema = validator\n .object<RawThought>({\n id: validator.string().required(),\n content: Tokenizable.schema.required(),\n identity: validator.alternatives(validator.string(), Identity.schema).default('assistant'),\n payload: validator.any().optional(),\n replayCompatibility: validator.string().min(1).optional(),\n createdAt: validator.datetime().required(),\n updatedAt: validator.datetime().required(),\n })\n .custom((value, helpers) => {\n const v = value as RawThought\n if (\n v.payload !== undefined &&\n (v.replayCompatibility === undefined || v.replayCompatibility === null)\n ) {\n return helpers.error('any.invalid')\n }\n return value\n })\n\n/**\n * An immutable, validated internal reasoning trace produced by an agent.\n *\n * @remarks\n * Represents an agent's internal thinking — distinct from {@link @nhtio/adk!Message} (which is part of\n * the visible conversation) and never shown to end users directly. Carries an `identity` so\n * reasoning traces can be attributed to a specific agent in multi-agent conversations.\n * Constructed from a {@link RawThought} via `rawThoughtSchema`. The `content` field is always\n * a {@link @nhtio/adk!Tokenizable} so token cost can be estimated inline.\n */\nexport class Thought {\n /**\n * Validator schema that accepts a {@link RawThought} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a thought entry.\n */\n public static schema = rawThoughtSchema\n\n /**\n * Returns `true` if `value` is a {@link Thought} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Thought} instance.\n */\n public static isThought(value: unknown): value is Thought {\n return isInstanceOf(value, 'Thought', Thought)\n }\n\n /** Stable unique identifier for this thought. */\n declare readonly id: string\n /** The reasoning content as a {@link @nhtio/adk!Tokenizable} for inline token estimation. */\n declare readonly content: Tokenizable\n /** The identity of the agent who produced this thought. */\n declare readonly identity: Identity\n /**\n * Optional vendor-opaque payload that round-trips back to a matching model wire.\n * See {@link RawThought.payload}.\n */\n declare readonly payload: unknown\n /**\n * Optional wire-shape identifier describing which adapter can safely replay this thought.\n * See {@link RawThought.replayCompatibility}.\n */\n declare readonly replayCompatibility: string | undefined\n /** When this thought was recorded. */\n declare readonly createdAt: DateTime\n /** When this thought was last modified. */\n declare readonly updatedAt: DateTime\n\n #id: string\n #content: Tokenizable\n #identity: Identity\n #payload: unknown\n #replayCompatibility: string | undefined\n #createdAt: DateTime\n #updatedAt: DateTime\n\n /**\n * @param raw - The raw thought input validated against `rawThoughtSchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_THOUGHT_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawThought) {\n let resolved: ResolvedThought\n try {\n resolved = validateOrThrow<ResolvedThought>(rawThoughtSchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_THOUGHT_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#id = resolved.id\n this.#content = Tokenizable.isTokenizable(resolved.content)\n ? resolved.content\n : new Tokenizable(resolved.content)\n const rawIdentity = resolved.identity\n this.#identity = Identity.isIdentity(rawIdentity)\n ? rawIdentity\n : typeof rawIdentity === 'string'\n ? new Identity({ identifier: rawIdentity, representation: rawIdentity })\n : new Identity(rawIdentity)\n this.#payload = resolved.payload\n this.#replayCompatibility = resolved.replayCompatibility\n this.#createdAt = resolved.createdAt\n this.#updatedAt = resolved.updatedAt\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n content: {\n get: () => this.#content,\n enumerable: true,\n configurable: false,\n },\n identity: {\n get: () => this.#identity,\n enumerable: true,\n configurable: false,\n },\n payload: {\n get: () => this.#payload,\n enumerable: true,\n configurable: false,\n },\n replayCompatibility: {\n get: () => this.#replayCompatibility,\n enumerable: true,\n configurable: false,\n },\n createdAt: {\n get: () => this.#createdAt,\n enumerable: true,\n configurable: false,\n },\n updatedAt: {\n get: () => this.#updatedAt,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n"],"mappings":"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"}
|
package/thought-B_P8LiB6.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"thought-B_P8LiB6.mjs","names":["#identifier","#representation","#id","#content","#confidence","#importance","#createdAt","#updatedAt","#id","#role","#content","#attachments","#identity","#createdAt","#updatedAt","#id","#content","#identity","#payload","#replayCompatibility","#createdAt","#updatedAt"],"sources":["../src/lib/classes/identity.ts","../src/lib/classes/memory.ts","../src/lib/classes/message.ts","../src/lib/classes/thought.ts"],"sourcesContent":["import { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_IDENTITY_VALUE } from '../exceptions/runtime'\n\n/**\n * Plain input object supplied to {@link Identity} at construction time.\n *\n * @remarks\n * Validated against `rawIdentitySchema` before the `Identity` instance is created.\n */\nexport interface RawIdentity {\n /**\n * The system-facing identifier for this participant.\n *\n * @remarks\n * Used internally to correlate messages to a specific participant — e.g. a database ID or\n * a username. Never sent to the model directly; use `representation` for that.\n */\n identifier: string | number\n /**\n * How this participant should be presented to the model.\n *\n * @remarks\n * Accepts a plain string or an existing {@link @nhtio/adk!Tokenizable} instance. This is what the model\n * sees when it needs to distinguish between participants of the same role.\n */\n representation: string | Tokenizable\n}\n\n/**\n * A fully-resolved {@link RawIdentity} where `representation` has been normalised to a\n * {@link @nhtio/adk!Tokenizable} instance.\n *\n * @remarks\n * Used internally by the {@link Identity} constructor to assign private fields with\n * guaranteed types.\n */\ninterface ResolvedIdentity {\n identifier: string | number\n representation: Tokenizable\n}\n\n/**\n * Validator schema used to validate a {@link RawIdentity} before constructing an {@link Identity}.\n *\n * @remarks\n * Validates both fields of {@link RawIdentity}:\n * - `identifier` — required string or number.\n * - `representation` — required string or {@link @nhtio/adk!Tokenizable}, via {@link @nhtio/adk!Tokenizable.schema}.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_IDENTITY_VALUE} (via the {@link Identity} constructor) when\n * validation fails.\n */\nconst rawIdentitySchema = validator.object<RawIdentity>({\n identifier: validator.alternatives(validator.string(), validator.number()).required(),\n representation: Tokenizable.schema.required(),\n})\n\n/**\n * An immutable, validated participant identity attached to a {@link @nhtio/adk!Message}.\n *\n * @remarks\n * Carries two distinct representations of the same participant: `identifier` is the\n * system-facing key (e.g. a database ID) used to correlate messages programmatically;\n * `representation` is what the model sees when it needs to distinguish between participants\n * sharing the same role. The `representation` is always a {@link @nhtio/adk!Tokenizable} so token cost\n * can be estimated inline.\n */\nexport class Identity {\n /**\n * Validator schema that accepts a {@link RawIdentity} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest an identity — for example,\n * as a required field inside a message schema.\n */\n public static schema = rawIdentitySchema\n\n /**\n * Returns `true` if `value` is an {@link Identity} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is an {@link Identity} instance.\n */\n public static isIdentity(value: unknown): value is Identity {\n return isInstanceOf(value, 'Identity', Identity)\n }\n\n /**\n * The system-facing identifier for this participant — never sent to the model directly.\n */\n declare readonly identifier: string | number\n\n /**\n * How this participant is presented to the model, as a {@link @nhtio/adk!Tokenizable} for inline\n * token estimation.\n */\n declare readonly representation: Tokenizable\n\n #identifier: string | number\n #representation: Tokenizable\n\n /**\n * @param raw - The raw identity input validated against `rawIdentitySchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_IDENTITY_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawIdentity) {\n let resolved: ResolvedIdentity\n try {\n resolved = validateOrThrow<ResolvedIdentity>(rawIdentitySchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_IDENTITY_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#identifier = resolved.identifier\n this.#representation = Tokenizable.isTokenizable(resolved.representation)\n ? resolved.representation\n : new Tokenizable(resolved.representation)\n\n Object.defineProperties(this, {\n identifier: {\n get: () => this.#identifier,\n enumerable: true,\n configurable: false,\n },\n representation: {\n get: () => this.#representation,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n","import { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_MEMORY_VALUE } from '../exceptions/runtime'\nimport type { DateTime } from 'luxon'\n\n/**\n * Plain input object supplied to {@link Memory} at construction time.\n *\n * @remarks\n * Validated against `rawMemorySchema` before the `Memory` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n */\nexport interface RawMemory {\n /** Stable unique identifier for this memory entry. */\n id: string\n /** The memory content as a plain string or an existing {@link @nhtio/adk!Tokenizable} instance. */\n content: string | Tokenizable\n /** Confidence score in the range `[0, 1]` — how certain the agent is that this memory is accurate. */\n confidence: number\n /** Importance score in the range `[0, 1]` — how much weight this memory should carry during retrieval. */\n importance: number\n /** When this memory was first recorded. */\n createdAt: string | number | Date | DateTime\n /** When this memory was last modified. */\n updatedAt: string | number | Date | DateTime\n}\n\n/**\n * A fully-resolved {@link RawMemory} where all fields have been validated and temporal values\n * normalised to Luxon `DateTime` instances.\n *\n * @remarks\n * This is the shape returned by `rawMemorySchema` after validation — used internally by the\n * {@link Memory} constructor to assign private fields with guaranteed types.\n */\ninterface ResolvedMemory {\n id: string\n content: Tokenizable\n confidence: number\n importance: number\n createdAt: DateTime\n updatedAt: DateTime\n}\n\n/**\n * Validator schema used to validate a {@link RawMemory} before constructing a {@link Memory}.\n *\n * @remarks\n * Validates all six fields of {@link RawMemory}:\n * - `id` — required non-empty string.\n * - `content` — required string or {@link @nhtio/adk!Tokenizable}, via {@link @nhtio/adk!Tokenizable.schema}.\n * - `confidence` — required number in `[0, 1]`.\n * - `importance` — required number in `[0, 1]`.\n * - `createdAt` / `updatedAt` — required datetime-parseable values, normalised to `DateTime`.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_MEMORY_VALUE} (via the {@link Memory} constructor) when\n * validation fails.\n */\nconst rawMemorySchema = validator.object<RawMemory>({\n id: validator.string().required(),\n content: Tokenizable.schema.required(),\n confidence: validator.number().min(0).max(1).required(),\n importance: validator.number().min(0).max(1).required(),\n createdAt: validator.datetime().required(),\n updatedAt: validator.datetime().required(),\n})\n\n/**\n * An immutable, validated memory entry held by the agent.\n *\n * @remarks\n * Constructed from a {@link RawMemory} via `rawMemorySchema`. All temporal fields are\n * normalised to Luxon `DateTime` instances at construction time. The `content` field is\n * always a {@link @nhtio/adk!Tokenizable} so callers can estimate token cost without an additional\n * wrapping step.\n */\nexport class Memory {\n /**\n * Validator schema that accepts a {@link RawMemory} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a memory entry — for\n * example, a collection schema that holds an array of memories.\n */\n public static schema = rawMemorySchema\n\n /**\n * Returns `true` if `value` is a {@link Memory} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Memory} instance.\n */\n public static isMemory(value: unknown): value is Memory {\n return isInstanceOf(value, 'Memory', Memory)\n }\n /** Stable unique identifier for this memory entry. */\n declare readonly id: string\n /** The memory content as a {@link @nhtio/adk!Tokenizable} for inline token estimation. */\n declare readonly content: Tokenizable\n /** Confidence score in the range `[0, 1]`. */\n declare readonly confidence: number\n /** Importance score in the range `[0, 1]`. */\n declare readonly importance: number\n /** When this memory was first recorded. */\n declare readonly createdAt: DateTime\n /** When this memory was last modified. */\n declare readonly updatedAt: DateTime\n\n #id: string\n #content: Tokenizable\n #confidence: number\n #importance: number\n #createdAt: DateTime\n #updatedAt: DateTime\n\n /**\n * @param raw - The raw memory input validated against `rawMemorySchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_MEMORY_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawMemory) {\n let resolved: ResolvedMemory\n try {\n resolved = validateOrThrow<ResolvedMemory>(rawMemorySchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_MEMORY_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#id = resolved.id\n this.#content = Tokenizable.isTokenizable(resolved.content)\n ? resolved.content\n : new Tokenizable(resolved.content)\n this.#confidence = resolved.confidence\n this.#importance = resolved.importance\n this.#createdAt = resolved.createdAt\n this.#updatedAt = resolved.updatedAt\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n content: {\n get: () => this.#content,\n enumerable: true,\n configurable: false,\n },\n confidence: {\n get: () => this.#confidence,\n enumerable: true,\n configurable: false,\n },\n importance: {\n get: () => this.#importance,\n enumerable: true,\n configurable: false,\n },\n createdAt: {\n get: () => this.#createdAt,\n enumerable: true,\n configurable: false,\n },\n updatedAt: {\n get: () => this.#updatedAt,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n","import { Media } from './media'\nimport { Identity } from './identity'\nimport { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_MESSAGE_VALUE } from '../exceptions/runtime'\nimport type { DateTime } from 'luxon'\nimport type { RawIdentity } from './identity'\n\n/**\n * The roles a {@link Message} author can hold.\n *\n * @remarks\n * Restricted to `user` and `assistant` — system instructions, developer directives, and\n * tool results are handled separately and never appear in the persisted message history.\n */\nexport type MessageRole = 'user' | 'assistant'\n\n/**\n * Plain input object supplied to {@link Message} at construction time.\n *\n * @remarks\n * Validated against `rawMessageSchema` before the `Message` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n *\n * At least one of `content` or `attachments` (non-empty) must be present — a message with\n * neither throws {@link @nhtio/adk!E_INVALID_INITIAL_MESSAGE_VALUE}.\n */\nexport interface RawMessage {\n /** Stable unique identifier for this message. */\n id: string\n /** Whether this message is from the human participant or the model. */\n role: MessageRole\n /**\n * The message content as a plain string or an existing {@link @nhtio/adk!Tokenizable} instance.\n *\n * @remarks\n * Optional — but required when `attachments` is absent or empty. The cross-field rule on\n * `rawMessageSchema` enforces that at least one of `content` or `attachments` is present.\n */\n content?: string | Tokenizable\n /**\n * Media attachments carried by this message — images, audio, video, documents.\n *\n * @remarks\n * Optional and symmetric across roles: both `user` and `assistant` messages may carry\n * attachments. Each attachment carries its own `trustTier` and `modalityHazard`, which the\n * renderer uses to wrap the asset in its own trust envelope independent of the message\n * envelope. How a renderer orders text vs attachments in the on-the-wire content array is\n * a renderer-policy concern, not a contract of {@link Message}.\n */\n attachments?: Media[]\n /**\n * The identity of the participant who authored this message.\n *\n * @remarks\n * Optional. When omitted, the `role` value is used as both the system-facing `identifier`\n * and the model-facing `representation`. Three accepted forms when provided:\n * - A plain `string` — used as both `identifier` and `representation`.\n * - A {@link @nhtio/adk!RawIdentity} object — validated and wrapped into an {@link @nhtio/adk!Identity}.\n * - An existing {@link @nhtio/adk!Identity} instance — passed through unchanged.\n */\n identity?: string | RawIdentity | Identity\n /** When this message was created. */\n createdAt: string | number | Date | DateTime\n /** When this message was last modified. */\n updatedAt: string | number | Date | DateTime\n}\n\n/**\n * A fully-resolved {@link RawMessage} where temporal fields have been normalised to Luxon\n * `DateTime` instances and `identity` is a validated {@link @nhtio/adk!Identity}.\n *\n * @remarks\n * Used internally by the {@link Message} constructor to assign private fields with\n * guaranteed types.\n */\ninterface ResolvedMessage {\n id: string\n role: MessageRole\n content?: Tokenizable\n attachments: Media[]\n identity: string | RawIdentity | Identity\n createdAt: DateTime\n updatedAt: DateTime\n}\n\n/**\n * Validator schema used to validate a {@link RawMessage} before constructing a {@link Message}.\n *\n * @remarks\n * Validates all fields of {@link RawMessage}:\n * - `id` — required non-empty string.\n * - `role` — required; must be `'user'` or `'assistant'`.\n * - `content` — optional string or {@link @nhtio/adk!Tokenizable}, via {@link @nhtio/adk!Tokenizable.schema}.\n * - `attachments` — optional array of {@link @nhtio/adk!Media} instances. Defaults to `[]`.\n * - At least one of `content` or `attachments` must be present and non-empty; a message with\n * neither is invalid.\n * - `identity` — required string, {@link @nhtio/adk!RawIdentity}, or {@link @nhtio/adk!Identity}; a plain string is\n * mapped to both `identifier` and `representation` automatically.\n * - `createdAt` / `updatedAt` — required datetime-parseable values, normalised to `DateTime`.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_MESSAGE_VALUE} (via the {@link Message} constructor) when\n * validation fails.\n */\nconst rawMessageSchema = validator\n .object<RawMessage>({\n id: validator.string().required(),\n role: validator.string().valid('user', 'assistant').required(),\n content: Tokenizable.schema.optional(),\n attachments: validator\n .array()\n .items(\n validator.any().custom((value, helpers) => {\n if (Media.isMedia(value)) return value\n return helpers.error('any.invalid')\n })\n )\n .default([]),\n identity: validator\n .alternatives(validator.string(), Identity.schema)\n .default(validator.ref('role')),\n createdAt: validator.datetime().required(),\n updatedAt: validator.datetime().required(),\n })\n .custom((value, helpers) => {\n const resolved = value as ResolvedMessage\n const hasContent = resolved.content !== undefined && resolved.content !== null\n const hasAttachments = Array.isArray(resolved.attachments) && resolved.attachments.length > 0\n if (!hasContent && !hasAttachments) {\n return helpers.error('any.invalid')\n }\n return resolved\n })\n\n/**\n * An immutable, validated conversation message from a human participant or the model.\n *\n * @remarks\n * Covers only `user` and `assistant` roles — system instructions, developer directives, and\n * tool results are not represented here. Constructed from a {@link RawMessage} via\n * `rawMessageSchema`. Temporal fields are normalised to Luxon `DateTime` instances at\n * construction time. Both `content` and `identity.representation` are {@link @nhtio/adk!Tokenizable} so\n * token cost can be estimated inline.\n *\n * A message may carry `content` (text), `attachments` (media), or both. The cross-field rule\n * on `rawMessageSchema` enforces that at least one is present. Downstream code that reaches\n * for `message.content` must handle the attachments-only case where `content` is `undefined`.\n */\nexport class Message {\n /**\n * Validator schema that accepts a {@link RawMessage} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a message entry — for\n * example, a collection schema that holds an array of messages.\n */\n public static schema = rawMessageSchema\n\n /**\n * Returns `true` if `value` is a {@link Message} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Message} instance.\n */\n public static isMessage(value: unknown): value is Message {\n return isInstanceOf(value, 'Message', Message)\n }\n\n /** Stable unique identifier for this message. */\n declare readonly id: string\n /** Whether this message is from the human participant or the model. */\n declare readonly role: MessageRole\n /**\n * The message content as a {@link @nhtio/adk!Tokenizable} for inline token estimation, or `undefined`\n * for attachments-only messages.\n *\n * @remarks\n * `undefined` when the message was constructed with only `attachments`. Render code that\n * needs the text portion must guard for the missing case rather than blindly calling\n * `message.content.toString()`.\n */\n declare readonly content: Tokenizable | undefined\n /**\n * Media attachments carried by this message.\n *\n * @remarks\n * Always defined as a frozen array — empty when the message has no attachments. Both\n * `user` and `assistant` messages may carry attachments. Each entry carries its own\n * `trustTier` and `modalityHazard`; the renderer wraps each in its own trust envelope\n * independent of the message envelope.\n */\n declare readonly attachments: ReadonlyArray<Media>\n /** The identity of the participant who authored this message. */\n declare readonly identity: Identity\n /** When this message was created. */\n declare readonly createdAt: DateTime\n /** When this message was last modified. */\n declare readonly updatedAt: DateTime\n\n #id: string\n #role: MessageRole\n #content: Tokenizable | undefined\n #attachments: ReadonlyArray<Media>\n #identity: Identity\n #createdAt: DateTime\n #updatedAt: DateTime\n\n /**\n * @param raw - The raw message input validated against `rawMessageSchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_MESSAGE_VALUE} when `raw` does not satisfy the schema —\n * including the cross-field rule that at least one of `content` or `attachments` must be\n * present and non-empty.\n */\n constructor(raw: RawMessage) {\n let resolved: ResolvedMessage\n try {\n resolved = validateOrThrow<ResolvedMessage>(rawMessageSchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_MESSAGE_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#id = resolved.id\n this.#role = resolved.role\n this.#content =\n resolved.content === undefined || resolved.content === null\n ? undefined\n : Tokenizable.isTokenizable(resolved.content)\n ? resolved.content\n : new Tokenizable(resolved.content)\n this.#attachments = Object.freeze([...(resolved.attachments ?? [])])\n const rawIdentity = resolved.identity\n this.#identity = Identity.isIdentity(rawIdentity)\n ? rawIdentity\n : typeof rawIdentity === 'string'\n ? new Identity({ identifier: rawIdentity, representation: rawIdentity })\n : new Identity(rawIdentity)\n this.#createdAt = resolved.createdAt\n this.#updatedAt = resolved.updatedAt\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n role: {\n get: () => this.#role,\n enumerable: true,\n configurable: false,\n },\n content: {\n get: () => this.#content,\n enumerable: true,\n configurable: false,\n },\n attachments: {\n get: () => this.#attachments,\n enumerable: true,\n configurable: false,\n },\n identity: {\n get: () => this.#identity,\n enumerable: true,\n configurable: false,\n },\n createdAt: {\n get: () => this.#createdAt,\n enumerable: true,\n configurable: false,\n },\n updatedAt: {\n get: () => this.#updatedAt,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n","import { Identity } from './identity'\nimport { Tokenizable } from './tokenizable'\nimport { validator } from '@nhtio/validation'\nimport { validateOrThrow } from '../utils/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { E_INVALID_INITIAL_THOUGHT_VALUE } from '../exceptions/runtime'\nimport type { DateTime } from 'luxon'\nimport type { RawIdentity } from './identity'\n\n/**\n * Plain input object supplied to {@link Thought} at construction time.\n *\n * @remarks\n * Validated against `rawThoughtSchema` before the `Thought` instance is created.\n * Temporal fields accept any value that Luxon can parse — ISO strings, Unix timestamps,\n * `Date` objects, or existing `DateTime` instances.\n */\nexport interface RawThought {\n /** Stable unique identifier for this thought. */\n id: string\n /** The reasoning content as a plain string or an existing {@link @nhtio/adk!Tokenizable} instance. */\n content: string | Tokenizable\n /**\n * The identity of the agent who produced this thought.\n *\n * @remarks\n * Required in multi-agent conversations to attribute reasoning traces to a specific agent.\n * Three accepted forms when provided:\n * - A plain `string` — used as both `identifier` and `representation`.\n * - A {@link @nhtio/adk!RawIdentity} object — validated and wrapped into an {@link @nhtio/adk!Identity}.\n * - An existing {@link @nhtio/adk!Identity} instance — passed through unchanged.\n *\n * When omitted, defaults to `'assistant'` (both `identifier` and `representation`).\n */\n identity?: string | RawIdentity | Identity\n /**\n * Optional vendor-opaque payload that round-trips back to a matching model wire.\n *\n * @remarks\n * Carries anything the ADK cannot interpret but a specific provider can — for example,\n * an Anthropic Messages thinking-block `signature`, an OpenAI Responses\n * `ResponseReasoningItem.encrypted_content` blob, a DeepSeek server-side reasoning handle,\n * or an MCP-mediated reasoning item.\n *\n * When present, an LLM battery MUST treat the thought as **opaque-mode**: do NOT inline\n * `content` through the plain `<thought>` envelope; serialise `payload` back to the wire in\n * whichever shape the matching {@link RawThought.replayCompatibility} identifier specifies.\n * The plain-text `content` is kept alongside for token-accounting and human/observer\n * inspection — it is not the thing the model sees.\n *\n * Cross-field invariant: a present `payload` REQUIRES a present {@link RawThought.replayCompatibility}.\n * A `payload` without `replayCompatibility` is malformed (the ADK has no way to know\n * which adapter can consume it) and {@link Thought.schema} rejects with\n * {@link @nhtio/adk!E_INVALID_INITIAL_THOUGHT_VALUE}.\n *\n * @defaultValue `undefined`\n */\n payload?: unknown\n /**\n * Optional free-form identifier describing which adapter wire-shape this thought can be\n * safely replayed into.\n *\n * @remarks\n * Examples (none of these are reserved by the ADK — they are consumer conventions):\n * - `'plain-text'` — replayable into every LLM battery\n * - `'anthropic-messages-thinking-v1'`\n * - `'openai-responses-reasoning-item-v1'`\n * - `'deepseek-reasoning-handle-v1'`\n *\n * LLM batteries declare via constructor option which tags they can safely replay; matching\n * opaque thoughts are routed to the wire's typed reasoning channel where it exists, or to a\n * documented side-channel key on the request body where the wire has none. Non-matching\n * opaque thoughts are elided from the current dispatch but NOT removed from\n * `ctx.turnThoughts` — they remain in context so a subsequent dispatch to a different\n * adapter that DOES declare the matching tag can pick them up.\n *\n * Plain-text thoughts (`payload === undefined` AND `replayCompatibility === undefined`, or\n * explicit `replayCompatibility: 'plain-text'`) are always replayable.\n *\n * A `replayCompatibility` without a `payload` is allowed — it documents intent (\"this\n * plain-text thought is only meaningful to a specific fine-tuned variant\") without\n * requiring an opaque blob.\n *\n * @defaultValue `undefined`\n */\n replayCompatibility?: string\n /** When this thought was recorded. */\n createdAt: string | number | Date | DateTime\n /** When this thought was last modified. */\n updatedAt: string | number | Date | DateTime\n}\n\n/**\n * A fully-resolved {@link RawThought} where temporal fields have been normalised to Luxon\n * `DateTime` instances.\n *\n * @remarks\n * Used internally by the {@link Thought} constructor to assign private fields with\n * guaranteed types.\n */\ninterface ResolvedThought {\n id: string\n content: Tokenizable\n identity: string | RawIdentity | Identity\n payload?: unknown\n replayCompatibility?: string\n createdAt: DateTime\n updatedAt: DateTime\n}\n\n/**\n * Validator schema used to validate a {@link RawThought} before constructing a {@link Thought}.\n *\n * @remarks\n * Validates all fields of {@link RawThought}:\n * - `id` — required non-empty string.\n * - `content` — required string or {@link @nhtio/adk!Tokenizable}, via {@link @nhtio/adk!Tokenizable.schema}.\n * - `identity` — optional string, {@link @nhtio/adk!RawIdentity}, or {@link @nhtio/adk!Identity}; defaults to\n * `'assistant'` when omitted.\n * - `createdAt` / `updatedAt` — required datetime-parseable values, normalised to `DateTime`.\n *\n * Throws {@link @nhtio/adk!E_INVALID_INITIAL_THOUGHT_VALUE} (via the {@link Thought} constructor) when\n * validation fails.\n */\nconst rawThoughtSchema = validator\n .object<RawThought>({\n id: validator.string().required(),\n content: Tokenizable.schema.required(),\n identity: validator.alternatives(validator.string(), Identity.schema).default('assistant'),\n payload: validator.any().optional(),\n replayCompatibility: validator.string().min(1).optional(),\n createdAt: validator.datetime().required(),\n updatedAt: validator.datetime().required(),\n })\n .custom((value, helpers) => {\n const v = value as RawThought\n if (\n v.payload !== undefined &&\n (v.replayCompatibility === undefined || v.replayCompatibility === null)\n ) {\n return helpers.error('any.invalid')\n }\n return value\n })\n\n/**\n * An immutable, validated internal reasoning trace produced by an agent.\n *\n * @remarks\n * Represents an agent's internal thinking — distinct from {@link @nhtio/adk!Message} (which is part of\n * the visible conversation) and never shown to end users directly. Carries an `identity` so\n * reasoning traces can be attributed to a specific agent in multi-agent conversations.\n * Constructed from a {@link RawThought} via `rawThoughtSchema`. The `content` field is always\n * a {@link @nhtio/adk!Tokenizable} so token cost can be estimated inline.\n */\nexport class Thought {\n /**\n * Validator schema that accepts a {@link RawThought} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a thought entry.\n */\n public static schema = rawThoughtSchema\n\n /**\n * Returns `true` if `value` is a {@link Thought} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Thought} instance.\n */\n public static isThought(value: unknown): value is Thought {\n return isInstanceOf(value, 'Thought', Thought)\n }\n\n /** Stable unique identifier for this thought. */\n declare readonly id: string\n /** The reasoning content as a {@link @nhtio/adk!Tokenizable} for inline token estimation. */\n declare readonly content: Tokenizable\n /** The identity of the agent who produced this thought. */\n declare readonly identity: Identity\n /**\n * Optional vendor-opaque payload that round-trips back to a matching model wire.\n * See {@link RawThought.payload}.\n */\n declare readonly payload: unknown\n /**\n * Optional wire-shape identifier describing which adapter can safely replay this thought.\n * See {@link RawThought.replayCompatibility}.\n */\n declare readonly replayCompatibility: string | undefined\n /** When this thought was recorded. */\n declare readonly createdAt: DateTime\n /** When this thought was last modified. */\n declare readonly updatedAt: DateTime\n\n #id: string\n #content: Tokenizable\n #identity: Identity\n #payload: unknown\n #replayCompatibility: string | undefined\n #createdAt: DateTime\n #updatedAt: DateTime\n\n /**\n * @param raw - The raw thought input validated against `rawThoughtSchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_THOUGHT_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawThought) {\n let resolved: ResolvedThought\n try {\n resolved = validateOrThrow<ResolvedThought>(rawThoughtSchema, raw, true)\n } catch (err) {\n throw new E_INVALID_INITIAL_THOUGHT_VALUE({ cause: isError(err) ? err : undefined })\n }\n this.#id = resolved.id\n this.#content = Tokenizable.isTokenizable(resolved.content)\n ? resolved.content\n : new Tokenizable(resolved.content)\n const rawIdentity = resolved.identity\n this.#identity = Identity.isIdentity(rawIdentity)\n ? rawIdentity\n : typeof rawIdentity === 'string'\n ? new Identity({ identifier: rawIdentity, representation: rawIdentity })\n : new Identity(rawIdentity)\n this.#payload = resolved.payload\n this.#replayCompatibility = resolved.replayCompatibility\n this.#createdAt = resolved.createdAt\n this.#updatedAt = resolved.updatedAt\n\n Object.defineProperties(this, {\n id: {\n get: () => this.#id,\n enumerable: true,\n configurable: false,\n },\n content: {\n get: () => this.#content,\n enumerable: true,\n configurable: false,\n },\n identity: {\n get: () => this.#identity,\n enumerable: true,\n configurable: false,\n },\n payload: {\n get: () => this.#payload,\n enumerable: true,\n configurable: false,\n },\n replayCompatibility: {\n get: () => this.#replayCompatibility,\n enumerable: true,\n configurable: false,\n },\n createdAt: {\n get: () => this.#createdAt,\n enumerable: true,\n configurable: false,\n },\n updatedAt: {\n get: () => this.#updatedAt,\n enumerable: true,\n configurable: false,\n },\n })\n }\n}\n"],"mappings":"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"}
|
package/tool-CRZSUcdP.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-CRZSUcdP.mjs","names":["#name","#description","#inputSchema","#handler","#artifactConstructor","#meta","#ephemeral","#trusted","#onCollision"],"sources":["../src/lib/contracts/spooled_artifact_constructor.ts","../src/lib/classes/tool.ts"],"sourcesContent":["import { validator } from '@nhtio/validation'\nimport { passesSchema } from '../utils/validation'\nimport type { SpooledArtifact } from '../classes/spooled_artifact'\n\n/**\n * Constructor signature for any {@link @nhtio/adk!SpooledArtifact} (the class itself or a subclass).\n *\n * @remarks\n * Re-declared here at the contract level so consumers — and the `Tool.artifactConstructor`\n * resolver validator in particular — can talk about the constructor shape without value-importing\n * the {@link @nhtio/adk!SpooledArtifact} class (which would close the `tool.ts` ↔ `spooled_artifact.ts` ↔\n * `artifact_tool.ts` module cycle at load time and TDZ-crash `ArtifactTool extends Tool`).\n *\n * @typeParam A - The {@link @nhtio/adk!SpooledArtifact} subtype the constructor produces.\n */\nexport type SpooledArtifactConstructorLike<A extends SpooledArtifact = SpooledArtifact> = new (\n ...args: any[]\n) => A\n\nconst ARTIFACT_METHODS = [\n 'head',\n 'tail',\n 'grep',\n 'cat',\n 'byteLength',\n 'lineCount',\n 'estimateTokens',\n] as const\n\n/**\n * Validator schema used to validate a {@link SpooledArtifactConstructorLike} value.\n *\n * @remarks\n * Because the validator is invoked at validate-time (not at module-load), it is safe to inspect\n * the constructor's prototype here. The check is duck-typed: the value must be a function whose\n * `prototype` carries every canonical artifact instance method (`head`, `tail`, `grep`, `cat`,\n * `byteLength`, `lineCount`, `estimateTokens`). This mirrors {@link spoolReaderSchema}'s\n * cross-realm-safe duck-type pattern — `instanceof SpooledArtifact` would be tighter but would\n * force a value-import of the class and reopen the module cycle.\n */\nexport const spooledArtifactConstructorSchema = validator.any().custom((value, helpers) => {\n if (typeof value !== 'function') return helpers.error('any.invalid')\n const proto = (value as { prototype?: unknown }).prototype\n if (proto === undefined || proto === null) return helpers.error('any.invalid')\n if (ARTIFACT_METHODS.every((m) => typeof (proto as Record<string, unknown>)[m] === 'function')) {\n return value\n }\n return helpers.error('any.invalid')\n})\n\n/**\n * Returns `true` if `value` is a constructor whose prototype carries every canonical\n * {@link @nhtio/adk!SpooledArtifact} instance method.\n *\n * @remarks\n * Duck-typed; does not use `instanceof SpooledArtifact`. Used by the `Tool.artifactConstructor`\n * resolver validator and any other site that needs to recognise a `SpooledArtifact`-like\n * constructor without pulling the class into its module-load graph.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a `SpooledArtifact`-shaped constructor.\n */\nexport const implementsSpooledArtifactConstructor = (\n value: unknown\n): value is SpooledArtifactConstructorLike => {\n return passesSchema(spooledArtifactConstructorSchema, value)\n}\n","import { DateTime } from 'luxon'\nimport { sha256 } from 'js-sha256'\nimport { Registry } from './registry'\nimport { validator } from '@nhtio/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { canonicalStringify } from '../utils/canonical_json'\nimport { validateOrThrow, asyncValidateOrThrow, ValidationException } from '../utils/validation'\nimport { implementsSpooledArtifactConstructor } from '../contracts/spooled_artifact_constructor'\nimport {\n E_INVALID_INITIAL_TOOL_VALUE,\n E_INVALID_TOOL_ARGS,\n E_TOOL_DOWNSTREAM_ERROR,\n} from '../exceptions/runtime'\nimport type { Media } from './media'\nimport type { Schema, Description } from '@nhtio/validation'\nimport type { DispatchContext } from '../contracts/dispatch_context'\nimport type { SpooledArtifact, SpooledArtifactConstructor } from './spooled_artifact'\n\n/**\n * A zero-arg function that returns the {@link @nhtio/adk!SpooledArtifactConstructor} the consumer should\n * use when wrapping this tool's serialised output into a `ToolCall.results` field.\n *\n * @remarks\n * Why a resolver (and not the constructor itself)? `tool.ts` participates in a module-load\n * cycle with `spooled_artifact.ts` and `artifact_tool.ts` (`ArtifactTool extends Tool` closes\n * the loop). Any eager value-level reference to `SpooledArtifact` in `tool.ts` would crash the\n * cycle with a TDZ error. A resolver lets `tool.ts` validate \"is a function\" at module-load\n * time and defer the actual constructor check to validate-time (which always runs after every\n * module body has executed). Wrap-sites invoke `tool.artifactConstructor?.() ?? SpooledArtifact`\n * to obtain the final constructor.\n */\nexport type ArtifactConstructorResolver<A extends SpooledArtifact = SpooledArtifact> =\n () => SpooledArtifactConstructor<A>\n\n/**\n * The execution function for a {@link Tool}.\n *\n * @remarks\n * Receives the raw arguments passed to the executor, the active {@link @nhtio/adk!DispatchContext}, and the\n * tool's metadata registry.\n *\n * Return shapes:\n * - `string` / `Uint8Array` — opaque serialised output. The ADK does not persist the bytes\n * itself; the consumer's executor middleware is responsible for storing them and wrapping\n * them via `tool.artifactConstructor?.() ?? SpooledArtifact` when assembling the `ToolCall`\n * record.\n * - {@link @nhtio/adk!Media} / `Media[]` — explicit-modality silo. Bypasses\n * {@link Tool.artifactConstructor} — the handler returns the final result shape directly.\n * The LLM battery renders each `Media` as a provider-specific content block.\n */\nexport type ToolHandler = (\n args: unknown,\n ctx: DispatchContext,\n meta: Registry\n) => string | Uint8Array | Media | Media[] | Promise<string | Uint8Array | Media | Media[]>\n\n/**\n * Plain input object supplied to {@link Tool} at construction time.\n *\n * @typeParam A - The {@link @nhtio/adk!SpooledArtifact} subtype used to wrap this tool's results when\n * the consumer assembles a `ToolCall.results` field. Defaults to {@link @nhtio/adk!SpooledArtifact}\n * (plain text). Tools producing JSON output should set this to `SpooledJsonArtifact`; tools\n * producing markdown should set it to `SpooledMarkdownArtifact`; consumers can also pass a\n * custom subclass.\n */\nexport interface RawTool<A extends SpooledArtifact = SpooledArtifact> {\n /** Unique identifier used in LLM tool definitions. Recommend lowercase snake_case. */\n name: string\n /** Human-readable description passed to the model to explain what the tool does. */\n description: string\n /** @nhtio/validation schema for the tool's input arguments. Annotate with `.description()`, `.note()`, `.example()` etc. to produce rich LLM tool definitions via `.describe()`. */\n inputSchema: Schema\n /** Execution function. Not exposed as a public property — invoke via `executor()`. */\n handler: ToolHandler\n /**\n * Zero-arg resolver returning the {@link @nhtio/adk!SpooledArtifactConstructor} the consumer should use\n * when wrapping this tool's serialised output into a `ToolCall.results` field. Optional —\n * when omitted, wrap-sites fall back to {@link @nhtio/adk!SpooledArtifact} (plain text).\n *\n * @remarks\n * Recommended call shape: `artifactConstructor: () => SpooledJsonArtifact`. The closure is\n * the indirection that lets `tool.ts` validate this field without eagerly importing\n * `SpooledArtifact` (which would crash the `tool.ts ↔ spooled_artifact.ts ↔ artifact_tool.ts`\n * module-load cycle). At validate time the schema invokes the resolver and verifies its\n * return value is a `SpooledArtifact`-derived constructor — wrong-shape resolvers throw\n * {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_VALUE}.\n *\n * Wrap-sites (storage batteries, scripted executors) read the constructor via\n * `tool.artifactConstructor?.() ?? SpooledArtifact`.\n */\n artifactConstructor?: ArtifactConstructorResolver<A>\n /** Optional arbitrary metadata for this tool (e.g. RBAC scopes, feature flags). Defaults to `{}`. Stored in a {@link @nhtio/adk!Registry} for dot-path access. */\n meta?: Record<string, unknown>\n /**\n * When `true`, marks this tool as owned by a specific {@link @nhtio/adk!DispatchContext} so that\n * `ToolRegistry.pruneEphemeral()` will drop it at ctx-completion.\n *\n * @remarks\n * The flag is advisory at the `Tool` level — registries decide what to do with it. The canonical\n * producer of ephemeral tools is `SpooledArtifact.forgeTools(ctx)`, which sets this to `true`\n * on every artifact-query tool it emits.\n *\n * @defaultValue `false`\n */\n ephemeral?: boolean\n /**\n * When `true`, declares that this tool's output should be treated as **trusted developer/user\n * intent** rather than as untrusted third-party text when surfaced to the model.\n *\n * @remarks\n * LLM batteries read this flag per call when rendering tool-call results. The default\n * untrusted envelope (e.g. `<untrusted_content>` in the OpenAI Chat Completions battery) is the\n * secure-by-default treatment for arbitrary tool output. A tool whose output is authored by the\n * user or operator (Q&A tools surfacing user-authored answers, human-in-the-loop approval\n * gates, feedback-collection tools, configuration tools returning developer-authored\n * constants) sets this to `true` so the LLM battery routes the result through its trusted\n * envelope (`<trusted_content>` in the OpenAI Chat Completions battery).\n *\n * Trust is a property of the tool's output, not a property of how a particular battery is\n * wired — putting the flag here means the trust signal travels with the tool wherever it is\n * registered, no per-battery string lists, no name-matching to fail-open on typos.\n *\n * @defaultValue `false`\n */\n trusted?: boolean\n /**\n * Self-declared merge collision policy. Honoured by `ToolRegistry.merge` (NOT by\n * `ToolRegistry.register`) when this tool collides with another of the same name.\n *\n * @remarks\n * - `'throw'` (default): defer to the merge-level `options.onCollision`. If that is also\n * `'throw'`, the merge raises `E_TOOL_ALREADY_REGISTERED`. This matches the default behaviour\n * of `ToolRegistry.register`.\n * - `'replace'`: this tool always wins the collision, regardless of the merge-level option.\n * - `'keep'`: this tool always loses to any previously-registered tool of the same name.\n *\n * Forged artifact-query tools set this to `'replace'` so that merging multiple\n * `Subclass.forgeTools(ctx)` outputs (whose base-method tools overlap by name) resolves\n * silently — the descriptors, snapshot, and handler behaviour are interchangeable across\n * subclasses, so replacement is a behavioural no-op.\n *\n * @defaultValue `'throw'`\n */\n onCollision?: 'throw' | 'replace' | 'keep'\n}\n\n/**\n * Validator schema for a {@link RawTool}.\n */\nconst rawToolSchema = validator.object<RawTool>({\n name: validator.string().required(),\n description: validator.string().required(),\n inputSchema: validator\n .any()\n .custom((value, helpers) => {\n if (validator.isSchema(value) && (value as any).type === 'object') return value\n return helpers.error('any.invalid')\n })\n .required(),\n handler: validator.function().required(),\n artifactConstructor: validator\n .any()\n .custom((value, helpers) => {\n if (typeof value !== 'function') return helpers.error('any.invalid')\n // The resolver runs at validate time — well after the tool.ts ↔ spooled_artifact.ts ↔\n // artifact_tool.ts module cycle has fully unwound — so invoking it is safe. Delegate the\n // \"is this a SpooledArtifact-shaped constructor?\" check to the contract-level guard so\n // there's one canonical duck-type test (mirrors `implementsSpoolReader`'s pattern).\n let resolved: unknown\n try {\n resolved = (value as () => unknown)()\n } catch {\n return helpers.error('any.invalid')\n }\n if (implementsSpooledArtifactConstructor(resolved)) return value\n return helpers.error('any.invalid')\n })\n .optional(),\n meta: validator.object().pattern(validator.string(), validator.any()).default({}),\n ephemeral: validator.boolean().default(false),\n trusted: validator.boolean().default(false),\n onCollision: validator.string().valid('throw', 'replace', 'keep').default('throw'),\n})\n\n/**\n * A tool definition that serves as the single source of truth for a callable tool: its name,\n * description, input schema, execution handler, and the {@link @nhtio/adk!SpooledArtifact} subclass that\n * wraps its serialised output.\n *\n * @typeParam A - The {@link @nhtio/adk!SpooledArtifact} subtype this tool's results should be wrapped in.\n * Defaults to {@link @nhtio/adk!SpooledArtifact}.\n *\n * @remarks\n * The `inputSchema` is a `@nhtio/validation` schema. It is used at runtime to validate incoming\n * arguments before the handler is called, and its `.describe()` output provides all the metadata\n * needed to build a provider-specific LLM tool definition — annotate the schema with\n * `.description()`, `.note()`, `.example()` etc. once, and that information is available in both\n * contexts without duplication.\n *\n * The handler is private — invoke it only through `executor(ctx)` which validates args, fires\n * observability events (with a stable `callId` derived from the tool name and arguments), and\n * wraps handler errors in {@link @nhtio/adk!E_TOOL_DOWNSTREAM_ERROR}. The handler returns serialised bytes\n * (`string | Uint8Array`); persistence is the consumer's responsibility.\n *\n * `artifactConstructor` is the {@link @nhtio/adk!SpooledArtifact} subclass the consumer should use when\n * wrapping the handler's output into a `ToolCall.results` field. The author declares it once\n * on the tool instance; the consumer reads it when assembling persisted records.\n */\nexport class Tool<A extends SpooledArtifact = SpooledArtifact> {\n /**\n * Validator schema that accepts a {@link RawTool} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a tool entry\n * (e.g. `TurnRunnerConfig.tools`).\n */\n public static schema = rawToolSchema\n\n /**\n * Returns `true` if `value` is a {@link Tool} instance.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Tool} instance.\n */\n public static isTool(value: unknown): value is Tool {\n return isInstanceOf(value, 'Tool', Tool)\n }\n\n declare readonly name: string\n declare readonly description: string\n declare readonly inputSchema: Schema\n declare readonly artifactConstructor: ArtifactConstructorResolver<A> | undefined\n declare readonly meta: Registry\n declare readonly ephemeral: boolean\n declare readonly trusted: boolean\n declare readonly onCollision: 'throw' | 'replace' | 'keep'\n\n #name: string\n #description: string\n #inputSchema: Schema\n #handler: ToolHandler\n #artifactConstructor: ArtifactConstructorResolver<A> | undefined\n #meta: Registry\n #ephemeral: boolean\n #trusted: boolean\n #onCollision: 'throw' | 'replace' | 'keep'\n\n /**\n * @param raw - The raw tool input validated against `rawToolSchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawTool<A>) {\n let resolved: RawTool<A> & {\n meta: Record<string, unknown>\n ephemeral: boolean\n trusted: boolean\n onCollision: 'throw' | 'replace' | 'keep'\n }\n try {\n resolved = validateOrThrow<typeof resolved>(\n rawToolSchema,\n raw as RawTool,\n true\n ) as typeof resolved\n } catch (err) {\n throw new E_INVALID_INITIAL_TOOL_VALUE({ cause: isError(err) ? err : undefined })\n }\n\n this.#name = resolved.name\n this.#description = resolved.description\n this.#inputSchema = resolved.inputSchema\n this.#handler = resolved.handler\n this.#artifactConstructor = resolved.artifactConstructor as\n | ArtifactConstructorResolver<A>\n | undefined\n this.#meta = new Registry(resolved.meta)\n this.#ephemeral = resolved.ephemeral\n this.#trusted = resolved.trusted\n this.#onCollision = resolved.onCollision\n\n Object.defineProperties(this, {\n name: {\n get: () => this.#name,\n enumerable: true,\n configurable: false,\n },\n description: {\n get: () => this.#description,\n enumerable: true,\n configurable: false,\n },\n inputSchema: {\n get: () => this.#inputSchema,\n enumerable: true,\n configurable: false,\n },\n artifactConstructor: {\n get: () => this.#artifactConstructor,\n enumerable: true,\n configurable: false,\n },\n meta: {\n get: () => this.#meta,\n enumerable: true,\n configurable: false,\n },\n ephemeral: {\n get: () => this.#ephemeral,\n enumerable: true,\n configurable: false,\n },\n trusted: {\n get: () => this.#trusted,\n enumerable: true,\n configurable: false,\n },\n onCollision: {\n get: () => this.#onCollision,\n enumerable: true,\n configurable: false,\n },\n })\n }\n\n /**\n * Validates `args` against the tool's input schema asynchronously.\n *\n * @remarks\n * Async to support schemas with external validators (e.g. database lookups, API calls).\n * A validation failure throws {@link @nhtio/adk!E_INVALID_TOOL_ARGS} — this indicates a programming error\n * in the tool call loop, not a downstream failure.\n *\n * @param args - The arguments to validate.\n * @returns The validated (and coerced) arguments.\n * @throws {@link @nhtio/adk!E_INVALID_TOOL_ARGS} when `args` does not satisfy the input schema.\n */\n async validate(args: unknown): Promise<unknown> {\n try {\n return await asyncValidateOrThrow(this.#inputSchema, args)\n } catch (err) {\n if (isInstanceOf(err, 'ValidationException', ValidationException)) {\n throw new E_INVALID_TOOL_ARGS({ cause: err })\n }\n throw err\n }\n }\n\n /**\n * Returns a bound executor function for this tool against the given turn context.\n *\n * @remarks\n * The executor: (1) computes a stable `callId` as `sha256(canonicalStringify({tool, args}))`\n * over the **raw, pre-validation args**, (2) validates `args` via {@link Tool.validate},\n * (3) emits `toolExecutionStart` on the context (with the computed `callId`), (4) calls the\n * handler, (5) emits `toolExecutionEnd` (with the same `callId`), (6) wraps any handler error\n * in {@link @nhtio/adk!E_TOOL_DOWNSTREAM_ERROR} before re-throwing.\n *\n * The handler returns serialised bytes (`string | Uint8Array`) — persistence is the consumer's\n * concern. Use {@link Tool.artifactConstructor} when wrapping the bytes into a\n * `ToolCall.results` field.\n *\n * Pattern mirrors `Middleware.runner()` — call once per turn, reuse the returned function.\n *\n * @param ctx - The active turn context. Provides emit functions and turn ID.\n * @returns An async function `(args) => Promise<string | Uint8Array>`.\n */\n executor(\n ctx: DispatchContext\n ): (args: unknown) => Promise<string | Uint8Array | Media | Media[]> {\n return async (args: unknown): Promise<string | Uint8Array | Media | Media[]> => {\n // Compute callId over raw args (pre-validation) so two invocations with the same\n // (tool, raw args) produce the same identifier even if validation coerces values.\n const callId = sha256(canonicalStringify({ tool: this.#name, args }))\n const validatedArgs = await this.validate(args)\n const startedAt = DateTime.now()\n ctx.emitToolExecutionStart({\n toolName: this.#name,\n turnId: ctx.id,\n callId,\n args: validatedArgs,\n startedAt,\n })\n try {\n const result = await this.#handler(validatedArgs, ctx, this.#meta)\n const endedAt = DateTime.now()\n ctx.emitToolExecutionEnd({\n toolName: this.#name,\n turnId: ctx.id,\n callId,\n startedAt,\n endedAt,\n durationMs: endedAt.diff(startedAt).milliseconds,\n isError: false,\n })\n return result\n } catch (err) {\n const endedAt = DateTime.now()\n ctx.emitToolExecutionEnd({\n toolName: this.#name,\n turnId: ctx.id,\n callId,\n startedAt,\n endedAt,\n durationMs: endedAt.diff(startedAt).milliseconds,\n isError: true,\n })\n throw new E_TOOL_DOWNSTREAM_ERROR({ cause: isError(err) ? err : undefined })\n }\n }\n }\n\n /**\n * Returns a fully serialisable snapshot of this tool's definition.\n *\n * @remarks\n * The `inputSchema` property is the result of calling `.describe()` on the raw schema — a plain\n * object carrying all the annotation metadata (descriptions, notes, examples, types) without any\n * validator functions. Use this to build provider-specific LLM tool definitions.\n *\n * @returns `{ name, description, inputSchema }` where `inputSchema` is the schema description.\n */\n describe(): { name: string; description: string; inputSchema: Description } {\n return {\n name: this.#name,\n description: this.#description,\n inputSchema: this.#inputSchema.describe(),\n }\n }\n}\n"],"mappings":"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"}
|
package/tool-CX9vNHAw.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool-CX9vNHAw.js","names":["#name","#description","#inputSchema","#handler","#artifactConstructor","#meta","#ephemeral","#trusted","#onCollision"],"sources":["../src/lib/contracts/spooled_artifact_constructor.ts","../src/lib/classes/tool.ts"],"sourcesContent":["import { validator } from '@nhtio/validation'\nimport { passesSchema } from '../utils/validation'\nimport type { SpooledArtifact } from '../classes/spooled_artifact'\n\n/**\n * Constructor signature for any {@link @nhtio/adk!SpooledArtifact} (the class itself or a subclass).\n *\n * @remarks\n * Re-declared here at the contract level so consumers — and the `Tool.artifactConstructor`\n * resolver validator in particular — can talk about the constructor shape without value-importing\n * the {@link @nhtio/adk!SpooledArtifact} class (which would close the `tool.ts` ↔ `spooled_artifact.ts` ↔\n * `artifact_tool.ts` module cycle at load time and TDZ-crash `ArtifactTool extends Tool`).\n *\n * @typeParam A - The {@link @nhtio/adk!SpooledArtifact} subtype the constructor produces.\n */\nexport type SpooledArtifactConstructorLike<A extends SpooledArtifact = SpooledArtifact> = new (\n ...args: any[]\n) => A\n\nconst ARTIFACT_METHODS = [\n 'head',\n 'tail',\n 'grep',\n 'cat',\n 'byteLength',\n 'lineCount',\n 'estimateTokens',\n] as const\n\n/**\n * Validator schema used to validate a {@link SpooledArtifactConstructorLike} value.\n *\n * @remarks\n * Because the validator is invoked at validate-time (not at module-load), it is safe to inspect\n * the constructor's prototype here. The check is duck-typed: the value must be a function whose\n * `prototype` carries every canonical artifact instance method (`head`, `tail`, `grep`, `cat`,\n * `byteLength`, `lineCount`, `estimateTokens`). This mirrors {@link spoolReaderSchema}'s\n * cross-realm-safe duck-type pattern — `instanceof SpooledArtifact` would be tighter but would\n * force a value-import of the class and reopen the module cycle.\n */\nexport const spooledArtifactConstructorSchema = validator.any().custom((value, helpers) => {\n if (typeof value !== 'function') return helpers.error('any.invalid')\n const proto = (value as { prototype?: unknown }).prototype\n if (proto === undefined || proto === null) return helpers.error('any.invalid')\n if (ARTIFACT_METHODS.every((m) => typeof (proto as Record<string, unknown>)[m] === 'function')) {\n return value\n }\n return helpers.error('any.invalid')\n})\n\n/**\n * Returns `true` if `value` is a constructor whose prototype carries every canonical\n * {@link @nhtio/adk!SpooledArtifact} instance method.\n *\n * @remarks\n * Duck-typed; does not use `instanceof SpooledArtifact`. Used by the `Tool.artifactConstructor`\n * resolver validator and any other site that needs to recognise a `SpooledArtifact`-like\n * constructor without pulling the class into its module-load graph.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a `SpooledArtifact`-shaped constructor.\n */\nexport const implementsSpooledArtifactConstructor = (\n value: unknown\n): value is SpooledArtifactConstructorLike => {\n return passesSchema(spooledArtifactConstructorSchema, value)\n}\n","import { DateTime } from 'luxon'\nimport { sha256 } from 'js-sha256'\nimport { Registry } from './registry'\nimport { validator } from '@nhtio/validation'\nimport { isInstanceOf, isError } from '../utils/guards'\nimport { canonicalStringify } from '../utils/canonical_json'\nimport { validateOrThrow, asyncValidateOrThrow, ValidationException } from '../utils/validation'\nimport { implementsSpooledArtifactConstructor } from '../contracts/spooled_artifact_constructor'\nimport {\n E_INVALID_INITIAL_TOOL_VALUE,\n E_INVALID_TOOL_ARGS,\n E_TOOL_DOWNSTREAM_ERROR,\n} from '../exceptions/runtime'\nimport type { Media } from './media'\nimport type { Schema, Description } from '@nhtio/validation'\nimport type { DispatchContext } from '../contracts/dispatch_context'\nimport type { SpooledArtifact, SpooledArtifactConstructor } from './spooled_artifact'\n\n/**\n * A zero-arg function that returns the {@link @nhtio/adk!SpooledArtifactConstructor} the consumer should\n * use when wrapping this tool's serialised output into a `ToolCall.results` field.\n *\n * @remarks\n * Why a resolver (and not the constructor itself)? `tool.ts` participates in a module-load\n * cycle with `spooled_artifact.ts` and `artifact_tool.ts` (`ArtifactTool extends Tool` closes\n * the loop). Any eager value-level reference to `SpooledArtifact` in `tool.ts` would crash the\n * cycle with a TDZ error. A resolver lets `tool.ts` validate \"is a function\" at module-load\n * time and defer the actual constructor check to validate-time (which always runs after every\n * module body has executed). Wrap-sites invoke `tool.artifactConstructor?.() ?? SpooledArtifact`\n * to obtain the final constructor.\n */\nexport type ArtifactConstructorResolver<A extends SpooledArtifact = SpooledArtifact> =\n () => SpooledArtifactConstructor<A>\n\n/**\n * The execution function for a {@link Tool}.\n *\n * @remarks\n * Receives the raw arguments passed to the executor, the active {@link @nhtio/adk!DispatchContext}, and the\n * tool's metadata registry.\n *\n * Return shapes:\n * - `string` / `Uint8Array` — opaque serialised output. The ADK does not persist the bytes\n * itself; the consumer's executor middleware is responsible for storing them and wrapping\n * them via `tool.artifactConstructor?.() ?? SpooledArtifact` when assembling the `ToolCall`\n * record.\n * - {@link @nhtio/adk!Media} / `Media[]` — explicit-modality silo. Bypasses\n * {@link Tool.artifactConstructor} — the handler returns the final result shape directly.\n * The LLM battery renders each `Media` as a provider-specific content block.\n */\nexport type ToolHandler = (\n args: unknown,\n ctx: DispatchContext,\n meta: Registry\n) => string | Uint8Array | Media | Media[] | Promise<string | Uint8Array | Media | Media[]>\n\n/**\n * Plain input object supplied to {@link Tool} at construction time.\n *\n * @typeParam A - The {@link @nhtio/adk!SpooledArtifact} subtype used to wrap this tool's results when\n * the consumer assembles a `ToolCall.results` field. Defaults to {@link @nhtio/adk!SpooledArtifact}\n * (plain text). Tools producing JSON output should set this to `SpooledJsonArtifact`; tools\n * producing markdown should set it to `SpooledMarkdownArtifact`; consumers can also pass a\n * custom subclass.\n */\nexport interface RawTool<A extends SpooledArtifact = SpooledArtifact> {\n /** Unique identifier used in LLM tool definitions. Recommend lowercase snake_case. */\n name: string\n /** Human-readable description passed to the model to explain what the tool does. */\n description: string\n /** @nhtio/validation schema for the tool's input arguments. Annotate with `.description()`, `.note()`, `.example()` etc. to produce rich LLM tool definitions via `.describe()`. */\n inputSchema: Schema\n /** Execution function. Not exposed as a public property — invoke via `executor()`. */\n handler: ToolHandler\n /**\n * Zero-arg resolver returning the {@link @nhtio/adk!SpooledArtifactConstructor} the consumer should use\n * when wrapping this tool's serialised output into a `ToolCall.results` field. Optional —\n * when omitted, wrap-sites fall back to {@link @nhtio/adk!SpooledArtifact} (plain text).\n *\n * @remarks\n * Recommended call shape: `artifactConstructor: () => SpooledJsonArtifact`. The closure is\n * the indirection that lets `tool.ts` validate this field without eagerly importing\n * `SpooledArtifact` (which would crash the `tool.ts ↔ spooled_artifact.ts ↔ artifact_tool.ts`\n * module-load cycle). At validate time the schema invokes the resolver and verifies its\n * return value is a `SpooledArtifact`-derived constructor — wrong-shape resolvers throw\n * {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_VALUE}.\n *\n * Wrap-sites (storage batteries, scripted executors) read the constructor via\n * `tool.artifactConstructor?.() ?? SpooledArtifact`.\n */\n artifactConstructor?: ArtifactConstructorResolver<A>\n /** Optional arbitrary metadata for this tool (e.g. RBAC scopes, feature flags). Defaults to `{}`. Stored in a {@link @nhtio/adk!Registry} for dot-path access. */\n meta?: Record<string, unknown>\n /**\n * When `true`, marks this tool as owned by a specific {@link @nhtio/adk!DispatchContext} so that\n * `ToolRegistry.pruneEphemeral()` will drop it at ctx-completion.\n *\n * @remarks\n * The flag is advisory at the `Tool` level — registries decide what to do with it. The canonical\n * producer of ephemeral tools is `SpooledArtifact.forgeTools(ctx)`, which sets this to `true`\n * on every artifact-query tool it emits.\n *\n * @defaultValue `false`\n */\n ephemeral?: boolean\n /**\n * When `true`, declares that this tool's output should be treated as **trusted developer/user\n * intent** rather than as untrusted third-party text when surfaced to the model.\n *\n * @remarks\n * LLM batteries read this flag per call when rendering tool-call results. The default\n * untrusted envelope (e.g. `<untrusted_content>` in the OpenAI Chat Completions battery) is the\n * secure-by-default treatment for arbitrary tool output. A tool whose output is authored by the\n * user or operator (Q&A tools surfacing user-authored answers, human-in-the-loop approval\n * gates, feedback-collection tools, configuration tools returning developer-authored\n * constants) sets this to `true` so the LLM battery routes the result through its trusted\n * envelope (`<trusted_content>` in the OpenAI Chat Completions battery).\n *\n * Trust is a property of the tool's output, not a property of how a particular battery is\n * wired — putting the flag here means the trust signal travels with the tool wherever it is\n * registered, no per-battery string lists, no name-matching to fail-open on typos.\n *\n * @defaultValue `false`\n */\n trusted?: boolean\n /**\n * Self-declared merge collision policy. Honoured by `ToolRegistry.merge` (NOT by\n * `ToolRegistry.register`) when this tool collides with another of the same name.\n *\n * @remarks\n * - `'throw'` (default): defer to the merge-level `options.onCollision`. If that is also\n * `'throw'`, the merge raises `E_TOOL_ALREADY_REGISTERED`. This matches the default behaviour\n * of `ToolRegistry.register`.\n * - `'replace'`: this tool always wins the collision, regardless of the merge-level option.\n * - `'keep'`: this tool always loses to any previously-registered tool of the same name.\n *\n * Forged artifact-query tools set this to `'replace'` so that merging multiple\n * `Subclass.forgeTools(ctx)` outputs (whose base-method tools overlap by name) resolves\n * silently — the descriptors, snapshot, and handler behaviour are interchangeable across\n * subclasses, so replacement is a behavioural no-op.\n *\n * @defaultValue `'throw'`\n */\n onCollision?: 'throw' | 'replace' | 'keep'\n}\n\n/**\n * Validator schema for a {@link RawTool}.\n */\nconst rawToolSchema = validator.object<RawTool>({\n name: validator.string().required(),\n description: validator.string().required(),\n inputSchema: validator\n .any()\n .custom((value, helpers) => {\n if (validator.isSchema(value) && (value as any).type === 'object') return value\n return helpers.error('any.invalid')\n })\n .required(),\n handler: validator.function().required(),\n artifactConstructor: validator\n .any()\n .custom((value, helpers) => {\n if (typeof value !== 'function') return helpers.error('any.invalid')\n // The resolver runs at validate time — well after the tool.ts ↔ spooled_artifact.ts ↔\n // artifact_tool.ts module cycle has fully unwound — so invoking it is safe. Delegate the\n // \"is this a SpooledArtifact-shaped constructor?\" check to the contract-level guard so\n // there's one canonical duck-type test (mirrors `implementsSpoolReader`'s pattern).\n let resolved: unknown\n try {\n resolved = (value as () => unknown)()\n } catch {\n return helpers.error('any.invalid')\n }\n if (implementsSpooledArtifactConstructor(resolved)) return value\n return helpers.error('any.invalid')\n })\n .optional(),\n meta: validator.object().pattern(validator.string(), validator.any()).default({}),\n ephemeral: validator.boolean().default(false),\n trusted: validator.boolean().default(false),\n onCollision: validator.string().valid('throw', 'replace', 'keep').default('throw'),\n})\n\n/**\n * A tool definition that serves as the single source of truth for a callable tool: its name,\n * description, input schema, execution handler, and the {@link @nhtio/adk!SpooledArtifact} subclass that\n * wraps its serialised output.\n *\n * @typeParam A - The {@link @nhtio/adk!SpooledArtifact} subtype this tool's results should be wrapped in.\n * Defaults to {@link @nhtio/adk!SpooledArtifact}.\n *\n * @remarks\n * The `inputSchema` is a `@nhtio/validation` schema. It is used at runtime to validate incoming\n * arguments before the handler is called, and its `.describe()` output provides all the metadata\n * needed to build a provider-specific LLM tool definition — annotate the schema with\n * `.description()`, `.note()`, `.example()` etc. once, and that information is available in both\n * contexts without duplication.\n *\n * The handler is private — invoke it only through `executor(ctx)` which validates args, fires\n * observability events (with a stable `callId` derived from the tool name and arguments), and\n * wraps handler errors in {@link @nhtio/adk!E_TOOL_DOWNSTREAM_ERROR}. The handler returns serialised bytes\n * (`string | Uint8Array`); persistence is the consumer's responsibility.\n *\n * `artifactConstructor` is the {@link @nhtio/adk!SpooledArtifact} subclass the consumer should use when\n * wrapping the handler's output into a `ToolCall.results` field. The author declares it once\n * on the tool instance; the consumer reads it when assembling persisted records.\n */\nexport class Tool<A extends SpooledArtifact = SpooledArtifact> {\n /**\n * Validator schema that accepts a {@link RawTool} object.\n *\n * @remarks\n * Reusable fragment for any schema that needs to validate or nest a tool entry\n * (e.g. `TurnRunnerConfig.tools`).\n */\n public static schema = rawToolSchema\n\n /**\n * Returns `true` if `value` is a {@link Tool} instance.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Tool} instance.\n */\n public static isTool(value: unknown): value is Tool {\n return isInstanceOf(value, 'Tool', Tool)\n }\n\n declare readonly name: string\n declare readonly description: string\n declare readonly inputSchema: Schema\n declare readonly artifactConstructor: ArtifactConstructorResolver<A> | undefined\n declare readonly meta: Registry\n declare readonly ephemeral: boolean\n declare readonly trusted: boolean\n declare readonly onCollision: 'throw' | 'replace' | 'keep'\n\n #name: string\n #description: string\n #inputSchema: Schema\n #handler: ToolHandler\n #artifactConstructor: ArtifactConstructorResolver<A> | undefined\n #meta: Registry\n #ephemeral: boolean\n #trusted: boolean\n #onCollision: 'throw' | 'replace' | 'keep'\n\n /**\n * @param raw - The raw tool input validated against `rawToolSchema`.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_TOOL_VALUE} when `raw` does not satisfy the schema.\n */\n constructor(raw: RawTool<A>) {\n let resolved: RawTool<A> & {\n meta: Record<string, unknown>\n ephemeral: boolean\n trusted: boolean\n onCollision: 'throw' | 'replace' | 'keep'\n }\n try {\n resolved = validateOrThrow<typeof resolved>(\n rawToolSchema,\n raw as RawTool,\n true\n ) as typeof resolved\n } catch (err) {\n throw new E_INVALID_INITIAL_TOOL_VALUE({ cause: isError(err) ? err : undefined })\n }\n\n this.#name = resolved.name\n this.#description = resolved.description\n this.#inputSchema = resolved.inputSchema\n this.#handler = resolved.handler\n this.#artifactConstructor = resolved.artifactConstructor as\n | ArtifactConstructorResolver<A>\n | undefined\n this.#meta = new Registry(resolved.meta)\n this.#ephemeral = resolved.ephemeral\n this.#trusted = resolved.trusted\n this.#onCollision = resolved.onCollision\n\n Object.defineProperties(this, {\n name: {\n get: () => this.#name,\n enumerable: true,\n configurable: false,\n },\n description: {\n get: () => this.#description,\n enumerable: true,\n configurable: false,\n },\n inputSchema: {\n get: () => this.#inputSchema,\n enumerable: true,\n configurable: false,\n },\n artifactConstructor: {\n get: () => this.#artifactConstructor,\n enumerable: true,\n configurable: false,\n },\n meta: {\n get: () => this.#meta,\n enumerable: true,\n configurable: false,\n },\n ephemeral: {\n get: () => this.#ephemeral,\n enumerable: true,\n configurable: false,\n },\n trusted: {\n get: () => this.#trusted,\n enumerable: true,\n configurable: false,\n },\n onCollision: {\n get: () => this.#onCollision,\n enumerable: true,\n configurable: false,\n },\n })\n }\n\n /**\n * Validates `args` against the tool's input schema asynchronously.\n *\n * @remarks\n * Async to support schemas with external validators (e.g. database lookups, API calls).\n * A validation failure throws {@link @nhtio/adk!E_INVALID_TOOL_ARGS} — this indicates a programming error\n * in the tool call loop, not a downstream failure.\n *\n * @param args - The arguments to validate.\n * @returns The validated (and coerced) arguments.\n * @throws {@link @nhtio/adk!E_INVALID_TOOL_ARGS} when `args` does not satisfy the input schema.\n */\n async validate(args: unknown): Promise<unknown> {\n try {\n return await asyncValidateOrThrow(this.#inputSchema, args)\n } catch (err) {\n if (isInstanceOf(err, 'ValidationException', ValidationException)) {\n throw new E_INVALID_TOOL_ARGS({ cause: err })\n }\n throw err\n }\n }\n\n /**\n * Returns a bound executor function for this tool against the given turn context.\n *\n * @remarks\n * The executor: (1) computes a stable `callId` as `sha256(canonicalStringify({tool, args}))`\n * over the **raw, pre-validation args**, (2) validates `args` via {@link Tool.validate},\n * (3) emits `toolExecutionStart` on the context (with the computed `callId`), (4) calls the\n * handler, (5) emits `toolExecutionEnd` (with the same `callId`), (6) wraps any handler error\n * in {@link @nhtio/adk!E_TOOL_DOWNSTREAM_ERROR} before re-throwing.\n *\n * The handler returns serialised bytes (`string | Uint8Array`) — persistence is the consumer's\n * concern. Use {@link Tool.artifactConstructor} when wrapping the bytes into a\n * `ToolCall.results` field.\n *\n * Pattern mirrors `Middleware.runner()` — call once per turn, reuse the returned function.\n *\n * @param ctx - The active turn context. Provides emit functions and turn ID.\n * @returns An async function `(args) => Promise<string | Uint8Array>`.\n */\n executor(\n ctx: DispatchContext\n ): (args: unknown) => Promise<string | Uint8Array | Media | Media[]> {\n return async (args: unknown): Promise<string | Uint8Array | Media | Media[]> => {\n // Compute callId over raw args (pre-validation) so two invocations with the same\n // (tool, raw args) produce the same identifier even if validation coerces values.\n const callId = sha256(canonicalStringify({ tool: this.#name, args }))\n const validatedArgs = await this.validate(args)\n const startedAt = DateTime.now()\n ctx.emitToolExecutionStart({\n toolName: this.#name,\n turnId: ctx.id,\n callId,\n args: validatedArgs,\n startedAt,\n })\n try {\n const result = await this.#handler(validatedArgs, ctx, this.#meta)\n const endedAt = DateTime.now()\n ctx.emitToolExecutionEnd({\n toolName: this.#name,\n turnId: ctx.id,\n callId,\n startedAt,\n endedAt,\n durationMs: endedAt.diff(startedAt).milliseconds,\n isError: false,\n })\n return result\n } catch (err) {\n const endedAt = DateTime.now()\n ctx.emitToolExecutionEnd({\n toolName: this.#name,\n turnId: ctx.id,\n callId,\n startedAt,\n endedAt,\n durationMs: endedAt.diff(startedAt).milliseconds,\n isError: true,\n })\n throw new E_TOOL_DOWNSTREAM_ERROR({ cause: isError(err) ? err : undefined })\n }\n }\n }\n\n /**\n * Returns a fully serialisable snapshot of this tool's definition.\n *\n * @remarks\n * The `inputSchema` property is the result of calling `.describe()` on the raw schema — a plain\n * object carrying all the annotation metadata (descriptions, notes, examples, types) without any\n * validator functions. Use this to build provider-specific LLM tool definitions.\n *\n * @returns `{ name, description, inputSchema }` where `inputSchema` is the schema description.\n */\n describe(): { name: string; description: string; inputSchema: Description } {\n return {\n name: this.#name,\n description: this.#description,\n inputSchema: this.#inputSchema.describe(),\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool_registry-BGHg6KTq.mjs","names":["#value","#cache","#store","#tools"],"sources":["../src/lib/utils/guards.ts","../src/lib/classes/tokenizable.ts","../src/lib/classes/registry.ts","../src/lib/utils/canonical_json.ts","../src/lib/classes/tool_registry.ts"],"sourcesContent":["import { passesSchema } from './validation'\nimport { validator } from '@nhtio/validation'\n\n/**\n * Returns `true` if `value` is an instance of the class identified by `type` (and optionally `ctor`).\n *\n * @remarks\n * Performs three checks in order: `instanceof ctor`, `Symbol.hasInstance`, then constructor-name\n * comparison. The constructor-name fallback handles cross-realm cases where `instanceof` fails.\n *\n * @typeParam T - The expected instance type.\n * @param value - The value to test.\n * @param type - The constructor name to compare against when `instanceof` is unavailable.\n * @param ctor - Optional constructor to use for `instanceof` and `Symbol.hasInstance` checks.\n * @returns `true` when `value` is an instance of the class described by `type`/`ctor`.\n */\nexport const isInstanceOf = <T>(\n value: unknown,\n type: string,\n ctor?: new (...args: any[]) => T\n): value is T => {\n // eslint-disable-next-line adk/use-is-instance-of -- this IS the implementation of isInstanceOf\n if ('undefined' !== typeof ctor && value instanceof ctor) return true\n /* istanbul ignore next 4 */\n if (\n 'undefined' !== typeof ctor &&\n typeof ctor[Symbol.hasInstance] === 'function' &&\n ctor[Symbol.hasInstance](value)\n )\n /* istanbul ignore next */\n return true\n // eslint-disable-next-line adk/prefer-is-object -- this guard is the building block isObject depends on (no circular usage)\n if ('object' === typeof value && null !== value) {\n const valueWithConstructor = value as { constructor?: Function }\n const constructorName = valueWithConstructor.constructor?.name\n return constructorName === type\n }\n return false\n}\n\nconst errorSchema = validator\n .any()\n .custom((value, helpers) => {\n if (isInstanceOf(value, 'Error', Error)) {\n return value\n }\n return helpers.error('any.invalid')\n })\n .required()\n\n/**\n * Returns `true` if `value` is an `Error` instance or satisfies the `Error` duck-type shape.\n *\n * @remarks\n * Returns `false` for `undefined` and `null` — the `Error` contract requires an actual instance.\n *\n * @param value - The value to test.\n * @returns `true` when `value` conforms to the `Error` shape.\n */\nexport const isError = (value: unknown): value is Error => {\n return passesSchema(errorSchema, value)\n}\n\n/**\n * Type guard to check if a value is a plain object (not null, not array)\n * @param value - The value to check\n * @returns True if the value is a plain object, false otherwise\n */\nexport const isObject = (value: unknown): value is { [key: string]: unknown } => {\n // eslint-disable-next-line adk/prefer-is-object -- this IS the implementation of isObject\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import { getEncoding } from 'js-tiktoken'\nimport { validator } from '@nhtio/validation'\nimport { isInstanceOf } from '../utils/guards'\nimport { LlamaTokenizer } from 'llama-tokenizer-js'\nimport { fromPreTrained as geminiFromPreTrained } from '@lenml/tokenizer-gemini'\nimport type { Tiktoken } from 'js-tiktoken'\n\n/**\n * The set of supported token encoding identifiers.\n *\n * @remarks\n * Each value maps to a specific estimation backend:\n * - `gpt2`, `r50k_base`, `p50k_base`, `p50k_edit`, `cl100k_base`, `o200k_base` — exact counts\n * via `js-tiktoken` (OpenAI / tiktoken-compatible models).\n * - `gemini` — exact counts via `@lenml/tokenizer-gemini`, which embeds Gemini's actual\n * SentencePiece vocabulary locally with no API call required.\n * - `llama2` — exact counts via `llama-tokenizer-js` (Llama 1 and 2). Llama 3+ uses a\n * different vocabulary and should use the `llama3` identifier once a suitable sync backend\n * is available.\n * - `claude` — heuristic approximation using Anthropic's published ~3.5 chars/token ratio.\n * No local tokenizer is available for Claude 3+ models; the Anthropic SDK's\n * `messages.countTokens()` API is the only exact path but requires a network call.\n *\n * When adding a new encoding, add a case to {@link Tokenizable.estimateTokens}.\n */\nexport const TokenEncoding = [\n 'gpt2',\n 'r50k_base',\n 'p50k_base',\n 'p50k_edit',\n 'cl100k_base',\n 'o200k_base',\n 'gemini',\n 'llama2',\n 'claude',\n] as const\n\n/**\n * Union of all recognised token encoding identifier strings.\n *\n * @remarks\n * Derived from {@link TokenEncoding} so the type and the runtime array stay in sync\n * automatically when new encodings are added.\n */\nexport type TokenEncoding = (typeof TokenEncoding)[number]\n\n/**\n * Backing schema for {@link Tokenizable.schema}.\n *\n * @remarks\n * Accepts a plain `string` or an existing {@link Tokenizable} instance. Strings pass through\n * unchanged; {@link Tokenizable} instances are accepted via {@link Tokenizable.isTokenizable}\n * to remain cross-realm safe.\n */\nconst stringOrTokenizableSchema = validator.alternatives(\n validator.string(),\n validator.custom((value, helpers) => {\n if (Tokenizable.isTokenizable(value)) {\n return value\n }\n return helpers.error('any.invalid')\n })\n)\n\n// Lazily-initialised singletons — tokenizers are expensive to load so we defer\n// until first use and reuse across all Tokenizable instances thereafter.\nlet geminiTokenizerInstance: ReturnType<typeof geminiFromPreTrained> | undefined\nlet llamaTokenizerInstance: InstanceType<typeof LlamaTokenizer> | undefined\n\nconst getGeminiTokenizer = () => {\n if (!geminiTokenizerInstance) {\n geminiTokenizerInstance = geminiFromPreTrained()\n }\n return geminiTokenizerInstance\n}\n\nconst getLlamaTokenizer = () => {\n if (!llamaTokenizerInstance) {\n llamaTokenizerInstance = new LlamaTokenizer()\n }\n return llamaTokenizerInstance\n}\n\n/**\n * A mutable string with a built-in token counter.\n *\n * @remarks\n * The wrapped string can be read via the standard coercion protocol and updated at any time via\n * {@link Tokenizable.set}. Token counts are computed lazily on first access per encoding and\n * cached until the value changes, avoiding redundant encoder invocations when the same content\n * is measured multiple times across a pipeline.\n *\n * Estimation is dispatched by encoding identifier — see {@link TokenEncoding} for the full list\n * of supported backends and their accuracy characteristics. Unrecognised encodings fall back to\n * a `ceil(length / 4)` character heuristic.\n *\n * The class implements the standard JS value-coercion protocol (`toString`, `valueOf`,\n * `toJSON`, `toLocaleString`, `Symbol.for('nodejs.util.inspect.custom')`) so instances behave\n * transparently as strings in most contexts.\n */\nexport class Tokenizable {\n public static TokenEncoding = TokenEncoding\n\n /**\n * Validator schema that accepts a plain `string` or a {@link Tokenizable} instance.\n *\n * @remarks\n * Reusable fragment for any schema that wants to accept either form — for example,\n * `systemPrompt` and each item in `standingInstructions` in `turnContextSchema`.\n */\n public static schema = stringOrTokenizableSchema\n\n declare toJSON: () => string\n declare toString: () => string\n declare valueOf: () => string\n declare toLocaleString: () => string\n declare set: (value: string) => void\n declare estimateTokens: (encoding: TokenEncoding) => number\n\n #value: string\n #cache: Map<TokenEncoding, number> = new Map()\n\n /**\n * @param value - The initial string value to wrap.\n */\n constructor(value: string) {\n this.#value = value\n\n const estimateTokensWithTiktoken = (encoding: TokenEncoding): number => {\n try {\n const enc: Tiktoken = getEncoding(encoding as any)\n return enc.encode(this.#value, []).length\n } catch {\n return Number.POSITIVE_INFINITY\n }\n }\n\n const estimateTokensWithGemini = (): number => {\n try {\n return getGeminiTokenizer().encode(this.#value).length\n } catch {\n return Number.POSITIVE_INFINITY\n }\n }\n\n const estimateTokensWithLlama2 = (): number => {\n try {\n return getLlamaTokenizer().encode(this.#value, false).length\n } catch {\n return Number.POSITIVE_INFINITY\n }\n }\n\n const estimateTokensWithClaudeHeuristic = (): number => {\n try {\n return Math.ceil(this.#value.length / 3.5)\n } catch {\n return Number.POSITIVE_INFINITY\n }\n }\n\n Object.defineProperties(this, {\n toJSON: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n toString: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n valueOf: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n toLocaleString: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n [Symbol.for('nodejs.util.inspect.custom')]: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n set: {\n value: (next: string) => {\n this.#value = next\n this.#cache.clear()\n },\n enumerable: false,\n configurable: false,\n writable: false,\n },\n estimateTokens: {\n value: (encoding: TokenEncoding): number => {\n if (this.#cache.has(encoding)) {\n return this.#cache.get(encoding)!\n }\n\n let estimate: number\n switch (encoding) {\n case 'gpt2':\n case 'r50k_base':\n case 'p50k_base':\n case 'p50k_edit':\n case 'cl100k_base':\n case 'o200k_base':\n estimate = estimateTokensWithTiktoken(encoding)\n break\n case 'gemini':\n estimate = estimateTokensWithGemini()\n break\n case 'llama2':\n estimate = estimateTokensWithLlama2()\n break\n case 'claude':\n estimate = estimateTokensWithClaudeHeuristic()\n break\n }\n if (estimate === Number.POSITIVE_INFINITY) {\n estimate = Math.ceil(this.#value.length / 4)\n } else {\n this.#cache.set(encoding, estimate)\n }\n return estimate\n },\n enumerable: false,\n configurable: false,\n writable: false,\n },\n })\n }\n\n /**\n * Convenience overload for one-off token counting without managing a {@link Tokenizable} instance.\n *\n * @remarks\n * Creates a temporary instance and immediately discards it — no caching benefit. Use the\n * instance method when you need to count the same value under multiple encodings or when the\n * value may change over time.\n *\n * @param value - The string to count tokens for.\n * @param encoding - The encoding identifier to use for counting.\n * @returns The estimated number of tokens.\n */\n public static estimateTokens(value: string, encoding: TokenEncoding): number {\n const temp = new Tokenizable(value)\n return temp.estimateTokens(encoding)\n }\n\n /**\n * Returns `true` if `value` is a {@link Tokenizable} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Tokenizable} instance.\n */\n public static isTokenizable(value: unknown): value is Tokenizable {\n return isInstanceOf(value, 'Tokenizable', Tokenizable)\n }\n}\n\n/**\n * Returns `true` if `value` is a {@link Tokenizable} instance.\n *\n * @remarks\n * Module-level convenience alias for {@link Tokenizable.isTokenizable}. Prefer this form when\n * you need a standalone type guard without importing the full class.\n *\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Tokenizable} instance.\n */\nexport const isTokenizable = (value: unknown): value is Tokenizable => {\n return isInstanceOf(value, 'Tokenizable', Tokenizable)\n}\n","import { dset } from 'dset'\nimport { klona } from 'klona'\nimport { default as delve } from 'dlv'\nimport { isInstanceOf, isObject } from '../utils/guards'\nimport { E_INVALID_INITIAL_REGISTRY_VALUE } from '../exceptions/runtime'\n\n/**\n * A controlled-mutation key-value store with dot-path access and deep-clone isolation.\n *\n * @remarks\n * The registry enforces a safe read/write contract: callers never hold a live reference into\n * the internal store. Every value that enters (`set`) or leaves (`get`, `all`) is deep-cloned\n * via `klona`, so mutations to a retrieved value cannot affect stored state and vice versa.\n *\n * Keys are dot-delimited paths (e.g. `\"user.profile.name\"`), resolved via `dlv` for reads and\n * `dset` for writes; intermediate objects are created automatically on write.\n */\nexport class Registry {\n #store: Record<string, unknown>\n\n /**\n * @param initial - Optional plain object to seed the registry. Deep-cloned on construction.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_REGISTRY_VALUE} when `initial` is defined but not a plain object.\n */\n constructor(initial?: Record<string, unknown>) {\n if ('undefined' !== typeof initial && !isObject(initial)) {\n throw new E_INVALID_INITIAL_REGISTRY_VALUE()\n }\n this.#store = initial ? klona(initial) : {}\n }\n\n /**\n * Returns `true` if `value` is a {@link Registry} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Registry} instance.\n */\n public static isRegistry(value: unknown): value is Registry {\n return isInstanceOf(value, 'Registry', Registry)\n }\n\n /**\n * Retrieves the value at `key`, returning `defaultValue` if the path is absent.\n *\n * @remarks\n * The returned value is a deep clone — mutating it will not affect the stored state.\n *\n * @typeParam T - Expected type of the value at `key`.\n * @param key - Dot-delimited path into the store (e.g. `\"user.name\"`).\n * @param defaultValue - Fallback returned when the path resolves to `undefined`.\n * @returns A deep clone of the stored value cast to `T`, or `defaultValue` when the path is absent.\n */\n get<T = unknown>(key: string, defaultValue?: T): T {\n const cloned = klona(this.#store)\n const value = delve(cloned, key)\n return 'undefined' === typeof value ? (defaultValue as T) : (value as T)\n }\n\n /**\n * Sets the value at `key`, creating intermediate objects as needed.\n *\n * @remarks\n * The stored value is isolated from the caller — mutating `value` after this call will not\n * affect what is held in the registry.\n *\n * @param key - Dot-delimited path into the store (e.g. `\"user.name\"`).\n * @param value - Value to store at the path.\n */\n set(key: string, value: unknown): void {\n dset(this.#store, key, value)\n }\n\n /**\n * Returns `true` if the registry has a value at `key`, `false` otherwise.\n *\n * @remarks\n * A key resolving to `undefined` is treated as absent — same convention as {@link Registry.get}'s\n * `defaultValue` fallback. No clone is performed; this is a pure existence check.\n *\n * @param key - Dot-delimited path into the store (e.g. `\"user.name\"`).\n * @returns `true` when the path resolves to a value other than `undefined`.\n */\n has(key: string): boolean {\n return 'undefined' !== typeof delve(this.#store, key)\n }\n\n /**\n * Returns all leaf dot-paths present in the registry.\n *\n * @remarks\n * The store is deep-cloned before traversal. Plain objects are walked recursively with path\n * segments joined by dots; arrays, primitives, `null`, and class instances are treated as leaves.\n *\n * @returns A string array of dot-delimited paths to leaf values in the store.\n */\n keys(): string[] {\n const store = klona(this.#store)\n const keys: string[] = []\n\n const isPlainRecord = (value: unknown): value is Record<string, unknown> => {\n if (!isObject(value)) return false\n const prototype = Object.getPrototypeOf(value)\n return prototype === Object.prototype || prototype === null\n }\n\n const walk = (value: unknown, segments: string[]): void => {\n if (!isPlainRecord(value)) {\n if (segments.length > 0) keys.push(segments.join('.'))\n return\n }\n\n for (const [segment, child] of Object.entries(value)) {\n walk(child, [...segments, segment])\n }\n }\n\n walk(store, [])\n return keys\n }\n\n /**\n * Returns a deep clone of the entire store contents.\n *\n * @returns A plain object snapshot of all stored key-value pairs.\n */\n all(): Record<string, unknown> {\n return klona(this.#store)\n }\n}\n","/**\n * Canonical `JSON.stringify` that sorts object keys recursively so that semantically-equal\n * objects produce identical strings.\n *\n * @remarks\n * Used wherever the ADK derives a stable identity from a structured value — for example,\n * `Tool.executor` computing the `callId` for `ToolExecutionStart`/`End` events, and the\n * `reportToolCall` executor helper computing the `checksum` field on `TurnToolCallContent`.\n * Both code paths hash `canonicalStringify({ tool, args })` so that argument key order does not\n * affect the resulting identifier.\n *\n * Arrays are serialised in their declared order (order is meaningful for an array). Object keys\n * are sorted with `Array.prototype.sort()`'s default lexicographic comparator.\n *\n * @param value - The value to serialise.\n * @returns A canonical JSON string representation of `value`.\n */\nexport function canonicalStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value)\n if (Array.isArray(value)) return '[' + value.map((v) => canonicalStringify(v)).join(',') + ']'\n const obj = value as Record<string, unknown>\n const keys = Object.keys(obj).sort()\n return '{' + keys.map((k) => JSON.stringify(k) + ':' + canonicalStringify(obj[k])).join(',') + '}'\n}\n","import { isInstanceOf } from '../utils/guards'\nimport { E_TOOL_ALREADY_REGISTERED } from '../exceptions/runtime'\nimport type { Tool } from './tool'\nimport type { DispatchContext } from '../contracts/dispatch_context'\n\n/**\n * Options accepted by {@link ToolRegistry.merge}.\n */\nexport interface MergeOptions {\n /**\n * What to do when two registries contain a tool with the same name AND neither tool's own\n * `onCollision` resolves the collision.\n *\n * @remarks\n * - `'throw'` (default): raise {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} on the first unresolved\n * collision. Mirrors the default behaviour of {@link ToolRegistry.register} and surfaces\n * accidental name shadowing immediately.\n * - `'replace'`: the later registry's tool wins.\n * - `'keep'`: the earlier registry's tool wins; later occurrences are dropped.\n *\n * Per-tool {@link @nhtio/adk!Tool.onCollision} takes precedence: if the incoming tool declares\n * `'replace'` or `'keep'`, that policy wins regardless of this option. Only when the incoming\n * tool's policy is `'throw'` (the default) does this fallback apply.\n *\n * @defaultValue `'throw'`\n */\n onCollision?: 'throw' | 'replace' | 'keep'\n}\n\n/**\n * A mutable, turn-scoped collection of {@link @nhtio/adk!Tool} instances.\n *\n * @remarks\n * Each `TurnRunner.run()` call constructs a fresh `ToolRegistry` from the runner's configured\n * baseline tools, so middleware edits are isolated to the current turn and cannot bleed across\n * concurrent or subsequent turns.\n *\n * `Tool` instances are immutable, so `all()` returns a fresh array without deep-cloning.\n *\n * `register()` throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} if a tool with the same name is already\n * present — pass `overwrite: true` to replace it explicitly.\n */\nexport class ToolRegistry {\n #tools: Map<string, Tool>\n\n /**\n * Returns `true` if `value` is a {@link ToolRegistry} instance.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link ToolRegistry} instance.\n */\n public static isToolRegistry(value: unknown): value is ToolRegistry {\n return isInstanceOf(value, 'ToolRegistry', ToolRegistry)\n }\n\n /**\n * @param tools - Optional initial tools. Insertion order is preserved. Duplicate names throw\n * {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} — ensure each tool has a unique name.\n * @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when two tools in `tools` share a name.\n */\n constructor(tools?: Tool[]) {\n this.#tools = new Map()\n for (const tool of tools ?? []) {\n this.register(tool)\n }\n }\n\n /**\n * Adds a tool to the registry.\n *\n * @param tool - The tool to register.\n * @param overwrite - When `true`, silently replaces an existing tool with the same name.\n * Defaults to `false`.\n * @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when a tool with the same name is already registered\n * and `overwrite` is not `true`.\n */\n register(tool: Tool, overwrite?: boolean): void {\n if (this.#tools.has(tool.name) && !overwrite) {\n throw new E_TOOL_ALREADY_REGISTERED()\n }\n this.#tools.set(tool.name, tool)\n }\n\n /**\n * Removes the tool with the given name from the registry.\n *\n * @remarks\n * No-ops if no tool with that name is registered.\n *\n * @param name - The name of the tool to remove.\n */\n unregister(name: string): void {\n this.#tools.delete(name)\n }\n\n /**\n * Returns the tool registered under `name`, or `undefined` if not present.\n *\n * @param name - The tool name to look up.\n */\n get(name: string): Tool | undefined {\n return this.#tools.get(name)\n }\n\n /**\n * Returns `true` if a tool with the given name is registered.\n *\n * @param name - The tool name to test.\n */\n has(name: string): boolean {\n return this.#tools.has(name)\n }\n\n /**\n * Returns a fresh array of all registered tools in insertion order.\n *\n * @remarks\n * Since {@link @nhtio/adk!Tool} instances are immutable, no deep-cloning is needed.\n */\n all(): Tool[] {\n return Array.from(this.#tools.values())\n }\n\n /**\n * Removes every tool whose {@link @nhtio/adk!Tool.ephemeral} flag is `true`.\n *\n * @remarks\n * Synchronous and idempotent — calling it twice in a row is a no-op the second time. The\n * canonical caller is {@link ToolRegistry.bindContext}, which schedules this method to run\n * at {@link @nhtio/adk!DispatchContext.ack}. Non-ephemeral tools are left untouched.\n */\n pruneEphemeral(): void {\n for (const [name, tool] of this.#tools) {\n if (tool.ephemeral) {\n this.#tools.delete(name)\n }\n }\n }\n\n /**\n * Binds this registry to a {@link @nhtio/adk!DispatchContext} so that {@link pruneEphemeral} runs\n * automatically when the context is acked.\n *\n * @remarks\n * The handler does NOT fire on {@link @nhtio/adk!DispatchContext.nack} — failed executor runs leave\n * any forged tools in place so the consumer can inspect what was registered when debugging the\n * failure. Subscriptions are short-lived and die with the context regardless.\n *\n * Forgetting this call after merging in `Subclass.forgeTools(ctx)` output means ephemeral tools\n * accumulate across executor invocations, and subsequent `forgeTools(ctx)` calls in later\n * iterations will see a stale `callId` enum that excludes new tool calls. The plan-documented\n * pattern is:\n *\n * ```ts\n * const executor: DispatchExecutorFn = async (ctx) => {\n * const forged = SpooledArtifact.forgeTools(ctx)\n * const merged = ToolRegistry.merge([main, forged])\n * main.bindContext(ctx)\n * const result = await llm.invoke({ tools: merged.all(), ... })\n * ctx.ack()\n * }\n * ```\n *\n * @param ctx - The execution context whose `ack` event should trigger pruning.\n * @returns An unsubscribe function — calling it before `ctx.ack()` prevents pruning. Rarely\n * useful outside of tests.\n *\n * @see {@link @nhtio/adk!SpooledArtifact.forgeTools}\n * @see {@link @nhtio/adk!DispatchContext.onAck}\n */\n bindContext(ctx: DispatchContext): () => void {\n return ctx.onAck(() => this.pruneEphemeral())\n }\n\n /**\n * Combines multiple {@link ToolRegistry} instances into a fresh registry without mutating any\n * input.\n *\n * @remarks\n * Iteration is left-to-right across `registries` and then in each registry's insertion order.\n * Collisions are resolved by consulting the **incoming** tool's {@link @nhtio/adk!Tool.onCollision} first:\n *\n * - `'replace'` (per-tool): the incoming tool wins, replacing the existing entry.\n * - `'keep'` (per-tool): the existing entry wins; the incoming tool is dropped.\n * - `'throw'` (per-tool, the default): fall back to the merge-level `options.onCollision`.\n *\n * The merge-level `options.onCollision` defaults to `'throw'`, which mirrors {@link register}.\n *\n * The result is a brand-new registry; no input is mutated and no event subscription is\n * propagated. Each `Tool`'s `ephemeral` flag carries through unchanged — the flag lives on the\n * tool, not the registry, so `bindContext(ctx)` on the merged registry will prune the forged\n * tools as expected.\n *\n * @param registries - Registries to merge, in priority order (left-to-right insertion).\n * @param options - Merge-level collision policy. Defaults to `{ onCollision: 'throw' }`.\n * @returns A fresh {@link ToolRegistry} containing the resolved union of all inputs.\n * @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when the resolved collision policy is `'throw'`\n * and a collision occurs.\n */\n static merge(registries: ToolRegistry[], options?: MergeOptions): ToolRegistry {\n const policy = options?.onCollision ?? 'throw'\n const merged = new ToolRegistry()\n for (const registry of registries) {\n for (const tool of registry.all()) {\n const existing = merged.get(tool.name)\n if (!existing) {\n merged.register(tool)\n continue\n }\n const incomingPolicy = tool.onCollision\n if (incomingPolicy === 'replace') {\n merged.register(tool, true)\n continue\n }\n if (incomingPolicy === 'keep') {\n continue\n }\n // Incoming policy is 'throw' — fall back to the merge-level option.\n if (policy === 'replace') {\n merged.register(tool, true)\n continue\n }\n if (policy === 'keep') {\n continue\n }\n throw new E_TOOL_ALREADY_REGISTERED()\n }\n }\n return merged\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAgBA,IAAa,gBACX,OACA,MACA,SACe;CAEf,IAAI,gBAAgB,OAAO,QAAQ,iBAAiB,MAAM,OAAO;;CAEjE,IACE,gBAAgB,OAAO,QACvB,OAAO,KAAK,OAAO,iBAAiB,cACpC,KAAK,OAAO,aAAa,KAAK;;CAG9B,OAAO;CAET,IAAI,aAAa,OAAO,SAAS,SAAS,OAGxC,OADwB,MAAqB,aAAa,SAC/B;CAE7B,OAAO;AACT;AAEA,IAAM,cAAc,UACjB,IAAI,EACJ,QAAQ,OAAO,YAAY;CAC1B,IAAI,aAAa,OAAO,SAAS,KAAK,GACpC,OAAO;CAET,OAAO,QAAQ,MAAM,aAAa;AACpC,CAAC,EACA,SAAS;;;;;;;;;;AAWZ,IAAa,WAAW,UAAmC;CACzD,OAAO,aAAa,aAAa,KAAK;AACxC;;;;;;AAOA,IAAa,YAAY,UAAwD;CAE/E,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;;;;;;;;;;;;;;;;;;;;;AC9CA,IAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;;;;;AAmBA,IAAM,4BAA4B,UAAU,aAC1C,UAAU,OAAO,GACjB,UAAU,QAAQ,OAAO,YAAY;CACnC,IAAI,YAAY,cAAc,KAAK,GACjC,OAAO;CAET,OAAO,QAAQ,MAAM,aAAa;AACpC,CAAC,CACH;AAIA,IAAI;AACJ,IAAI;AAEJ,IAAM,2BAA2B;CAC/B,IAAI,CAAC,yBACH,0BAA0B,eAAqB;CAEjD,OAAO;AACT;AAEA,IAAM,0BAA0B;CAC9B,IAAI,CAAC,wBACH,yBAAyB,IAAI,eAAe;CAE9C,OAAO;AACT;;;;;;;;;;;;;;;;;;AAmBA,IAAa,cAAb,MAAa,YAAY;CACvB,OAAc,gBAAgB;;;;;;;;CAS9B,OAAc,SAAS;CASvB;CACA,yBAAqC,IAAI,IAAI;;;;CAK7C,YAAY,OAAe;EACzB,KAAKA,SAAS;EAEd,MAAM,8BAA8B,aAAoC;GACtE,IAAI;IAEF,OADsB,YAAY,QAC3B,EAAI,OAAO,KAAKA,QAAQ,CAAC,CAAC,EAAE;GACrC,QAAQ;IACN,OAAO,OAAO;GAChB;EACF;EAEA,MAAM,iCAAyC;GAC7C,IAAI;IACF,OAAO,mBAAmB,EAAE,OAAO,KAAKA,MAAM,EAAE;GAClD,QAAQ;IACN,OAAO,OAAO;GAChB;EACF;EAEA,MAAM,iCAAyC;GAC7C,IAAI;IACF,OAAO,kBAAkB,EAAE,OAAO,KAAKA,QAAQ,KAAK,EAAE;GACxD,QAAQ;IACN,OAAO,OAAO;GAChB;EACF;EAEA,MAAM,0CAAkD;GACtD,IAAI;IACF,OAAO,KAAK,KAAK,KAAKA,OAAO,SAAS,GAAG;GAC3C,QAAQ;IACN,OAAO,OAAO;GAChB;EACF;EAEA,OAAO,iBAAiB,MAAM;GAC5B,QAAQ;IACN,aAAa,KAAKA;IAClB,YAAY;IACZ,cAAc;IACd,UAAU;GACZ;GACA,UAAU;IACR,aAAa,KAAKA;IAClB,YAAY;IACZ,cAAc;IACd,UAAU;GACZ;GACA,SAAS;IACP,aAAa,KAAKA;IAClB,YAAY;IACZ,cAAc;IACd,UAAU;GACZ;GACA,gBAAgB;IACd,aAAa,KAAKA;IAClB,YAAY;IACZ,cAAc;IACd,UAAU;GACZ;IACC,OAAO,IAAI,4BAA4B,IAAI;IAC1C,aAAa,KAAKA;IAClB,YAAY;IACZ,cAAc;IACd,UAAU;GACZ;GACA,KAAK;IACH,QAAQ,SAAiB;KACvB,KAAKA,SAAS;KACd,KAAKC,OAAO,MAAM;IACpB;IACA,YAAY;IACZ,cAAc;IACd,UAAU;GACZ;GACA,gBAAgB;IACd,QAAQ,aAAoC;KAC1C,IAAI,KAAKA,OAAO,IAAI,QAAQ,GAC1B,OAAO,KAAKA,OAAO,IAAI,QAAQ;KAGjC,IAAI;KACJ,QAAQ,UAAR;MACE,KAAK;MACL,KAAK;MACL,KAAK;MACL,KAAK;MACL,KAAK;MACL,KAAK;OACH,WAAW,2BAA2B,QAAQ;OAC9C;MACF,KAAK;OACH,WAAW,yBAAyB;OACpC;MACF,KAAK;OACH,WAAW,yBAAyB;OACpC;MACF,KAAK;OACH,WAAW,kCAAkC;OAC7C;KACJ;KACA,IAAI,aAAa,OAAO,mBACtB,WAAW,KAAK,KAAK,KAAKD,OAAO,SAAS,CAAC;UAE3C,KAAKC,OAAO,IAAI,UAAU,QAAQ;KAEpC,OAAO;IACT;IACA,YAAY;IACZ,cAAc;IACd,UAAU;GACZ;EACF,CAAC;CACH;;;;;;;;;;;;;CAcA,OAAc,eAAe,OAAe,UAAiC;EAE3E,OAAO,IADU,YAAY,KACtB,EAAK,eAAe,QAAQ;CACrC;;;;;;;;;;;CAYA,OAAc,cAAc,OAAsC;EAChE,OAAO,aAAa,OAAO,eAAe,WAAW;CACvD;AACF;;;;;;;;;;;;;;AC9PA,IAAa,WAAb,MAAa,SAAS;CACpB;;;;;CAMA,YAAY,SAAmC;EAC7C,IAAI,gBAAgB,OAAO,WAAW,CAAC,SAAS,OAAO,GACrD,MAAM,IAAI,iCAAiC;EAE7C,KAAKC,SAAS,UAAU,MAAM,OAAO,IAAI,CAAC;CAC5C;;;;;;;;;;CAWA,OAAc,WAAW,OAAmC;EAC1D,OAAO,aAAa,OAAO,YAAY,QAAQ;CACjD;;;;;;;;;;;;CAaA,IAAiB,KAAa,cAAqB;EAEjD,MAAM,QAAQ,MADC,MAAM,KAAKA,MACN,GAAQ,GAAG;EAC/B,OAAO,gBAAgB,OAAO,QAAS,eAAsB;CAC/D;;;;;;;;;;;CAYA,IAAI,KAAa,OAAsB;EACrC,KAAK,KAAKA,QAAQ,KAAK,KAAK;CAC9B;;;;;;;;;;;CAYA,IAAI,KAAsB;EACxB,OAAO,gBAAgB,OAAO,MAAM,KAAKA,QAAQ,GAAG;CACtD;;;;;;;;;;CAWA,OAAiB;EACf,MAAM,QAAQ,MAAM,KAAKA,MAAM;EAC/B,MAAM,OAAiB,CAAC;EAExB,MAAM,iBAAiB,UAAqD;GAC1E,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO;GAC7B,MAAM,YAAY,OAAO,eAAe,KAAK;GAC7C,OAAO,cAAc,OAAO,aAAa,cAAc;EACzD;EAEA,MAAM,QAAQ,OAAgB,aAA6B;GACzD,IAAI,CAAC,cAAc,KAAK,GAAG;IACzB,IAAI,SAAS,SAAS,GAAG,KAAK,KAAK,SAAS,KAAK,GAAG,CAAC;IACrD;GACF;GAEA,KAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,KAAK,GACjD,KAAK,OAAO,CAAC,GAAG,UAAU,OAAO,CAAC;EAEtC;EAEA,KAAK,OAAO,CAAC,CAAC;EACd,OAAO;CACT;;;;;;CAOA,MAA+B;EAC7B,OAAO,MAAM,KAAKA,MAAM;CAC1B;AACF;;;;;;;;;;;;;;;;;;;;AClHA,SAAgB,mBAAmB,OAAwB;CACzD,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO,KAAK,UAAU,KAAK;CAC5E,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,MAAM,KAAK,MAAM,mBAAmB,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;CAC3F,MAAM,MAAM;CAEZ,OAAO,MADM,OAAO,KAAK,GAAG,EAAE,KACjB,EAAK,KAAK,MAAM,KAAK,UAAU,CAAC,IAAI,MAAM,mBAAmB,IAAI,EAAE,CAAC,EAAE,KAAK,GAAG,IAAI;AACjG;;;;;;;;;;;;;;;;ACmBA,IAAa,eAAb,MAAa,aAAa;CACxB;;;;;;;CAQA,OAAc,eAAe,OAAuC;EAClE,OAAO,aAAa,OAAO,gBAAgB,YAAY;CACzD;;;;;;CAOA,YAAY,OAAgB;EAC1B,KAAKC,yBAAS,IAAI,IAAI;EACtB,KAAK,MAAM,QAAQ,SAAS,CAAC,GAC3B,KAAK,SAAS,IAAI;CAEtB;;;;;;;;;;CAWA,SAAS,MAAY,WAA2B;EAC9C,IAAI,KAAKA,OAAO,IAAI,KAAK,IAAI,KAAK,CAAC,WACjC,MAAM,IAAI,0BAA0B;EAEtC,KAAKA,OAAO,IAAI,KAAK,MAAM,IAAI;CACjC;;;;;;;;;CAUA,WAAW,MAAoB;EAC7B,KAAKA,OAAO,OAAO,IAAI;CACzB;;;;;;CAOA,IAAI,MAAgC;EAClC,OAAO,KAAKA,OAAO,IAAI,IAAI;CAC7B;;;;;;CAOA,IAAI,MAAuB;EACzB,OAAO,KAAKA,OAAO,IAAI,IAAI;CAC7B;;;;;;;CAQA,MAAc;EACZ,OAAO,MAAM,KAAK,KAAKA,OAAO,OAAO,CAAC;CACxC;;;;;;;;;CAUA,iBAAuB;EACrB,KAAK,MAAM,CAAC,MAAM,SAAS,KAAKA,QAC9B,IAAI,KAAK,WACP,KAAKA,OAAO,OAAO,IAAI;CAG7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCA,YAAY,KAAkC;EAC5C,OAAO,IAAI,YAAY,KAAK,eAAe,CAAC;CAC9C;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BA,OAAO,MAAM,YAA4B,SAAsC;EAC7E,MAAM,SAAS,SAAS,eAAe;EACvC,MAAM,SAAS,IAAI,aAAa;EAChC,KAAK,MAAM,YAAY,YACrB,KAAK,MAAM,QAAQ,SAAS,IAAI,GAAG;GAEjC,IAAI,CADa,OAAO,IAAI,KAAK,IAC5B,GAAU;IACb,OAAO,SAAS,IAAI;IACpB;GACF;GACA,MAAM,iBAAiB,KAAK;GAC5B,IAAI,mBAAmB,WAAW;IAChC,OAAO,SAAS,MAAM,IAAI;IAC1B;GACF;GACA,IAAI,mBAAmB,QACrB;GAGF,IAAI,WAAW,WAAW;IACxB,OAAO,SAAS,MAAM,IAAI;IAC1B;GACF;GACA,IAAI,WAAW,QACb;GAEF,MAAM,IAAI,0BAA0B;EACtC;EAEF,OAAO;CACT;AACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool_registry-CtCQ4Xoz.js","names":["#value","#cache","#store","#tools"],"sources":["../src/lib/utils/guards.ts","../src/lib/classes/tokenizable.ts","../src/lib/classes/registry.ts","../src/lib/utils/canonical_json.ts","../src/lib/classes/tool_registry.ts"],"sourcesContent":["import { passesSchema } from './validation'\nimport { validator } from '@nhtio/validation'\n\n/**\n * Returns `true` if `value` is an instance of the class identified by `type` (and optionally `ctor`).\n *\n * @remarks\n * Performs three checks in order: `instanceof ctor`, `Symbol.hasInstance`, then constructor-name\n * comparison. The constructor-name fallback handles cross-realm cases where `instanceof` fails.\n *\n * @typeParam T - The expected instance type.\n * @param value - The value to test.\n * @param type - The constructor name to compare against when `instanceof` is unavailable.\n * @param ctor - Optional constructor to use for `instanceof` and `Symbol.hasInstance` checks.\n * @returns `true` when `value` is an instance of the class described by `type`/`ctor`.\n */\nexport const isInstanceOf = <T>(\n value: unknown,\n type: string,\n ctor?: new (...args: any[]) => T\n): value is T => {\n // eslint-disable-next-line adk/use-is-instance-of -- this IS the implementation of isInstanceOf\n if ('undefined' !== typeof ctor && value instanceof ctor) return true\n /* istanbul ignore next 4 */\n if (\n 'undefined' !== typeof ctor &&\n typeof ctor[Symbol.hasInstance] === 'function' &&\n ctor[Symbol.hasInstance](value)\n )\n /* istanbul ignore next */\n return true\n // eslint-disable-next-line adk/prefer-is-object -- this guard is the building block isObject depends on (no circular usage)\n if ('object' === typeof value && null !== value) {\n const valueWithConstructor = value as { constructor?: Function }\n const constructorName = valueWithConstructor.constructor?.name\n return constructorName === type\n }\n return false\n}\n\nconst errorSchema = validator\n .any()\n .custom((value, helpers) => {\n if (isInstanceOf(value, 'Error', Error)) {\n return value\n }\n return helpers.error('any.invalid')\n })\n .required()\n\n/**\n * Returns `true` if `value` is an `Error` instance or satisfies the `Error` duck-type shape.\n *\n * @remarks\n * Returns `false` for `undefined` and `null` — the `Error` contract requires an actual instance.\n *\n * @param value - The value to test.\n * @returns `true` when `value` conforms to the `Error` shape.\n */\nexport const isError = (value: unknown): value is Error => {\n return passesSchema(errorSchema, value)\n}\n\n/**\n * Type guard to check if a value is a plain object (not null, not array)\n * @param value - The value to check\n * @returns True if the value is a plain object, false otherwise\n */\nexport const isObject = (value: unknown): value is { [key: string]: unknown } => {\n // eslint-disable-next-line adk/prefer-is-object -- this IS the implementation of isObject\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","import { getEncoding } from 'js-tiktoken'\nimport { validator } from '@nhtio/validation'\nimport { isInstanceOf } from '../utils/guards'\nimport { LlamaTokenizer } from 'llama-tokenizer-js'\nimport { fromPreTrained as geminiFromPreTrained } from '@lenml/tokenizer-gemini'\nimport type { Tiktoken } from 'js-tiktoken'\n\n/**\n * The set of supported token encoding identifiers.\n *\n * @remarks\n * Each value maps to a specific estimation backend:\n * - `gpt2`, `r50k_base`, `p50k_base`, `p50k_edit`, `cl100k_base`, `o200k_base` — exact counts\n * via `js-tiktoken` (OpenAI / tiktoken-compatible models).\n * - `gemini` — exact counts via `@lenml/tokenizer-gemini`, which embeds Gemini's actual\n * SentencePiece vocabulary locally with no API call required.\n * - `llama2` — exact counts via `llama-tokenizer-js` (Llama 1 and 2). Llama 3+ uses a\n * different vocabulary and should use the `llama3` identifier once a suitable sync backend\n * is available.\n * - `claude` — heuristic approximation using Anthropic's published ~3.5 chars/token ratio.\n * No local tokenizer is available for Claude 3+ models; the Anthropic SDK's\n * `messages.countTokens()` API is the only exact path but requires a network call.\n *\n * When adding a new encoding, add a case to {@link Tokenizable.estimateTokens}.\n */\nexport const TokenEncoding = [\n 'gpt2',\n 'r50k_base',\n 'p50k_base',\n 'p50k_edit',\n 'cl100k_base',\n 'o200k_base',\n 'gemini',\n 'llama2',\n 'claude',\n] as const\n\n/**\n * Union of all recognised token encoding identifier strings.\n *\n * @remarks\n * Derived from {@link TokenEncoding} so the type and the runtime array stay in sync\n * automatically when new encodings are added.\n */\nexport type TokenEncoding = (typeof TokenEncoding)[number]\n\n/**\n * Backing schema for {@link Tokenizable.schema}.\n *\n * @remarks\n * Accepts a plain `string` or an existing {@link Tokenizable} instance. Strings pass through\n * unchanged; {@link Tokenizable} instances are accepted via {@link Tokenizable.isTokenizable}\n * to remain cross-realm safe.\n */\nconst stringOrTokenizableSchema = validator.alternatives(\n validator.string(),\n validator.custom((value, helpers) => {\n if (Tokenizable.isTokenizable(value)) {\n return value\n }\n return helpers.error('any.invalid')\n })\n)\n\n// Lazily-initialised singletons — tokenizers are expensive to load so we defer\n// until first use and reuse across all Tokenizable instances thereafter.\nlet geminiTokenizerInstance: ReturnType<typeof geminiFromPreTrained> | undefined\nlet llamaTokenizerInstance: InstanceType<typeof LlamaTokenizer> | undefined\n\nconst getGeminiTokenizer = () => {\n if (!geminiTokenizerInstance) {\n geminiTokenizerInstance = geminiFromPreTrained()\n }\n return geminiTokenizerInstance\n}\n\nconst getLlamaTokenizer = () => {\n if (!llamaTokenizerInstance) {\n llamaTokenizerInstance = new LlamaTokenizer()\n }\n return llamaTokenizerInstance\n}\n\n/**\n * A mutable string with a built-in token counter.\n *\n * @remarks\n * The wrapped string can be read via the standard coercion protocol and updated at any time via\n * {@link Tokenizable.set}. Token counts are computed lazily on first access per encoding and\n * cached until the value changes, avoiding redundant encoder invocations when the same content\n * is measured multiple times across a pipeline.\n *\n * Estimation is dispatched by encoding identifier — see {@link TokenEncoding} for the full list\n * of supported backends and their accuracy characteristics. Unrecognised encodings fall back to\n * a `ceil(length / 4)` character heuristic.\n *\n * The class implements the standard JS value-coercion protocol (`toString`, `valueOf`,\n * `toJSON`, `toLocaleString`, `Symbol.for('nodejs.util.inspect.custom')`) so instances behave\n * transparently as strings in most contexts.\n */\nexport class Tokenizable {\n public static TokenEncoding = TokenEncoding\n\n /**\n * Validator schema that accepts a plain `string` or a {@link Tokenizable} instance.\n *\n * @remarks\n * Reusable fragment for any schema that wants to accept either form — for example,\n * `systemPrompt` and each item in `standingInstructions` in `turnContextSchema`.\n */\n public static schema = stringOrTokenizableSchema\n\n declare toJSON: () => string\n declare toString: () => string\n declare valueOf: () => string\n declare toLocaleString: () => string\n declare set: (value: string) => void\n declare estimateTokens: (encoding: TokenEncoding) => number\n\n #value: string\n #cache: Map<TokenEncoding, number> = new Map()\n\n /**\n * @param value - The initial string value to wrap.\n */\n constructor(value: string) {\n this.#value = value\n\n const estimateTokensWithTiktoken = (encoding: TokenEncoding): number => {\n try {\n const enc: Tiktoken = getEncoding(encoding as any)\n return enc.encode(this.#value, []).length\n } catch {\n return Number.POSITIVE_INFINITY\n }\n }\n\n const estimateTokensWithGemini = (): number => {\n try {\n return getGeminiTokenizer().encode(this.#value).length\n } catch {\n return Number.POSITIVE_INFINITY\n }\n }\n\n const estimateTokensWithLlama2 = (): number => {\n try {\n return getLlamaTokenizer().encode(this.#value, false).length\n } catch {\n return Number.POSITIVE_INFINITY\n }\n }\n\n const estimateTokensWithClaudeHeuristic = (): number => {\n try {\n return Math.ceil(this.#value.length / 3.5)\n } catch {\n return Number.POSITIVE_INFINITY\n }\n }\n\n Object.defineProperties(this, {\n toJSON: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n toString: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n valueOf: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n toLocaleString: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n [Symbol.for('nodejs.util.inspect.custom')]: {\n value: () => this.#value,\n enumerable: false,\n configurable: false,\n writable: false,\n },\n set: {\n value: (next: string) => {\n this.#value = next\n this.#cache.clear()\n },\n enumerable: false,\n configurable: false,\n writable: false,\n },\n estimateTokens: {\n value: (encoding: TokenEncoding): number => {\n if (this.#cache.has(encoding)) {\n return this.#cache.get(encoding)!\n }\n\n let estimate: number\n switch (encoding) {\n case 'gpt2':\n case 'r50k_base':\n case 'p50k_base':\n case 'p50k_edit':\n case 'cl100k_base':\n case 'o200k_base':\n estimate = estimateTokensWithTiktoken(encoding)\n break\n case 'gemini':\n estimate = estimateTokensWithGemini()\n break\n case 'llama2':\n estimate = estimateTokensWithLlama2()\n break\n case 'claude':\n estimate = estimateTokensWithClaudeHeuristic()\n break\n }\n if (estimate === Number.POSITIVE_INFINITY) {\n estimate = Math.ceil(this.#value.length / 4)\n } else {\n this.#cache.set(encoding, estimate)\n }\n return estimate\n },\n enumerable: false,\n configurable: false,\n writable: false,\n },\n })\n }\n\n /**\n * Convenience overload for one-off token counting without managing a {@link Tokenizable} instance.\n *\n * @remarks\n * Creates a temporary instance and immediately discards it — no caching benefit. Use the\n * instance method when you need to count the same value under multiple encodings or when the\n * value may change over time.\n *\n * @param value - The string to count tokens for.\n * @param encoding - The encoding identifier to use for counting.\n * @returns The estimated number of tokens.\n */\n public static estimateTokens(value: string, encoding: TokenEncoding): number {\n const temp = new Tokenizable(value)\n return temp.estimateTokens(encoding)\n }\n\n /**\n * Returns `true` if `value` is a {@link Tokenizable} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Tokenizable} instance.\n */\n public static isTokenizable(value: unknown): value is Tokenizable {\n return isInstanceOf(value, 'Tokenizable', Tokenizable)\n }\n}\n\n/**\n * Returns `true` if `value` is a {@link Tokenizable} instance.\n *\n * @remarks\n * Module-level convenience alias for {@link Tokenizable.isTokenizable}. Prefer this form when\n * you need a standalone type guard without importing the full class.\n *\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety — `instanceof` would fail for instances\n * created in a different module copy or VM context.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Tokenizable} instance.\n */\nexport const isTokenizable = (value: unknown): value is Tokenizable => {\n return isInstanceOf(value, 'Tokenizable', Tokenizable)\n}\n","import { dset } from 'dset'\nimport { klona } from 'klona'\nimport { default as delve } from 'dlv'\nimport { isInstanceOf, isObject } from '../utils/guards'\nimport { E_INVALID_INITIAL_REGISTRY_VALUE } from '../exceptions/runtime'\n\n/**\n * A controlled-mutation key-value store with dot-path access and deep-clone isolation.\n *\n * @remarks\n * The registry enforces a safe read/write contract: callers never hold a live reference into\n * the internal store. Every value that enters (`set`) or leaves (`get`, `all`) is deep-cloned\n * via `klona`, so mutations to a retrieved value cannot affect stored state and vice versa.\n *\n * Keys are dot-delimited paths (e.g. `\"user.profile.name\"`), resolved via `dlv` for reads and\n * `dset` for writes; intermediate objects are created automatically on write.\n */\nexport class Registry {\n #store: Record<string, unknown>\n\n /**\n * @param initial - Optional plain object to seed the registry. Deep-cloned on construction.\n * @throws {@link @nhtio/adk!E_INVALID_INITIAL_REGISTRY_VALUE} when `initial` is defined but not a plain object.\n */\n constructor(initial?: Record<string, unknown>) {\n if ('undefined' !== typeof initial && !isObject(initial)) {\n throw new E_INVALID_INITIAL_REGISTRY_VALUE()\n }\n this.#store = initial ? klona(initial) : {}\n }\n\n /**\n * Returns `true` if `value` is a {@link Registry} instance.\n *\n * @remarks\n * Uses {@link @nhtio/adk!isInstanceOf} for cross-realm safety.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link Registry} instance.\n */\n public static isRegistry(value: unknown): value is Registry {\n return isInstanceOf(value, 'Registry', Registry)\n }\n\n /**\n * Retrieves the value at `key`, returning `defaultValue` if the path is absent.\n *\n * @remarks\n * The returned value is a deep clone — mutating it will not affect the stored state.\n *\n * @typeParam T - Expected type of the value at `key`.\n * @param key - Dot-delimited path into the store (e.g. `\"user.name\"`).\n * @param defaultValue - Fallback returned when the path resolves to `undefined`.\n * @returns A deep clone of the stored value cast to `T`, or `defaultValue` when the path is absent.\n */\n get<T = unknown>(key: string, defaultValue?: T): T {\n const cloned = klona(this.#store)\n const value = delve(cloned, key)\n return 'undefined' === typeof value ? (defaultValue as T) : (value as T)\n }\n\n /**\n * Sets the value at `key`, creating intermediate objects as needed.\n *\n * @remarks\n * The stored value is isolated from the caller — mutating `value` after this call will not\n * affect what is held in the registry.\n *\n * @param key - Dot-delimited path into the store (e.g. `\"user.name\"`).\n * @param value - Value to store at the path.\n */\n set(key: string, value: unknown): void {\n dset(this.#store, key, value)\n }\n\n /**\n * Returns `true` if the registry has a value at `key`, `false` otherwise.\n *\n * @remarks\n * A key resolving to `undefined` is treated as absent — same convention as {@link Registry.get}'s\n * `defaultValue` fallback. No clone is performed; this is a pure existence check.\n *\n * @param key - Dot-delimited path into the store (e.g. `\"user.name\"`).\n * @returns `true` when the path resolves to a value other than `undefined`.\n */\n has(key: string): boolean {\n return 'undefined' !== typeof delve(this.#store, key)\n }\n\n /**\n * Returns all leaf dot-paths present in the registry.\n *\n * @remarks\n * The store is deep-cloned before traversal. Plain objects are walked recursively with path\n * segments joined by dots; arrays, primitives, `null`, and class instances are treated as leaves.\n *\n * @returns A string array of dot-delimited paths to leaf values in the store.\n */\n keys(): string[] {\n const store = klona(this.#store)\n const keys: string[] = []\n\n const isPlainRecord = (value: unknown): value is Record<string, unknown> => {\n if (!isObject(value)) return false\n const prototype = Object.getPrototypeOf(value)\n return prototype === Object.prototype || prototype === null\n }\n\n const walk = (value: unknown, segments: string[]): void => {\n if (!isPlainRecord(value)) {\n if (segments.length > 0) keys.push(segments.join('.'))\n return\n }\n\n for (const [segment, child] of Object.entries(value)) {\n walk(child, [...segments, segment])\n }\n }\n\n walk(store, [])\n return keys\n }\n\n /**\n * Returns a deep clone of the entire store contents.\n *\n * @returns A plain object snapshot of all stored key-value pairs.\n */\n all(): Record<string, unknown> {\n return klona(this.#store)\n }\n}\n","/**\n * Canonical `JSON.stringify` that sorts object keys recursively so that semantically-equal\n * objects produce identical strings.\n *\n * @remarks\n * Used wherever the ADK derives a stable identity from a structured value — for example,\n * `Tool.executor` computing the `callId` for `ToolExecutionStart`/`End` events, and the\n * `reportToolCall` executor helper computing the `checksum` field on `TurnToolCallContent`.\n * Both code paths hash `canonicalStringify({ tool, args })` so that argument key order does not\n * affect the resulting identifier.\n *\n * Arrays are serialised in their declared order (order is meaningful for an array). Object keys\n * are sorted with `Array.prototype.sort()`'s default lexicographic comparator.\n *\n * @param value - The value to serialise.\n * @returns A canonical JSON string representation of `value`.\n */\nexport function canonicalStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value)\n if (Array.isArray(value)) return '[' + value.map((v) => canonicalStringify(v)).join(',') + ']'\n const obj = value as Record<string, unknown>\n const keys = Object.keys(obj).sort()\n return '{' + keys.map((k) => JSON.stringify(k) + ':' + canonicalStringify(obj[k])).join(',') + '}'\n}\n","import { isInstanceOf } from '../utils/guards'\nimport { E_TOOL_ALREADY_REGISTERED } from '../exceptions/runtime'\nimport type { Tool } from './tool'\nimport type { DispatchContext } from '../contracts/dispatch_context'\n\n/**\n * Options accepted by {@link ToolRegistry.merge}.\n */\nexport interface MergeOptions {\n /**\n * What to do when two registries contain a tool with the same name AND neither tool's own\n * `onCollision` resolves the collision.\n *\n * @remarks\n * - `'throw'` (default): raise {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} on the first unresolved\n * collision. Mirrors the default behaviour of {@link ToolRegistry.register} and surfaces\n * accidental name shadowing immediately.\n * - `'replace'`: the later registry's tool wins.\n * - `'keep'`: the earlier registry's tool wins; later occurrences are dropped.\n *\n * Per-tool {@link @nhtio/adk!Tool.onCollision} takes precedence: if the incoming tool declares\n * `'replace'` or `'keep'`, that policy wins regardless of this option. Only when the incoming\n * tool's policy is `'throw'` (the default) does this fallback apply.\n *\n * @defaultValue `'throw'`\n */\n onCollision?: 'throw' | 'replace' | 'keep'\n}\n\n/**\n * A mutable, turn-scoped collection of {@link @nhtio/adk!Tool} instances.\n *\n * @remarks\n * Each `TurnRunner.run()` call constructs a fresh `ToolRegistry` from the runner's configured\n * baseline tools, so middleware edits are isolated to the current turn and cannot bleed across\n * concurrent or subsequent turns.\n *\n * `Tool` instances are immutable, so `all()` returns a fresh array without deep-cloning.\n *\n * `register()` throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} if a tool with the same name is already\n * present — pass `overwrite: true` to replace it explicitly.\n */\nexport class ToolRegistry {\n #tools: Map<string, Tool>\n\n /**\n * Returns `true` if `value` is a {@link ToolRegistry} instance.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link ToolRegistry} instance.\n */\n public static isToolRegistry(value: unknown): value is ToolRegistry {\n return isInstanceOf(value, 'ToolRegistry', ToolRegistry)\n }\n\n /**\n * @param tools - Optional initial tools. Insertion order is preserved. Duplicate names throw\n * {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} — ensure each tool has a unique name.\n * @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when two tools in `tools` share a name.\n */\n constructor(tools?: Tool[]) {\n this.#tools = new Map()\n for (const tool of tools ?? []) {\n this.register(tool)\n }\n }\n\n /**\n * Adds a tool to the registry.\n *\n * @param tool - The tool to register.\n * @param overwrite - When `true`, silently replaces an existing tool with the same name.\n * Defaults to `false`.\n * @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when a tool with the same name is already registered\n * and `overwrite` is not `true`.\n */\n register(tool: Tool, overwrite?: boolean): void {\n if (this.#tools.has(tool.name) && !overwrite) {\n throw new E_TOOL_ALREADY_REGISTERED()\n }\n this.#tools.set(tool.name, tool)\n }\n\n /**\n * Removes the tool with the given name from the registry.\n *\n * @remarks\n * No-ops if no tool with that name is registered.\n *\n * @param name - The name of the tool to remove.\n */\n unregister(name: string): void {\n this.#tools.delete(name)\n }\n\n /**\n * Returns the tool registered under `name`, or `undefined` if not present.\n *\n * @param name - The tool name to look up.\n */\n get(name: string): Tool | undefined {\n return this.#tools.get(name)\n }\n\n /**\n * Returns `true` if a tool with the given name is registered.\n *\n * @param name - The tool name to test.\n */\n has(name: string): boolean {\n return this.#tools.has(name)\n }\n\n /**\n * Returns a fresh array of all registered tools in insertion order.\n *\n * @remarks\n * Since {@link @nhtio/adk!Tool} instances are immutable, no deep-cloning is needed.\n */\n all(): Tool[] {\n return Array.from(this.#tools.values())\n }\n\n /**\n * Removes every tool whose {@link @nhtio/adk!Tool.ephemeral} flag is `true`.\n *\n * @remarks\n * Synchronous and idempotent — calling it twice in a row is a no-op the second time. The\n * canonical caller is {@link ToolRegistry.bindContext}, which schedules this method to run\n * at {@link @nhtio/adk!DispatchContext.ack}. Non-ephemeral tools are left untouched.\n */\n pruneEphemeral(): void {\n for (const [name, tool] of this.#tools) {\n if (tool.ephemeral) {\n this.#tools.delete(name)\n }\n }\n }\n\n /**\n * Binds this registry to a {@link @nhtio/adk!DispatchContext} so that {@link pruneEphemeral} runs\n * automatically when the context is acked.\n *\n * @remarks\n * The handler does NOT fire on {@link @nhtio/adk!DispatchContext.nack} — failed executor runs leave\n * any forged tools in place so the consumer can inspect what was registered when debugging the\n * failure. Subscriptions are short-lived and die with the context regardless.\n *\n * Forgetting this call after merging in `Subclass.forgeTools(ctx)` output means ephemeral tools\n * accumulate across executor invocations, and subsequent `forgeTools(ctx)` calls in later\n * iterations will see a stale `callId` enum that excludes new tool calls. The plan-documented\n * pattern is:\n *\n * ```ts\n * const executor: DispatchExecutorFn = async (ctx) => {\n * const forged = SpooledArtifact.forgeTools(ctx)\n * const merged = ToolRegistry.merge([main, forged])\n * main.bindContext(ctx)\n * const result = await llm.invoke({ tools: merged.all(), ... })\n * ctx.ack()\n * }\n * ```\n *\n * @param ctx - The execution context whose `ack` event should trigger pruning.\n * @returns An unsubscribe function — calling it before `ctx.ack()` prevents pruning. Rarely\n * useful outside of tests.\n *\n * @see {@link @nhtio/adk!SpooledArtifact.forgeTools}\n * @see {@link @nhtio/adk!DispatchContext.onAck}\n */\n bindContext(ctx: DispatchContext): () => void {\n return ctx.onAck(() => this.pruneEphemeral())\n }\n\n /**\n * Combines multiple {@link ToolRegistry} instances into a fresh registry without mutating any\n * input.\n *\n * @remarks\n * Iteration is left-to-right across `registries` and then in each registry's insertion order.\n * Collisions are resolved by consulting the **incoming** tool's {@link @nhtio/adk!Tool.onCollision} first:\n *\n * - `'replace'` (per-tool): the incoming tool wins, replacing the existing entry.\n * - `'keep'` (per-tool): the existing entry wins; the incoming tool is dropped.\n * - `'throw'` (per-tool, the default): fall back to the merge-level `options.onCollision`.\n *\n * The merge-level `options.onCollision` defaults to `'throw'`, which mirrors {@link register}.\n *\n * The result is a brand-new registry; no input is mutated and no event subscription is\n * propagated. Each `Tool`'s `ephemeral` flag carries through unchanged — the flag lives on the\n * tool, not the registry, so `bindContext(ctx)` on the merged registry will prune the forged\n * tools as expected.\n *\n * @param registries - Registries to merge, in priority order (left-to-right insertion).\n * @param options - Merge-level collision policy. Defaults to `{ onCollision: 'throw' }`.\n * @returns A fresh {@link ToolRegistry} containing the resolved union of all inputs.\n * @throws {@link @nhtio/adk!E_TOOL_ALREADY_REGISTERED} when the resolved collision policy is `'throw'`\n * and a collision occurs.\n */\n static merge(registries: ToolRegistry[], options?: MergeOptions): ToolRegistry {\n const policy = options?.onCollision ?? 'throw'\n const merged = new ToolRegistry()\n for (const registry of registries) {\n for (const tool of registry.all()) {\n const existing = merged.get(tool.name)\n if (!existing) {\n merged.register(tool)\n continue\n }\n const incomingPolicy = tool.onCollision\n if (incomingPolicy === 'replace') {\n merged.register(tool, true)\n continue\n }\n if (incomingPolicy === 'keep') {\n continue\n }\n // Incoming policy is 'throw' — fall back to the merge-level option.\n if (policy === 'replace') {\n merged.register(tool, true)\n continue\n }\n if (policy === 'keep') {\n continue\n }\n throw new E_TOOL_ALREADY_REGISTERED()\n }\n }\n return merged\n }\n}\n"],"mappings":"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"}
|