@nhtio/adk 1.20260607.2 → 1.20260609.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (501) hide show
  1. package/CHANGELOG.md +185 -0
  2. package/batteries/embeddings/openai/adapter.cjs +1 -1
  3. package/batteries/embeddings/openai/adapter.mjs +1 -1
  4. package/batteries/embeddings/openai/exceptions.cjs +1 -1
  5. package/batteries/embeddings/openai/exceptions.mjs +1 -1
  6. package/batteries/embeddings/openai/types.d.ts +7 -0
  7. package/batteries/embeddings/webllm/adapter.cjs +1 -1
  8. package/batteries/embeddings/webllm/adapter.mjs +1 -1
  9. package/batteries/embeddings/webllm/exceptions.cjs +1 -1
  10. package/batteries/embeddings/webllm/exceptions.mjs +1 -1
  11. package/batteries/llm/chat_common/helpers.d.ts +165 -0
  12. package/batteries/llm/chat_common/types.d.ts +309 -0
  13. package/batteries/llm/index.d.ts +5 -0
  14. package/batteries/llm/ollama/adapter.cjs +736 -0
  15. package/batteries/llm/ollama/adapter.cjs.map +1 -0
  16. package/batteries/llm/ollama/adapter.d.ts +64 -0
  17. package/batteries/llm/ollama/adapter.mjs +734 -0
  18. package/batteries/llm/ollama/adapter.mjs.map +1 -0
  19. package/batteries/llm/ollama/exceptions.cjs +105 -0
  20. package/batteries/llm/ollama/exceptions.cjs.map +1 -0
  21. package/batteries/llm/ollama/exceptions.d.ts +112 -0
  22. package/batteries/llm/ollama/exceptions.mjs +96 -0
  23. package/batteries/llm/ollama/exceptions.mjs.map +1 -0
  24. package/batteries/llm/ollama/helpers.cjs +487 -0
  25. package/batteries/llm/ollama/helpers.cjs.map +1 -0
  26. package/batteries/llm/ollama/helpers.d.ts +158 -0
  27. package/batteries/llm/ollama/helpers.mjs +450 -0
  28. package/batteries/llm/ollama/helpers.mjs.map +1 -0
  29. package/batteries/llm/ollama/index.d.ts +29 -0
  30. package/batteries/llm/ollama/types.cjs +2 -0
  31. package/batteries/llm/ollama/types.d.ts +334 -0
  32. package/batteries/llm/ollama/types.mjs +0 -0
  33. package/batteries/llm/ollama/validation.cjs +130 -0
  34. package/batteries/llm/ollama/validation.cjs.map +1 -0
  35. package/batteries/llm/ollama/validation.d.ts +31 -0
  36. package/batteries/llm/ollama/validation.mjs +127 -0
  37. package/batteries/llm/ollama/validation.mjs.map +1 -0
  38. package/batteries/llm/ollama.cjs +54 -0
  39. package/batteries/llm/ollama.mjs +6 -0
  40. package/batteries/llm/openai_chat_completions/adapter.cjs +36 -19
  41. package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -1
  42. package/batteries/llm/openai_chat_completions/adapter.mjs +23 -6
  43. package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -1
  44. package/batteries/llm/openai_chat_completions/exceptions.cjs +1 -1
  45. package/batteries/llm/openai_chat_completions/exceptions.mjs +1 -1
  46. package/batteries/llm/openai_chat_completions/helpers.cjs +80 -320
  47. package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -1
  48. package/batteries/llm/openai_chat_completions/helpers.d.ts +68 -144
  49. package/batteries/llm/openai_chat_completions/helpers.mjs +40 -280
  50. package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -1
  51. package/batteries/llm/openai_chat_completions/types.d.ts +273 -181
  52. package/batteries/llm/openai_chat_completions/validation.cjs +2 -2
  53. package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -1
  54. package/batteries/llm/openai_chat_completions/validation.mjs +2 -2
  55. package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -1
  56. package/batteries/llm/openai_chat_completions.cjs +29 -28
  57. package/batteries/llm/openai_chat_completions.mjs +2 -1
  58. package/batteries/llm/webllm_chat_completions/adapter.cjs +38 -19
  59. package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -1
  60. package/batteries/llm/webllm_chat_completions/adapter.d.ts +18 -0
  61. package/batteries/llm/webllm_chat_completions/adapter.mjs +25 -6
  62. package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -1
  63. package/batteries/llm/webllm_chat_completions/exceptions.cjs +1 -1
  64. package/batteries/llm/webllm_chat_completions/exceptions.mjs +1 -1
  65. package/batteries/llm/webllm_chat_completions/helpers.cjs +29 -28
  66. package/batteries/llm/webllm_chat_completions/helpers.mjs +2 -1
  67. package/batteries/llm/webllm_chat_completions/types.d.ts +21 -0
  68. package/batteries/llm/webllm_chat_completions/validation.cjs +13 -1
  69. package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -1
  70. package/batteries/llm/webllm_chat_completions/validation.d.ts +12 -0
  71. package/batteries/llm/webllm_chat_completions/validation.mjs +13 -1
  72. package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -1
  73. package/batteries/llm/webllm_chat_completions.cjs +29 -28
  74. package/batteries/llm/webllm_chat_completions.mjs +2 -1
  75. package/batteries/llm.cjs +44 -28
  76. package/batteries/llm.mjs +9 -4
  77. package/batteries/storage/flydrive.cjs +1 -1
  78. package/batteries/storage/flydrive.mjs +1 -1
  79. package/batteries/storage/in_memory/index.d.ts +1 -1
  80. package/batteries/storage/in_memory.cjs +2 -2
  81. package/batteries/storage/in_memory.cjs.map +1 -1
  82. package/batteries/storage/in_memory.mjs +2 -2
  83. package/batteries/storage/in_memory.mjs.map +1 -1
  84. package/batteries/storage/opfs/index.d.ts +19 -0
  85. package/batteries/storage/opfs.cjs +1 -1
  86. package/batteries/storage/opfs.cjs.map +1 -1
  87. package/batteries/storage/opfs.mjs +1 -1
  88. package/batteries/storage/opfs.mjs.map +1 -1
  89. package/batteries/tools/color.cjs +3 -2
  90. package/batteries/tools/color.cjs.map +1 -1
  91. package/batteries/tools/color.mjs +3 -2
  92. package/batteries/tools/color.mjs.map +1 -1
  93. package/batteries/tools/comparison.cjs +4 -3
  94. package/batteries/tools/comparison.cjs.map +1 -1
  95. package/batteries/tools/comparison.mjs +4 -3
  96. package/batteries/tools/comparison.mjs.map +1 -1
  97. package/batteries/tools/data_structure.cjs +30 -10
  98. package/batteries/tools/data_structure.cjs.map +1 -1
  99. package/batteries/tools/data_structure.mjs +30 -10
  100. package/batteries/tools/data_structure.mjs.map +1 -1
  101. package/batteries/tools/datetime_extended.cjs +5 -10
  102. package/batteries/tools/datetime_extended.cjs.map +1 -1
  103. package/batteries/tools/datetime_extended.mjs +5 -10
  104. package/batteries/tools/datetime_extended.mjs.map +1 -1
  105. package/batteries/tools/datetime_math.cjs +2 -2
  106. package/batteries/tools/datetime_math.mjs +2 -2
  107. package/batteries/tools/encoding.cjs +13 -4
  108. package/batteries/tools/encoding.cjs.map +1 -1
  109. package/batteries/tools/encoding.mjs +13 -4
  110. package/batteries/tools/encoding.mjs.map +1 -1
  111. package/batteries/tools/formatting.cjs +4 -4
  112. package/batteries/tools/formatting.cjs.map +1 -1
  113. package/batteries/tools/formatting.mjs +4 -4
  114. package/batteries/tools/formatting.mjs.map +1 -1
  115. package/batteries/tools/geo_basics.cjs +2 -2
  116. package/batteries/tools/geo_basics.mjs +2 -2
  117. package/batteries/tools/index.d.ts +1 -0
  118. package/batteries/tools/math.cjs +10 -8
  119. package/batteries/tools/math.cjs.map +1 -1
  120. package/batteries/tools/math.mjs +10 -8
  121. package/batteries/tools/math.mjs.map +1 -1
  122. package/batteries/tools/memory.cjs +5 -5
  123. package/batteries/tools/memory.mjs +5 -5
  124. package/batteries/tools/parsing.cjs +9 -5
  125. package/batteries/tools/parsing.cjs.map +1 -1
  126. package/batteries/tools/parsing.mjs +9 -5
  127. package/batteries/tools/parsing.mjs.map +1 -1
  128. package/batteries/tools/retrievables.cjs +4 -4
  129. package/batteries/tools/retrievables.mjs +4 -4
  130. package/batteries/tools/searxng/exceptions.d.ts +21 -0
  131. package/batteries/tools/searxng/index.d.ts +150 -0
  132. package/batteries/tools/searxng.cjs +5 -0
  133. package/batteries/tools/searxng.mjs +2 -0
  134. package/batteries/tools/standing_instructions.cjs +4 -4
  135. package/batteries/tools/standing_instructions.mjs +4 -4
  136. package/batteries/tools/statistics.cjs +54 -43
  137. package/batteries/tools/statistics.cjs.map +1 -1
  138. package/batteries/tools/statistics.mjs +54 -43
  139. package/batteries/tools/statistics.mjs.map +1 -1
  140. package/batteries/tools/string_processing.cjs +5 -5
  141. package/batteries/tools/string_processing.cjs.map +1 -1
  142. package/batteries/tools/string_processing.mjs +5 -5
  143. package/batteries/tools/string_processing.mjs.map +1 -1
  144. package/batteries/tools/structured_data.cjs +8 -13
  145. package/batteries/tools/structured_data.cjs.map +1 -1
  146. package/batteries/tools/structured_data.mjs +8 -13
  147. package/batteries/tools/structured_data.mjs.map +1 -1
  148. package/batteries/tools/text_analysis.cjs +3 -3
  149. package/batteries/tools/text_analysis.mjs +3 -3
  150. package/batteries/tools/text_comparison.cjs +2 -2
  151. package/batteries/tools/text_comparison.mjs +2 -2
  152. package/batteries/tools/time.cjs +2 -2
  153. package/batteries/tools/time.mjs +2 -2
  154. package/batteries/tools/unit_conversion.cjs +10 -8
  155. package/batteries/tools/unit_conversion.cjs.map +1 -1
  156. package/batteries/tools/unit_conversion.mjs +10 -8
  157. package/batteries/tools/unit_conversion.mjs.map +1 -1
  158. package/batteries/tools.cjs +3 -0
  159. package/batteries/tools.mjs +2 -1
  160. package/batteries/vector/arangodb/index.d.ts +2 -0
  161. package/batteries/vector/arangodb.cjs +2 -1
  162. package/batteries/vector/arangodb.cjs.map +1 -1
  163. package/batteries/vector/arangodb.mjs +2 -1
  164. package/batteries/vector/arangodb.mjs.map +1 -1
  165. package/batteries/vector/builder.cjs +31 -0
  166. package/batteries/vector/builder.cjs.map +1 -1
  167. package/batteries/vector/builder.d.ts +58 -0
  168. package/batteries/vector/builder.mjs +31 -0
  169. package/batteries/vector/builder.mjs.map +1 -1
  170. package/batteries/vector/chroma/index.d.ts +4 -0
  171. package/batteries/vector/chroma.cjs +3 -0
  172. package/batteries/vector/chroma.cjs.map +1 -1
  173. package/batteries/vector/chroma.mjs +3 -0
  174. package/batteries/vector/chroma.mjs.map +1 -1
  175. package/batteries/vector/clickhouse/index.d.ts +2 -0
  176. package/batteries/vector/clickhouse.cjs +2 -1
  177. package/batteries/vector/clickhouse.cjs.map +1 -1
  178. package/batteries/vector/clickhouse.mjs +2 -1
  179. package/batteries/vector/clickhouse.mjs.map +1 -1
  180. package/batteries/vector/cloudflare/index.d.ts +2 -0
  181. package/batteries/vector/cloudflare.cjs +2 -1
  182. package/batteries/vector/cloudflare.cjs.map +1 -1
  183. package/batteries/vector/cloudflare.mjs +2 -1
  184. package/batteries/vector/cloudflare.mjs.map +1 -1
  185. package/batteries/vector/conformance/index.d.ts +22 -0
  186. package/batteries/vector/conformance.cjs +22 -0
  187. package/batteries/vector/conformance.cjs.map +1 -1
  188. package/batteries/vector/conformance.mjs +22 -0
  189. package/batteries/vector/conformance.mjs.map +1 -1
  190. package/batteries/vector/contract.cjs +22 -0
  191. package/batteries/vector/contract.cjs.map +1 -1
  192. package/batteries/vector/contract.d.ts +51 -0
  193. package/batteries/vector/contract.mjs +22 -0
  194. package/batteries/vector/contract.mjs.map +1 -1
  195. package/batteries/vector/couchbase/index.d.ts +2 -0
  196. package/batteries/vector/couchbase.cjs +2 -1
  197. package/batteries/vector/couchbase.cjs.map +1 -1
  198. package/batteries/vector/couchbase.mjs +2 -1
  199. package/batteries/vector/couchbase.mjs.map +1 -1
  200. package/batteries/vector/duckdb/index.d.ts +2 -0
  201. package/batteries/vector/duckdb.cjs +2 -1
  202. package/batteries/vector/duckdb.cjs.map +1 -1
  203. package/batteries/vector/duckdb.mjs +2 -1
  204. package/batteries/vector/duckdb.mjs.map +1 -1
  205. package/batteries/vector/elasticsearch/index.d.ts +2 -0
  206. package/batteries/vector/elasticsearch.cjs +2 -1
  207. package/batteries/vector/elasticsearch.cjs.map +1 -1
  208. package/batteries/vector/elasticsearch.mjs +2 -1
  209. package/batteries/vector/elasticsearch.mjs.map +1 -1
  210. package/batteries/vector/exceptions.cjs +1 -1
  211. package/batteries/vector/exceptions.mjs +1 -1
  212. package/batteries/vector/factory.cjs +6 -0
  213. package/batteries/vector/factory.cjs.map +1 -1
  214. package/batteries/vector/factory.d.ts +14 -0
  215. package/batteries/vector/factory.mjs +6 -0
  216. package/batteries/vector/factory.mjs.map +1 -1
  217. package/batteries/vector/filters.cjs +22 -1
  218. package/batteries/vector/filters.cjs.map +1 -1
  219. package/batteries/vector/filters.d.ts +38 -0
  220. package/batteries/vector/filters.mjs +22 -1
  221. package/batteries/vector/filters.mjs.map +1 -1
  222. package/batteries/vector/helpers.cjs +13 -0
  223. package/batteries/vector/helpers.cjs.map +1 -1
  224. package/batteries/vector/helpers.d.ts +14 -0
  225. package/batteries/vector/helpers.mjs +13 -0
  226. package/batteries/vector/helpers.mjs.map +1 -1
  227. package/batteries/vector/hnswlib/index.d.ts +2 -0
  228. package/batteries/vector/hnswlib.cjs +2 -1
  229. package/batteries/vector/hnswlib.cjs.map +1 -1
  230. package/batteries/vector/hnswlib.mjs +2 -1
  231. package/batteries/vector/hnswlib.mjs.map +1 -1
  232. package/batteries/vector/in_memory/index.d.ts +1 -0
  233. package/batteries/vector/in_memory.cjs +1 -0
  234. package/batteries/vector/in_memory.cjs.map +1 -1
  235. package/batteries/vector/in_memory.mjs +1 -0
  236. package/batteries/vector/in_memory.mjs.map +1 -1
  237. package/batteries/vector/lancedb/index.d.ts +2 -0
  238. package/batteries/vector/lancedb.cjs +2 -1
  239. package/batteries/vector/lancedb.cjs.map +1 -1
  240. package/batteries/vector/lancedb.mjs +2 -1
  241. package/batteries/vector/lancedb.mjs.map +1 -1
  242. package/batteries/vector/mariadb/index.d.ts +2 -0
  243. package/batteries/vector/mariadb.cjs +2 -1
  244. package/batteries/vector/mariadb.cjs.map +1 -1
  245. package/batteries/vector/mariadb.mjs +2 -1
  246. package/batteries/vector/mariadb.mjs.map +1 -1
  247. package/batteries/vector/meilisearch/index.d.ts +2 -0
  248. package/batteries/vector/meilisearch.cjs +2 -1
  249. package/batteries/vector/meilisearch.cjs.map +1 -1
  250. package/batteries/vector/meilisearch.mjs +2 -1
  251. package/batteries/vector/meilisearch.mjs.map +1 -1
  252. package/batteries/vector/migrate.cjs +18 -1
  253. package/batteries/vector/migrate.cjs.map +1 -1
  254. package/batteries/vector/migrate.d.ts +31 -0
  255. package/batteries/vector/migrate.mjs +18 -1
  256. package/batteries/vector/migrate.mjs.map +1 -1
  257. package/batteries/vector/milvus/index.d.ts +5 -0
  258. package/batteries/vector/milvus.cjs +4 -0
  259. package/batteries/vector/milvus.cjs.map +1 -1
  260. package/batteries/vector/milvus.mjs +4 -0
  261. package/batteries/vector/milvus.mjs.map +1 -1
  262. package/batteries/vector/mongodb/index.d.ts +2 -0
  263. package/batteries/vector/mongodb.cjs +2 -1
  264. package/batteries/vector/mongodb.cjs.map +1 -1
  265. package/batteries/vector/mongodb.mjs +2 -1
  266. package/batteries/vector/mongodb.mjs.map +1 -1
  267. package/batteries/vector/neo4j/index.d.ts +2 -0
  268. package/batteries/vector/neo4j.cjs +2 -1
  269. package/batteries/vector/neo4j.cjs.map +1 -1
  270. package/batteries/vector/neo4j.mjs +2 -1
  271. package/batteries/vector/neo4j.mjs.map +1 -1
  272. package/batteries/vector/opensearch/index.d.ts +2 -0
  273. package/batteries/vector/opensearch.cjs +2 -1
  274. package/batteries/vector/opensearch.cjs.map +1 -1
  275. package/batteries/vector/opensearch.mjs +2 -1
  276. package/batteries/vector/opensearch.mjs.map +1 -1
  277. package/batteries/vector/oracle23ai/index.d.ts +2 -0
  278. package/batteries/vector/oracle23ai.cjs +2 -1
  279. package/batteries/vector/oracle23ai.cjs.map +1 -1
  280. package/batteries/vector/oracle23ai.mjs +2 -1
  281. package/batteries/vector/oracle23ai.mjs.map +1 -1
  282. package/batteries/vector/orama/index.d.ts +1 -0
  283. package/batteries/vector/orama.cjs +1 -0
  284. package/batteries/vector/orama.cjs.map +1 -1
  285. package/batteries/vector/orama.mjs +1 -0
  286. package/batteries/vector/orama.mjs.map +1 -1
  287. package/batteries/vector/pgvector/index.d.ts +9 -2
  288. package/batteries/vector/pgvector.cjs +4 -0
  289. package/batteries/vector/pgvector.cjs.map +1 -1
  290. package/batteries/vector/pgvector.mjs +4 -0
  291. package/batteries/vector/pgvector.mjs.map +1 -1
  292. package/batteries/vector/pinecone/index.d.ts +5 -0
  293. package/batteries/vector/pinecone.cjs +3 -1
  294. package/batteries/vector/pinecone.cjs.map +1 -1
  295. package/batteries/vector/pinecone.mjs +3 -1
  296. package/batteries/vector/pinecone.mjs.map +1 -1
  297. package/batteries/vector/plan.d.ts +27 -0
  298. package/batteries/vector/qdrant/index.d.ts +5 -0
  299. package/batteries/vector/qdrant.cjs +4 -0
  300. package/batteries/vector/qdrant.cjs.map +1 -1
  301. package/batteries/vector/qdrant.mjs +4 -0
  302. package/batteries/vector/qdrant.mjs.map +1 -1
  303. package/batteries/vector/redis/index.d.ts +2 -0
  304. package/batteries/vector/redis.cjs +2 -1
  305. package/batteries/vector/redis.cjs.map +1 -1
  306. package/batteries/vector/redis.mjs +2 -1
  307. package/batteries/vector/redis.mjs.map +1 -1
  308. package/batteries/vector/retrievable.cjs +9 -1
  309. package/batteries/vector/retrievable.cjs.map +1 -1
  310. package/batteries/vector/retrievable.mjs +9 -1
  311. package/batteries/vector/retrievable.mjs.map +1 -1
  312. package/batteries/vector/retrievable_glue.d.ts +21 -0
  313. package/batteries/vector/s3vectors/index.d.ts +2 -0
  314. package/batteries/vector/s3vectors.cjs +2 -1
  315. package/batteries/vector/s3vectors.cjs.map +1 -1
  316. package/batteries/vector/s3vectors.mjs +2 -1
  317. package/batteries/vector/s3vectors.mjs.map +1 -1
  318. package/batteries/vector/schema.cjs +28 -0
  319. package/batteries/vector/schema.cjs.map +1 -1
  320. package/batteries/vector/schema.d.ts +39 -0
  321. package/batteries/vector/schema.mjs +28 -0
  322. package/batteries/vector/schema.mjs.map +1 -1
  323. package/batteries/vector/solr/index.d.ts +2 -0
  324. package/batteries/vector/solr.cjs +2 -1
  325. package/batteries/vector/solr.cjs.map +1 -1
  326. package/batteries/vector/solr.mjs +2 -1
  327. package/batteries/vector/solr.mjs.map +1 -1
  328. package/batteries/vector/sqlite_vec/index.d.ts +6 -3
  329. package/batteries/vector/sqlite_vec.cjs +2 -0
  330. package/batteries/vector/sqlite_vec.cjs.map +1 -1
  331. package/batteries/vector/sqlite_vec.mjs +2 -0
  332. package/batteries/vector/sqlite_vec.mjs.map +1 -1
  333. package/batteries/vector/surrealdb/index.d.ts +2 -0
  334. package/batteries/vector/surrealdb.cjs +2 -1
  335. package/batteries/vector/surrealdb.cjs.map +1 -1
  336. package/batteries/vector/surrealdb.mjs +2 -1
  337. package/batteries/vector/surrealdb.mjs.map +1 -1
  338. package/batteries/vector/types.d.ts +27 -0
  339. package/batteries/vector/typesense/index.d.ts +2 -0
  340. package/batteries/vector/typesense.cjs +2 -1
  341. package/batteries/vector/typesense.cjs.map +1 -1
  342. package/batteries/vector/typesense.mjs +2 -1
  343. package/batteries/vector/typesense.mjs.map +1 -1
  344. package/batteries/vector/validation.cjs +14 -0
  345. package/batteries/vector/validation.cjs.map +1 -1
  346. package/batteries/vector/validation.d.ts +14 -0
  347. package/batteries/vector/validation.mjs +14 -0
  348. package/batteries/vector/validation.mjs.map +1 -1
  349. package/batteries/vector/vector_store_constructor.cjs +1 -1
  350. package/batteries/vector/vector_store_constructor.cjs.map +1 -1
  351. package/batteries/vector/vector_store_constructor.d.ts +1 -1
  352. package/batteries/vector/vector_store_constructor.mjs +1 -1
  353. package/batteries/vector/vector_store_constructor.mjs.map +1 -1
  354. package/batteries/vector/vespa/index.d.ts +2 -0
  355. package/batteries/vector/vespa.cjs +2 -1
  356. package/batteries/vector/vespa.cjs.map +1 -1
  357. package/batteries/vector/vespa.mjs +2 -1
  358. package/batteries/vector/vespa.mjs.map +1 -1
  359. package/batteries/vector/weaviate/index.d.ts +2 -0
  360. package/batteries/vector/weaviate.cjs +2 -1
  361. package/batteries/vector/weaviate.cjs.map +1 -1
  362. package/batteries/vector/weaviate.mjs +2 -1
  363. package/batteries/vector/weaviate.mjs.map +1 -1
  364. package/batteries.cjs +46 -28
  365. package/batteries.mjs +10 -5
  366. package/{common-BT0nfCi9.mjs → common-DYDUi99O.mjs} +9 -9
  367. package/common-DYDUi99O.mjs.map +1 -0
  368. package/{common-Cj8TaQ9U.js → common-DZl3ADJs.js} +9 -9
  369. package/common-DZl3ADJs.js.map +1 -0
  370. package/common.cjs +7 -7
  371. package/common.d.ts +1 -1
  372. package/common.mjs +7 -7
  373. package/{dispatch_runner-DPcS7Y_M.mjs → dispatch_runner--ZhdDWRZ.mjs} +27 -5
  374. package/{dispatch_runner-DPcS7Y_M.mjs.map → dispatch_runner--ZhdDWRZ.mjs.map} +1 -1
  375. package/{dispatch_runner-BHBNupqp.js → dispatch_runner-nHDKkxye.js} +27 -5
  376. package/{dispatch_runner-BHBNupqp.js.map → dispatch_runner-nHDKkxye.js.map} +1 -1
  377. package/dispatch_runner.cjs +1 -1
  378. package/dispatch_runner.d.ts +1 -1
  379. package/dispatch_runner.mjs +1 -1
  380. package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs +1 -0
  381. package/eslint/rules/artifact_tool_forbids_artifact_constructor.cjs.map +1 -1
  382. package/eslint/rules/artifact_tool_forbids_artifact_constructor.d.ts +1 -0
  383. package/eslint/rules/artifact_tool_forbids_artifact_constructor.mjs +1 -0
  384. package/eslint/rules/artifact_tool_forbids_artifact_constructor.mjs.map +1 -1
  385. package/eslint/rules/no_model_in_tool_handler.cjs +1 -0
  386. package/eslint/rules/no_model_in_tool_handler.cjs.map +1 -1
  387. package/eslint/rules/no_model_in_tool_handler.d.ts +1 -0
  388. package/eslint/rules/no_model_in_tool_handler.mjs +1 -0
  389. package/eslint/rules/no_model_in_tool_handler.mjs.map +1 -1
  390. package/eslint/rules/require_validator_any_required.cjs +1 -0
  391. package/eslint/rules/require_validator_any_required.cjs.map +1 -1
  392. package/eslint/rules/require_validator_any_required.d.ts +1 -0
  393. package/eslint/rules/require_validator_any_required.mjs +1 -0
  394. package/eslint/rules/require_validator_any_required.mjs.map +1 -1
  395. package/eslint/rules/thought_payload_requires_replay_tag.cjs +1 -0
  396. package/eslint/rules/thought_payload_requires_replay_tag.cjs.map +1 -1
  397. package/eslint/rules/thought_payload_requires_replay_tag.d.ts +1 -0
  398. package/eslint/rules/thought_payload_requires_replay_tag.mjs +1 -0
  399. package/eslint/rules/thought_payload_requires_replay_tag.mjs.map +1 -1
  400. package/eslint/rules/token_encoding_requires_context_window.cjs +1 -0
  401. package/eslint/rules/token_encoding_requires_context_window.cjs.map +1 -1
  402. package/eslint/rules/token_encoding_requires_context_window.d.ts +1 -0
  403. package/eslint/rules/token_encoding_requires_context_window.mjs +1 -0
  404. package/eslint/rules/token_encoding_requires_context_window.mjs.map +1 -1
  405. package/eslint.cjs +1 -1
  406. package/eslint.mjs +1 -1
  407. package/{exceptions-BeWH2FwP.mjs → exceptions-BDhN0Xzr.mjs} +3 -2
  408. package/exceptions-BDhN0Xzr.mjs.map +1 -0
  409. package/{exceptions-CitH5wZI.js → exceptions-BRXrUKiW.js} +3 -2
  410. package/exceptions-BRXrUKiW.js.map +1 -0
  411. package/exceptions.cjs +2 -2
  412. package/exceptions.mjs +2 -2
  413. package/factories.cjs +1 -1
  414. package/factories.mjs +1 -1
  415. package/forge.cjs +4 -4
  416. package/forge.d.ts +1 -1
  417. package/forge.mjs +4 -4
  418. package/guards.cjs +9 -9
  419. package/guards.mjs +9 -9
  420. package/helpers-DSTFxTiC.js +497 -0
  421. package/helpers-DSTFxTiC.js.map +1 -0
  422. package/helpers-xhrQbMAG.mjs +306 -0
  423. package/helpers-xhrQbMAG.mjs.map +1 -0
  424. package/index.cjs +13 -13
  425. package/index.mjs +13 -13
  426. package/lib/classes/base_exception.d.ts +1 -0
  427. package/lib/classes/media.d.ts +10 -0
  428. package/lib/classes/retrievable.d.ts +1 -1
  429. package/lib/classes/spooled_json_artifact.d.ts +1 -1
  430. package/lib/classes/spooled_markdown_artifact.d.ts +1 -0
  431. package/lib/classes/tokenizable.d.ts +3 -0
  432. package/lib/classes/tool.d.ts +8 -0
  433. package/lib/classes/turn_gate.d.ts +6 -0
  434. package/lib/dispatch_runner.d.ts +4 -32
  435. package/lib/helpers/bignum.cjs +82 -0
  436. package/lib/helpers/bignum.cjs.map +1 -0
  437. package/lib/helpers/bignum.d.ts +52 -0
  438. package/lib/helpers/bignum.mjs +74 -0
  439. package/lib/helpers/bignum.mjs.map +1 -0
  440. package/lib/turn_runner.d.ts +1 -1
  441. package/lib/types/dispatch_runner.d.ts +83 -0
  442. package/lib/utils/exceptions.d.ts +1 -1
  443. package/lib/utils/retry.cjs.map +1 -1
  444. package/lib/utils/retry.d.ts +2 -0
  445. package/lib/utils/retry.mjs.map +1 -1
  446. package/mcp/adk-docs-corpus.json +1 -1
  447. package/package.json +264 -224
  448. package/{runtime-j92CNi5z.mjs → runtime-Bz5zA8wc.mjs} +2 -2
  449. package/{runtime-j92CNi5z.mjs.map → runtime-Bz5zA8wc.mjs.map} +1 -1
  450. package/{runtime-MFFcJrRv.js → runtime-DslE1aBw.js} +2 -2
  451. package/{runtime-MFFcJrRv.js.map → runtime-DslE1aBw.js.map} +1 -1
  452. package/searxng-Bkrwhwhw.js +269 -0
  453. package/searxng-Bkrwhwhw.js.map +1 -0
  454. package/searxng-CyA-nEu5.mjs +257 -0
  455. package/searxng-CyA-nEu5.mjs.map +1 -0
  456. package/skills/adk-assembly/SKILL.md +2 -2
  457. package/{spooled_artifact-CHoZgWwI.mjs → spooled_artifact-7eePq7JA.mjs} +5 -5
  458. package/{spooled_artifact-CHoZgWwI.mjs.map → spooled_artifact-7eePq7JA.mjs.map} +1 -1
  459. package/{spooled_artifact-BTq6Nzfy.js → spooled_artifact-DX8LLyUX.js} +5 -5
  460. package/{spooled_artifact-BTq6Nzfy.js.map → spooled_artifact-DX8LLyUX.js.map} +1 -1
  461. package/spooled_artifact.cjs +2 -2
  462. package/spooled_artifact.mjs +2 -2
  463. package/{spooled_markdown_artifact-CALSDxIx.js → spooled_markdown_artifact-ClX72lek.js} +4 -4
  464. package/spooled_markdown_artifact-ClX72lek.js.map +1 -0
  465. package/{spooled_markdown_artifact-Ci5UL7l4.mjs → spooled_markdown_artifact-wkrBF3oX.mjs} +4 -4
  466. package/spooled_markdown_artifact-wkrBF3oX.mjs.map +1 -0
  467. package/{thought-D34QQZZ9.mjs → thought-B_vxAiKU.mjs} +5 -5
  468. package/{thought-D34QQZZ9.mjs.map → thought-B_vxAiKU.mjs.map} +1 -1
  469. package/{thought-BbwhJ1wb.js → thought-DLwpF7MI.js} +5 -5
  470. package/{thought-BbwhJ1wb.js.map → thought-DLwpF7MI.js.map} +1 -1
  471. package/{tool-CVyZkFC7.js → tool-D5WGVIcI.js} +4 -4
  472. package/{tool-CVyZkFC7.js.map → tool-D5WGVIcI.js.map} +1 -1
  473. package/{tool-CMhaDRNd.mjs → tool-wMYMVl60.mjs} +4 -4
  474. package/{tool-CMhaDRNd.mjs.map → tool-wMYMVl60.mjs.map} +1 -1
  475. package/{tool_call-CV5qVNlb.mjs → tool_call-B4-_-vjG.mjs} +5 -5
  476. package/tool_call-B4-_-vjG.mjs.map +1 -0
  477. package/{tool_call-Db68hB7y.js → tool_call-DixVlW40.js} +5 -5
  478. package/tool_call-DixVlW40.js.map +1 -0
  479. package/{tool_registry-D1pSSlsd.mjs → tool_registry-791Vrjtf.mjs} +4 -3
  480. package/tool_registry-791Vrjtf.mjs.map +1 -0
  481. package/{tool_registry-DYUYqXvo.js → tool_registry-CKJPze3j.js} +4 -3
  482. package/tool_registry-CKJPze3j.js.map +1 -0
  483. package/{turn_runner-DqWHNP80.js → turn_runner-HXImLGIn.js} +7 -7
  484. package/turn_runner-HXImLGIn.js.map +1 -0
  485. package/{turn_runner-fg1Wc3dK.mjs → turn_runner-ZyYO-Kti.mjs} +7 -7
  486. package/turn_runner-ZyYO-Kti.mjs.map +1 -0
  487. package/turn_runner.cjs +1 -1
  488. package/turn_runner.mjs +1 -1
  489. package/types.d.ts +1 -1
  490. package/common-BT0nfCi9.mjs.map +0 -1
  491. package/common-Cj8TaQ9U.js.map +0 -1
  492. package/exceptions-BeWH2FwP.mjs.map +0 -1
  493. package/exceptions-CitH5wZI.js.map +0 -1
  494. package/spooled_markdown_artifact-CALSDxIx.js.map +0 -1
  495. package/spooled_markdown_artifact-Ci5UL7l4.mjs.map +0 -1
  496. package/tool_call-CV5qVNlb.mjs.map +0 -1
  497. package/tool_call-Db68hB7y.js.map +0 -1
  498. package/tool_registry-D1pSSlsd.mjs.map +0 -1
  499. package/tool_registry-DYUYqXvo.js.map +0 -1
  500. package/turn_runner-DqWHNP80.js.map +0 -1
  501. package/turn_runner-fg1Wc3dK.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./chunk-Ble4zEEl.js");
3
- const require_dispatch_runner = require("./dispatch_runner-BHBNupqp.js");
3
+ const require_dispatch_runner = require("./dispatch_runner-nHDKkxye.js");
4
4
  exports.DispatchRunner = require_dispatch_runner.DispatchRunner;
@@ -14,4 +14,4 @@ export type { RawDispatchRunnerInput } from "./lib/dispatch_runner";
14
14
  /**
15
15
  * @primaryExport
16
16
  */
17
- export type { DispatchPipelineMiddlewareFn, DispatchExecutorFn, DispatchExecutorHelpers, DispatchExecutorLogChannel, DispatchExecutorLogEntry, DispatchExecutorLogLevel, LogEvent, DispatchStartEvent, DispatchEndEvent, IterationStartEvent, IterationEndEvent, DispatchRunnerFunctionalHooks, DispatchRunnerObservabilityHooks, DispatchRunnerFunctionalHookRegistrations, DispatchRunnerObservabilityHookRegistrations, } from "./lib/types/dispatch_runner";
17
+ export type { DispatchPipelineMiddlewareFn, DispatchExecutorFn, DispatchExecutorHelpers, DispatchExecutorLogChannel, DispatchExecutorLogEntry, DispatchExecutorLogLevel, LogEvent, GenerationStats, GenerationStatsEvent, DispatchStartEvent, DispatchEndEvent, IterationStartEvent, IterationEndEvent, DispatchRunnerFunctionalHooks, DispatchRunnerObservabilityHooks, DispatchRunnerFunctionalHookRegistrations, DispatchRunnerObservabilityHookRegistrations, } from "./lib/types/dispatch_runner";
@@ -1,2 +1,2 @@
1
- import { t as DispatchRunner } from "./dispatch_runner-DPcS7Y_M.mjs";
1
+ import { t as DispatchRunner } from "./dispatch_runner--ZhdDWRZ.mjs";
2
2
  export { DispatchRunner };
@@ -27,6 +27,7 @@ var literalKey = (prop) => {
27
27
  if (prop.key.type === "Literal" && typeof prop.key.value === "string") return prop.key.value;
28
28
  };
29
29
  var isUndefinedValue = (node) => node.type === "Identifier" && node.name === "undefined";
30
+ /** ESLint rule: flags `new ArtifactTool({ … })` that sets the forbidden `artifactConstructor` option. */
30
31
  var artifactToolForbidsArtifactConstructorRule = require_common.createRule({
31
32
  name: "artifact-tool-forbids-artifact-constructor",
32
33
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"artifact_tool_forbids_artifact_constructor.cjs","names":[],"sources":["../../../src/eslint/rules/artifact_tool_forbids_artifact_constructor.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/artifact_tool_forbids_artifact_constructor\n *\n * Flags `new ArtifactTool({ … })` whose options literal sets an `artifactConstructor`.\n *\n * Why: an `ArtifactTool` is the tool that answers queries AGAINST a spooled artifact — it must not\n * itself return a `SpooledArtifact`, or the result would be re-wrapped into another artifact whose\n * query tools are themselves `ArtifactTool`s, and so on without end. The base `RawTool` accepts an\n * `artifactConstructor` (the subclass used to wrap a tool's bytes), but `ArtifactTool` explicitly\n * FORBIDS it (`artifactConstructor: validator.any().forbidden()` in its schema). Supplying one is a\n * recursion footgun the constructor rejects at runtime; this rule surfaces it at the construction\n * site so it fails lint.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst isUndefinedValue = (node: TSESTree.Node): boolean =>\n node.type === 'Identifier' && node.name === 'undefined'\n\nconst artifactToolForbidsArtifactConstructorRule = createRule({\n name: 'artifact-tool-forbids-artifact-constructor',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'An `ArtifactTool` must not declare `artifactConstructor` — it answers queries against an artifact and cannot itself return one (infinite re-wrapping). The ArtifactTool schema forbids the field at runtime; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n forbidArtifactConstructor:\n '`new ArtifactTool` must not set `artifactConstructor` — an artifact-query tool cannot itself return a SpooledArtifact (it would re-wrap forever). The ArtifactTool schema forbids this field. Remove it. Opt out with an eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier' || node.callee.name !== 'ArtifactTool') return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') continue\n if (literalKey(p) === 'artifactConstructor' && !isUndefinedValue(p.value)) {\n context.report({ node: p, messageId: 'forbidArtifactConstructor' })\n }\n }\n },\n }\n },\n})\n\nexport default artifactToolForbidsArtifactConstructorRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,oBAAoB,SACxB,KAAK,SAAS,gBAAgB,KAAK,SAAS;AAE9C,IAAM,6CAA6C,eAAA,WAAW;CAC5D,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,0PACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,2BACE,qTACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,gBAAgB;GAC9E,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;IAChC,IAAI,WAAW,CAAC,MAAM,yBAAyB,CAAC,iBAAiB,EAAE,KAAK,GACtE,QAAQ,OAAO;KAAE,MAAM;KAAG,WAAW;IAA4B,CAAC;GAEtE;EACF,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"artifact_tool_forbids_artifact_constructor.cjs","names":[],"sources":["../../../src/eslint/rules/artifact_tool_forbids_artifact_constructor.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/artifact_tool_forbids_artifact_constructor\n *\n * Flags `new ArtifactTool({ … })` whose options literal sets an `artifactConstructor`.\n *\n * Why: an `ArtifactTool` is the tool that answers queries AGAINST a spooled artifact — it must not\n * itself return a `SpooledArtifact`, or the result would be re-wrapped into another artifact whose\n * query tools are themselves `ArtifactTool`s, and so on without end. The base `RawTool` accepts an\n * `artifactConstructor` (the subclass used to wrap a tool's bytes), but `ArtifactTool` explicitly\n * FORBIDS it (`artifactConstructor: validator.any().forbidden()` in its schema). Supplying one is a\n * recursion footgun the constructor rejects at runtime; this rule surfaces it at the construction\n * site so it fails lint.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst isUndefinedValue = (node: TSESTree.Node): boolean =>\n node.type === 'Identifier' && node.name === 'undefined'\n\n/** ESLint rule: flags `new ArtifactTool({ … })` that sets the forbidden `artifactConstructor` option. */\nconst artifactToolForbidsArtifactConstructorRule = createRule({\n name: 'artifact-tool-forbids-artifact-constructor',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'An `ArtifactTool` must not declare `artifactConstructor` — it answers queries against an artifact and cannot itself return one (infinite re-wrapping). The ArtifactTool schema forbids the field at runtime; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n forbidArtifactConstructor:\n '`new ArtifactTool` must not set `artifactConstructor` — an artifact-query tool cannot itself return a SpooledArtifact (it would re-wrap forever). The ArtifactTool schema forbids this field. Remove it. Opt out with an eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier' || node.callee.name !== 'ArtifactTool') return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') continue\n if (literalKey(p) === 'artifactConstructor' && !isUndefinedValue(p.value)) {\n context.report({ node: p, messageId: 'forbidArtifactConstructor' })\n }\n }\n },\n }\n },\n})\n\nexport default artifactToolForbidsArtifactConstructorRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,oBAAoB,SACxB,KAAK,SAAS,gBAAgB,KAAK,SAAS;;AAG9C,IAAM,6CAA6C,eAAA,WAAW;CAC5D,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,0PACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,2BACE,qTACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,gBAAgB;GAC9E,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;IAChC,IAAI,WAAW,CAAC,MAAM,yBAAyB,CAAC,iBAAiB,EAAE,KAAK,GACtE,QAAQ,OAAO;KAAE,MAAM;KAAG,WAAW;IAA4B,CAAC;GAEtE;EACF,EACF;CACF;AACF,CAAC"}
@@ -14,6 +14,7 @@
14
14
  * Opt-out:
15
15
  * // eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor -- <reason>
16
16
  */
17
+ /** ESLint rule: flags `new ArtifactTool({ … })` that sets the forbidden `artifactConstructor` option. */
17
18
  declare const artifactToolForbidsArtifactConstructorRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"forbidArtifactConstructor", [
18
19
  ], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
19
20
  name: string;
@@ -22,6 +22,7 @@ var literalKey = (prop) => {
22
22
  if (prop.key.type === "Literal" && typeof prop.key.value === "string") return prop.key.value;
23
23
  };
24
24
  var isUndefinedValue = (node) => node.type === "Identifier" && node.name === "undefined";
25
+ /** ESLint rule: flags `new ArtifactTool({ … })` that sets the forbidden `artifactConstructor` option. */
25
26
  var artifactToolForbidsArtifactConstructorRule = createRule({
26
27
  name: "artifact-tool-forbids-artifact-constructor",
27
28
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"artifact_tool_forbids_artifact_constructor.mjs","names":[],"sources":["../../../src/eslint/rules/artifact_tool_forbids_artifact_constructor.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/artifact_tool_forbids_artifact_constructor\n *\n * Flags `new ArtifactTool({ … })` whose options literal sets an `artifactConstructor`.\n *\n * Why: an `ArtifactTool` is the tool that answers queries AGAINST a spooled artifact — it must not\n * itself return a `SpooledArtifact`, or the result would be re-wrapped into another artifact whose\n * query tools are themselves `ArtifactTool`s, and so on without end. The base `RawTool` accepts an\n * `artifactConstructor` (the subclass used to wrap a tool's bytes), but `ArtifactTool` explicitly\n * FORBIDS it (`artifactConstructor: validator.any().forbidden()` in its schema). Supplying one is a\n * recursion footgun the constructor rejects at runtime; this rule surfaces it at the construction\n * site so it fails lint.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst isUndefinedValue = (node: TSESTree.Node): boolean =>\n node.type === 'Identifier' && node.name === 'undefined'\n\nconst artifactToolForbidsArtifactConstructorRule = createRule({\n name: 'artifact-tool-forbids-artifact-constructor',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'An `ArtifactTool` must not declare `artifactConstructor` — it answers queries against an artifact and cannot itself return one (infinite re-wrapping). The ArtifactTool schema forbids the field at runtime; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n forbidArtifactConstructor:\n '`new ArtifactTool` must not set `artifactConstructor` — an artifact-query tool cannot itself return a SpooledArtifact (it would re-wrap forever). The ArtifactTool schema forbids this field. Remove it. Opt out with an eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier' || node.callee.name !== 'ArtifactTool') return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') continue\n if (literalKey(p) === 'artifactConstructor' && !isUndefinedValue(p.value)) {\n context.report({ node: p, messageId: 'forbidArtifactConstructor' })\n }\n }\n },\n }\n },\n})\n\nexport default artifactToolForbidsArtifactConstructorRule\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqBA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,oBAAoB,SACxB,KAAK,SAAS,gBAAgB,KAAK,SAAS;AAE9C,IAAM,6CAA6C,WAAW;CAC5D,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,0PACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,2BACE,qTACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,gBAAgB;GAC9E,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;IAChC,IAAI,WAAW,CAAC,MAAM,yBAAyB,CAAC,iBAAiB,EAAE,KAAK,GACtE,QAAQ,OAAO;KAAE,MAAM;KAAG,WAAW;IAA4B,CAAC;GAEtE;EACF,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"artifact_tool_forbids_artifact_constructor.mjs","names":[],"sources":["../../../src/eslint/rules/artifact_tool_forbids_artifact_constructor.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/artifact_tool_forbids_artifact_constructor\n *\n * Flags `new ArtifactTool({ … })` whose options literal sets an `artifactConstructor`.\n *\n * Why: an `ArtifactTool` is the tool that answers queries AGAINST a spooled artifact — it must not\n * itself return a `SpooledArtifact`, or the result would be re-wrapped into another artifact whose\n * query tools are themselves `ArtifactTool`s, and so on without end. The base `RawTool` accepts an\n * `artifactConstructor` (the subclass used to wrap a tool's bytes), but `ArtifactTool` explicitly\n * FORBIDS it (`artifactConstructor: validator.any().forbidden()` in its schema). Supplying one is a\n * recursion footgun the constructor rejects at runtime; this rule surfaces it at the construction\n * site so it fails lint.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst isUndefinedValue = (node: TSESTree.Node): boolean =>\n node.type === 'Identifier' && node.name === 'undefined'\n\n/** ESLint rule: flags `new ArtifactTool({ … })` that sets the forbidden `artifactConstructor` option. */\nconst artifactToolForbidsArtifactConstructorRule = createRule({\n name: 'artifact-tool-forbids-artifact-constructor',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'An `ArtifactTool` must not declare `artifactConstructor` — it answers queries against an artifact and cannot itself return one (infinite re-wrapping). The ArtifactTool schema forbids the field at runtime; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n forbidArtifactConstructor:\n '`new ArtifactTool` must not set `artifactConstructor` — an artifact-query tool cannot itself return a SpooledArtifact (it would re-wrap forever). The ArtifactTool schema forbids this field. Remove it. Opt out with an eslint-disable-next-line adk/artifact-tool-forbids-artifact-constructor comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier' || node.callee.name !== 'ArtifactTool') return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') continue\n if (literalKey(p) === 'artifactConstructor' && !isUndefinedValue(p.value)) {\n context.report({ node: p, messageId: 'forbidArtifactConstructor' })\n }\n }\n },\n }\n },\n})\n\nexport default artifactToolForbidsArtifactConstructorRule\n"],"mappings":";;;;;;;;;;;;;;;;;;AAqBA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,oBAAoB,SACxB,KAAK,SAAS,gBAAgB,KAAK,SAAS;;AAG9C,IAAM,6CAA6C,WAAW;CAC5D,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,0PACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,2BACE,qTACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,gBAAgB;GAC9E,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;IAChC,IAAI,WAAW,CAAC,MAAM,yBAAyB,CAAC,iBAAiB,EAAE,KAAK,GACtE,QAAQ,OAAO;KAAE,MAAM;KAAG,WAAW;IAA4B,CAAC;GAEtE;EACF,EACF;CACF;AACF,CAAC"}
@@ -31,6 +31,7 @@ var literalKey = (prop) => {
31
31
  if (prop.key.type === "Identifier") return prop.key.name;
32
32
  if (prop.key.type === "Literal" && typeof prop.key.value === "string") return prop.key.value;
33
33
  };
34
+ /** ESLint rule: flags referencing the model or LLM adapter inside a tool handler. */
34
35
  var noModelInToolHandlerRule = require_common.createRule({
35
36
  name: "no-model-in-tool-handler",
36
37
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"no_model_in_tool_handler.cjs","names":[],"sources":["../../../src/eslint/rules/no_model_in_tool_handler.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/no_model_in_tool_handler\n *\n * Flags an LLM/model call inside a `Tool` / `ArtifactTool` `handler`.\n *\n * Why: the executor owns the dispatch loop. A tool handler runs as one step the model proposed; it\n * must do work and return a result, not start its own reasoning loop. Calling a model from inside a\n * handler hides a nested, unmanaged dispatch from the harness — no token accounting, no event\n * surfacing, no abort propagation. The one legitimate exception is a tool that is explicitly a\n * sub-agent running its own scoped dispatch; this rule allows a handler that constructs a\n * `new TurnRunner(...)` or calls the lower-level `DispatchRunner.dispatch(...)`.\n *\n * Detects provider SDK constructors (`new OpenAI()`, `new Anthropic()`) and chat/completion calls\n * (a `.create()` whose receiver chain passes through `messages`/`completions`/`responses`, or a\n * `generateContent()` call) within the `handler` function passed to `new Tool({ handler })` /\n * `new ArtifactTool({ handler })`, ignoring inner closures (so a sub-agent's own callbacks don't\n * false-positive).\n *\n * Opt-out:\n * // eslint-disable-next-line adk/no-model-in-tool-handler -- <reason>\n */\n\nimport {\n createRule,\n isFunctionNode,\n isLlmCall,\n runsSubAgent,\n walkBodySkippingNestedFunctions,\n} from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst noModelInToolHandlerRule = createRule({\n name: 'no-model-in-tool-handler',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A Tool/ArtifactTool handler must not invoke a model — the executor owns the dispatch loop. The only exception is a sub-agent tool that runs its own scoped dispatch via `new TurnRunner(...)` or `DispatchRunner.dispatch(...)`.',\n },\n schema: [],\n messages: {\n noModelInHandler:\n 'Do not call a model inside a tool handler — the executor owns the dispatch loop, and a model call here hides an unmanaged nested dispatch (no token accounting, events, or abort). If this tool is a sub-agent, run a scoped `new TurnRunner(...)` or `DispatchRunner.dispatch(...)` instead. Opt out with an eslint-disable-next-line adk/no-model-in-tool-handler comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (\n node.callee.type !== 'Identifier' ||\n (node.callee.name !== 'Tool' && node.callee.name !== 'ArtifactTool')\n ) {\n return\n }\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n const handlerProp = arg.properties.find(\n (p): p is TSESTree.Property => p.type === 'Property' && literalKey(p) === 'handler'\n )\n if (!handlerProp || !isFunctionNode(handlerProp.value)) return\n const handler = handlerProp.value\n\n // A sub-agent tool legitimately runs a scoped dispatch (new TurnRunner / DispatchRunner.dispatch)\n // — that's the documented exception.\n if (runsSubAgent(handler.body)) return\n\n walkBodySkippingNestedFunctions(handler.body, (n) => {\n if (isLlmCall(n)) {\n context.report({ node: n, messageId: 'noModelInHandler' })\n }\n })\n },\n }\n },\n})\n\nexport default noModelInToolHandlerRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,2BAA2B,eAAA,WAAW;CAC1C,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,mOACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,kBACE,wXACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IACE,KAAK,OAAO,SAAS,gBACpB,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO,SAAS,gBAErD;GAEF,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,MAAM,cAAc,IAAI,WAAW,MAChC,MAA8B,EAAE,SAAS,cAAc,WAAW,CAAC,MAAM,SAC5E;GACA,IAAI,CAAC,eAAe,CAAC,eAAA,eAAe,YAAY,KAAK,GAAG;GACxD,MAAM,UAAU,YAAY;GAI5B,IAAI,eAAA,aAAa,QAAQ,IAAI,GAAG;GAEhC,eAAA,gCAAgC,QAAQ,OAAO,MAAM;IACnD,IAAI,eAAA,UAAU,CAAC,GACb,QAAQ,OAAO;KAAE,MAAM;KAAG,WAAW;IAAmB,CAAC;GAE7D,CAAC;EACH,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"no_model_in_tool_handler.cjs","names":[],"sources":["../../../src/eslint/rules/no_model_in_tool_handler.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/no_model_in_tool_handler\n *\n * Flags an LLM/model call inside a `Tool` / `ArtifactTool` `handler`.\n *\n * Why: the executor owns the dispatch loop. A tool handler runs as one step the model proposed; it\n * must do work and return a result, not start its own reasoning loop. Calling a model from inside a\n * handler hides a nested, unmanaged dispatch from the harness — no token accounting, no event\n * surfacing, no abort propagation. The one legitimate exception is a tool that is explicitly a\n * sub-agent running its own scoped dispatch; this rule allows a handler that constructs a\n * `new TurnRunner(...)` or calls the lower-level `DispatchRunner.dispatch(...)`.\n *\n * Detects provider SDK constructors (`new OpenAI()`, `new Anthropic()`) and chat/completion calls\n * (a `.create()` whose receiver chain passes through `messages`/`completions`/`responses`, or a\n * `generateContent()` call) within the `handler` function passed to `new Tool({ handler })` /\n * `new ArtifactTool({ handler })`, ignoring inner closures (so a sub-agent's own callbacks don't\n * false-positive).\n *\n * Opt-out:\n * // eslint-disable-next-line adk/no-model-in-tool-handler -- <reason>\n */\n\nimport {\n createRule,\n isFunctionNode,\n isLlmCall,\n runsSubAgent,\n walkBodySkippingNestedFunctions,\n} from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\n/** ESLint rule: flags referencing the model or LLM adapter inside a tool handler. */\nconst noModelInToolHandlerRule = createRule({\n name: 'no-model-in-tool-handler',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A Tool/ArtifactTool handler must not invoke a model — the executor owns the dispatch loop. The only exception is a sub-agent tool that runs its own scoped dispatch via `new TurnRunner(...)` or `DispatchRunner.dispatch(...)`.',\n },\n schema: [],\n messages: {\n noModelInHandler:\n 'Do not call a model inside a tool handler — the executor owns the dispatch loop, and a model call here hides an unmanaged nested dispatch (no token accounting, events, or abort). If this tool is a sub-agent, run a scoped `new TurnRunner(...)` or `DispatchRunner.dispatch(...)` instead. Opt out with an eslint-disable-next-line adk/no-model-in-tool-handler comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (\n node.callee.type !== 'Identifier' ||\n (node.callee.name !== 'Tool' && node.callee.name !== 'ArtifactTool')\n ) {\n return\n }\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n const handlerProp = arg.properties.find(\n (p): p is TSESTree.Property => p.type === 'Property' && literalKey(p) === 'handler'\n )\n if (!handlerProp || !isFunctionNode(handlerProp.value)) return\n const handler = handlerProp.value\n\n // A sub-agent tool legitimately runs a scoped dispatch (new TurnRunner / DispatchRunner.dispatch)\n // — that's the documented exception.\n if (runsSubAgent(handler.body)) return\n\n walkBodySkippingNestedFunctions(handler.body, (n) => {\n if (isLlmCall(n)) {\n context.report({ node: n, messageId: 'noModelInHandler' })\n }\n })\n },\n }\n },\n})\n\nexport default noModelInToolHandlerRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;;AAGA,IAAM,2BAA2B,eAAA,WAAW;CAC1C,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,mOACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,kBACE,wXACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IACE,KAAK,OAAO,SAAS,gBACpB,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO,SAAS,gBAErD;GAEF,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,MAAM,cAAc,IAAI,WAAW,MAChC,MAA8B,EAAE,SAAS,cAAc,WAAW,CAAC,MAAM,SAC5E;GACA,IAAI,CAAC,eAAe,CAAC,eAAA,eAAe,YAAY,KAAK,GAAG;GACxD,MAAM,UAAU,YAAY;GAI5B,IAAI,eAAA,aAAa,QAAQ,IAAI,GAAG;GAEhC,eAAA,gCAAgC,QAAQ,OAAO,MAAM;IACnD,IAAI,eAAA,UAAU,CAAC,GACb,QAAQ,OAAO;KAAE,MAAM;KAAG,WAAW;IAAmB,CAAC;GAE7D,CAAC;EACH,EACF;CACF;AACF,CAAC"}
@@ -19,6 +19,7 @@
19
19
  * Opt-out:
20
20
  * // eslint-disable-next-line adk/no-model-in-tool-handler -- <reason>
21
21
  */
22
+ /** ESLint rule: flags referencing the model or LLM adapter inside a tool handler. */
22
23
  declare const noModelInToolHandlerRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noModelInHandler", [
23
24
  ], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
24
25
  name: string;
@@ -26,6 +26,7 @@ var literalKey = (prop) => {
26
26
  if (prop.key.type === "Identifier") return prop.key.name;
27
27
  if (prop.key.type === "Literal" && typeof prop.key.value === "string") return prop.key.value;
28
28
  };
29
+ /** ESLint rule: flags referencing the model or LLM adapter inside a tool handler. */
29
30
  var noModelInToolHandlerRule = createRule({
30
31
  name: "no-model-in-tool-handler",
31
32
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"no_model_in_tool_handler.mjs","names":[],"sources":["../../../src/eslint/rules/no_model_in_tool_handler.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/no_model_in_tool_handler\n *\n * Flags an LLM/model call inside a `Tool` / `ArtifactTool` `handler`.\n *\n * Why: the executor owns the dispatch loop. A tool handler runs as one step the model proposed; it\n * must do work and return a result, not start its own reasoning loop. Calling a model from inside a\n * handler hides a nested, unmanaged dispatch from the harness — no token accounting, no event\n * surfacing, no abort propagation. The one legitimate exception is a tool that is explicitly a\n * sub-agent running its own scoped dispatch; this rule allows a handler that constructs a\n * `new TurnRunner(...)` or calls the lower-level `DispatchRunner.dispatch(...)`.\n *\n * Detects provider SDK constructors (`new OpenAI()`, `new Anthropic()`) and chat/completion calls\n * (a `.create()` whose receiver chain passes through `messages`/`completions`/`responses`, or a\n * `generateContent()` call) within the `handler` function passed to `new Tool({ handler })` /\n * `new ArtifactTool({ handler })`, ignoring inner closures (so a sub-agent's own callbacks don't\n * false-positive).\n *\n * Opt-out:\n * // eslint-disable-next-line adk/no-model-in-tool-handler -- <reason>\n */\n\nimport {\n createRule,\n isFunctionNode,\n isLlmCall,\n runsSubAgent,\n walkBodySkippingNestedFunctions,\n} from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst noModelInToolHandlerRule = createRule({\n name: 'no-model-in-tool-handler',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A Tool/ArtifactTool handler must not invoke a model — the executor owns the dispatch loop. The only exception is a sub-agent tool that runs its own scoped dispatch via `new TurnRunner(...)` or `DispatchRunner.dispatch(...)`.',\n },\n schema: [],\n messages: {\n noModelInHandler:\n 'Do not call a model inside a tool handler — the executor owns the dispatch loop, and a model call here hides an unmanaged nested dispatch (no token accounting, events, or abort). If this tool is a sub-agent, run a scoped `new TurnRunner(...)` or `DispatchRunner.dispatch(...)` instead. Opt out with an eslint-disable-next-line adk/no-model-in-tool-handler comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (\n node.callee.type !== 'Identifier' ||\n (node.callee.name !== 'Tool' && node.callee.name !== 'ArtifactTool')\n ) {\n return\n }\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n const handlerProp = arg.properties.find(\n (p): p is TSESTree.Property => p.type === 'Property' && literalKey(p) === 'handler'\n )\n if (!handlerProp || !isFunctionNode(handlerProp.value)) return\n const handler = handlerProp.value\n\n // A sub-agent tool legitimately runs a scoped dispatch (new TurnRunner / DispatchRunner.dispatch)\n // — that's the documented exception.\n if (runsSubAgent(handler.body)) return\n\n walkBodySkippingNestedFunctions(handler.body, (n) => {\n if (isLlmCall(n)) {\n context.report({ node: n, messageId: 'noModelInHandler' })\n }\n })\n },\n }\n },\n})\n\nexport default noModelInToolHandlerRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,2BAA2B,WAAW;CAC1C,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,mOACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,kBACE,wXACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IACE,KAAK,OAAO,SAAS,gBACpB,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO,SAAS,gBAErD;GAEF,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,MAAM,cAAc,IAAI,WAAW,MAChC,MAA8B,EAAE,SAAS,cAAc,WAAW,CAAC,MAAM,SAC5E;GACA,IAAI,CAAC,eAAe,CAAC,eAAe,YAAY,KAAK,GAAG;GACxD,MAAM,UAAU,YAAY;GAI5B,IAAI,aAAa,QAAQ,IAAI,GAAG;GAEhC,gCAAgC,QAAQ,OAAO,MAAM;IACnD,IAAI,UAAU,CAAC,GACb,QAAQ,OAAO;KAAE,MAAM;KAAG,WAAW;IAAmB,CAAC;GAE7D,CAAC;EACH,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"no_model_in_tool_handler.mjs","names":[],"sources":["../../../src/eslint/rules/no_model_in_tool_handler.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/no_model_in_tool_handler\n *\n * Flags an LLM/model call inside a `Tool` / `ArtifactTool` `handler`.\n *\n * Why: the executor owns the dispatch loop. A tool handler runs as one step the model proposed; it\n * must do work and return a result, not start its own reasoning loop. Calling a model from inside a\n * handler hides a nested, unmanaged dispatch from the harness — no token accounting, no event\n * surfacing, no abort propagation. The one legitimate exception is a tool that is explicitly a\n * sub-agent running its own scoped dispatch; this rule allows a handler that constructs a\n * `new TurnRunner(...)` or calls the lower-level `DispatchRunner.dispatch(...)`.\n *\n * Detects provider SDK constructors (`new OpenAI()`, `new Anthropic()`) and chat/completion calls\n * (a `.create()` whose receiver chain passes through `messages`/`completions`/`responses`, or a\n * `generateContent()` call) within the `handler` function passed to `new Tool({ handler })` /\n * `new ArtifactTool({ handler })`, ignoring inner closures (so a sub-agent's own callbacks don't\n * false-positive).\n *\n * Opt-out:\n * // eslint-disable-next-line adk/no-model-in-tool-handler -- <reason>\n */\n\nimport {\n createRule,\n isFunctionNode,\n isLlmCall,\n runsSubAgent,\n walkBodySkippingNestedFunctions,\n} from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\n/** ESLint rule: flags referencing the model or LLM adapter inside a tool handler. */\nconst noModelInToolHandlerRule = createRule({\n name: 'no-model-in-tool-handler',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A Tool/ArtifactTool handler must not invoke a model — the executor owns the dispatch loop. The only exception is a sub-agent tool that runs its own scoped dispatch via `new TurnRunner(...)` or `DispatchRunner.dispatch(...)`.',\n },\n schema: [],\n messages: {\n noModelInHandler:\n 'Do not call a model inside a tool handler — the executor owns the dispatch loop, and a model call here hides an unmanaged nested dispatch (no token accounting, events, or abort). If this tool is a sub-agent, run a scoped `new TurnRunner(...)` or `DispatchRunner.dispatch(...)` instead. Opt out with an eslint-disable-next-line adk/no-model-in-tool-handler comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (\n node.callee.type !== 'Identifier' ||\n (node.callee.name !== 'Tool' && node.callee.name !== 'ArtifactTool')\n ) {\n return\n }\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n const handlerProp = arg.properties.find(\n (p): p is TSESTree.Property => p.type === 'Property' && literalKey(p) === 'handler'\n )\n if (!handlerProp || !isFunctionNode(handlerProp.value)) return\n const handler = handlerProp.value\n\n // A sub-agent tool legitimately runs a scoped dispatch (new TurnRunner / DispatchRunner.dispatch)\n // — that's the documented exception.\n if (runsSubAgent(handler.body)) return\n\n walkBodySkippingNestedFunctions(handler.body, (n) => {\n if (isLlmCall(n)) {\n context.report({ node: n, messageId: 'noModelInHandler' })\n }\n })\n },\n }\n },\n})\n\nexport default noModelInToolHandlerRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;;AAGA,IAAM,2BAA2B,WAAW;CAC1C,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,mOACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,kBACE,wXACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IACE,KAAK,OAAO,SAAS,gBACpB,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO,SAAS,gBAErD;GAEF,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,MAAM,cAAc,IAAI,WAAW,MAChC,MAA8B,EAAE,SAAS,cAAc,WAAW,CAAC,MAAM,SAC5E;GACA,IAAI,CAAC,eAAe,CAAC,eAAe,YAAY,KAAK,GAAG;GACxD,MAAM,UAAU,YAAY;GAI5B,IAAI,aAAa,QAAQ,IAAI,GAAG;GAEhC,gCAAgC,QAAQ,OAAO,MAAM;IACnD,IAAI,UAAU,CAAC,GACb,QAAQ,OAAO;KAAE,MAAM;KAAG,WAAW;IAAmB,CAAC;GAE7D,CAAC;EACH,EACF;CACF;AACF,CAAC"}
@@ -72,6 +72,7 @@ var collectChainCalls = (anyCall) => {
72
72
  return calls;
73
73
  };
74
74
  var chainCalls = (calls, name) => calls.some((c) => c.callee.type === "MemberExpression" && c.callee.property.type === "Identifier" && c.callee.property.name === name);
75
+ /** ESLint rule: flags a validator `any()` schema lacking an explicit required/optional/forbidden disposition. */
75
76
  var requireValidatorAnyRequiredRule = require_common.createRule({
76
77
  name: "require-validator-any-required",
77
78
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"require_validator_any_required.cjs","names":[],"sources":["../../../src/eslint/rules/require_validator_any_required.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/require_validator_any_required\n *\n * Flags every `validator.any()` schema chain that does not declare intent with `.required()`\n * or `.optional()`.\n *\n * Why: in `@nhtio/validation`, `.any()` ADMITS `null`/`undefined` unless you make it `.required()`.\n * That default is silent and easy to miss — a schema you believe rejects missing values quietly\n * accepts them, and any `.custom()` refinement is skipped for an absent value (a `.custom()` guard\n * is the usual way this surfaces, e.g. `implementsX(undefined) === true`). The fix is to make the\n * disposition an EXPLICIT declaration with no ambiguity — every `.any()` must say which it is:\n * - `.required()` → reject null/undefined\n * - `.optional()` → deliberately allow null/undefined\n * - `.default(x)` → allow absence, substituting a fallback value\n * - `.forbidden()` → the value must be absent\n * This applies whether the `.any()` is top-level or nested inside `items(...)` / `alternatives(...)`:\n * the enclosing schema being `.required()` does NOT govern an inner `.any()`'s null/undefined handling.\n *\n * The sharpest illustration is `.valid(null)`: an author writing `validator.any().valid(null)`\n * means \"must be exactly null\" — but because `.any()` admits `undefined`, that schema actually\n * accepts BOTH `null` and `undefined` (and `undefined !== null`). The fix is\n * `validator.any().required().valid(null)`.\n *\n * Opt-out (e.g. a bare `.any()` used purely as a type argument like `items(validator.any())`):\n * // eslint-disable-next-line adk/require-validator-any-required -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\n// The base identifier a member/call chain roots at, e.g. `validator` in `validator.any()` or\n// `validator.alternatives(...).any()`. Returns undefined if the chain doesn't root at a plain name.\nconst baseIdentifierName = (node: TSESTree.Node | undefined): string | undefined => {\n let cur: TSESTree.Node | undefined = node\n while (cur) {\n if (cur.type === 'Identifier') return cur.name\n if (cur.type === 'MemberExpression') {\n cur = cur.object\n continue\n }\n if (cur.type === 'CallExpression') {\n cur = cur.callee\n continue\n }\n return undefined\n }\n return undefined\n}\n\n// `validator.any()` (or a `validator.…().any()` chain) — NOT `expect.any()`, `_.any()`, etc.\nconst isAnyCall = (node: TSESTree.CallExpression): boolean =>\n node.callee.type === 'MemberExpression' &&\n node.callee.property.type === 'Identifier' &&\n node.callee.property.name === 'any' &&\n baseIdentifierName(node.callee.object) === 'validator'\n\n// Collect every CallExpression in the method chain `anyCall` belongs to — inward through the\n// callee object (`a.b().c()` -> `a.b()`) and outward through `.parent` links\n// (`x.any()` -> `x.any().required` -> `x.any().required()`).\nconst collectChainCalls = (anyCall: TSESTree.CallExpression): TSESTree.CallExpression[] => {\n const calls: TSESTree.CallExpression[] = []\n\n let cur: TSESTree.Node | null = anyCall\n while (cur && cur.type === 'CallExpression') {\n calls.push(cur)\n cur = cur.callee.type === 'MemberExpression' ? cur.callee.object : null\n }\n\n cur = anyCall\n while (cur) {\n const p: TSESTree.Node | undefined = cur.parent\n if (!p) break\n if (p.type === 'MemberExpression' && p.object === cur) {\n cur = p\n continue\n }\n if (p.type === 'CallExpression' && p.callee === cur) {\n calls.push(p)\n cur = p\n continue\n }\n break\n }\n\n return calls\n}\n\nconst chainCalls = (calls: TSESTree.CallExpression[], name: string): boolean =>\n calls.some(\n (c) =>\n c.callee.type === 'MemberExpression' &&\n c.callee.property.type === 'Identifier' &&\n c.callee.property.name === name\n )\n\nconst requireValidatorAnyRequiredRule = createRule({\n name: 'require-validator-any-required',\n meta: {\n type: 'problem',\n docs: {\n description:\n '`validator.any()` admits null/undefined unless `.required()`; make the disposition explicit by ending every `.any()` in `.required()`, `.optional()`, or `.default(…)`. Opt out with a tactical disable comment + reason.',\n },\n schema: [],\n messages: {\n declareIntent:\n '`validator.any()` admits null/undefined unless made `.required()`. Make the disposition explicit: end this `.any()` in `.required()` (reject null/undefined), `.optional()` (deliberately allow it), or `.default(…)` (allow it with a fallback) — applies even when nested in items()/alternatives(). Or add an eslint-disable-next-line adk/require-validator-any-required comment with a reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression) {\n if (!isAnyCall(node)) return\n const calls = collectChainCalls(node)\n // An unambiguous disposition declaration clears the rule:\n // .required() — reject null/undefined\n // .optional() — deliberately allow null/undefined\n // .default(x) — allow absence, substituting a fallback\n // .forbidden() — the value must be absent\n if (\n chainCalls(calls, 'required') ||\n chainCalls(calls, 'optional') ||\n chainCalls(calls, 'default') ||\n chainCalls(calls, 'forbidden')\n ) {\n return\n }\n const reportNode = node.callee.type === 'MemberExpression' ? node.callee.property : node\n context.report({ node: reportNode, messageId: 'declareIntent' })\n },\n }\n },\n})\n\nexport default requireValidatorAnyRequiredRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAM,sBAAsB,SAAwD;CAClF,IAAI,MAAiC;CACrC,OAAO,KAAK;EACV,IAAI,IAAI,SAAS,cAAc,OAAO,IAAI;EAC1C,IAAI,IAAI,SAAS,oBAAoB;GACnC,MAAM,IAAI;GACV;EACF;EACA,IAAI,IAAI,SAAS,kBAAkB;GACjC,MAAM,IAAI;GACV;EACF;EACA;CACF;AAEF;AAGA,IAAM,aAAa,SACjB,KAAK,OAAO,SAAS,sBACrB,KAAK,OAAO,SAAS,SAAS,gBAC9B,KAAK,OAAO,SAAS,SAAS,SAC9B,mBAAmB,KAAK,OAAO,MAAM,MAAM;AAK7C,IAAM,qBAAqB,YAAgE;CACzF,MAAM,QAAmC,CAAC;CAE1C,IAAI,MAA4B;CAChC,OAAO,OAAO,IAAI,SAAS,kBAAkB;EAC3C,MAAM,KAAK,GAAG;EACd,MAAM,IAAI,OAAO,SAAS,qBAAqB,IAAI,OAAO,SAAS;CACrE;CAEA,MAAM;CACN,OAAO,KAAK;EACV,MAAM,IAA+B,IAAI;EACzC,IAAI,CAAC,GAAG;EACR,IAAI,EAAE,SAAS,sBAAsB,EAAE,WAAW,KAAK;GACrD,MAAM;GACN;EACF;EACA,IAAI,EAAE,SAAS,oBAAoB,EAAE,WAAW,KAAK;GACnD,MAAM,KAAK,CAAC;GACZ,MAAM;GACN;EACF;EACA;CACF;CAEA,OAAO;AACT;AAEA,IAAM,cAAc,OAAkC,SACpD,MAAM,MACH,MACC,EAAE,OAAO,SAAS,sBAClB,EAAE,OAAO,SAAS,SAAS,gBAC3B,EAAE,OAAO,SAAS,SAAS,IAC/B;AAEF,IAAM,kCAAkC,eAAA,WAAW;CACjD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,4NACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,eACE,sYACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,eAAe,MAA+B;GAC5C,IAAI,CAAC,UAAU,IAAI,GAAG;GACtB,MAAM,QAAQ,kBAAkB,IAAI;GAMpC,IACE,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,SAAS,KAC3B,WAAW,OAAO,WAAW,GAE7B;GAEF,MAAM,aAAa,KAAK,OAAO,SAAS,qBAAqB,KAAK,OAAO,WAAW;GACpF,QAAQ,OAAO;IAAE,MAAM;IAAY,WAAW;GAAgB,CAAC;EACjE,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"require_validator_any_required.cjs","names":[],"sources":["../../../src/eslint/rules/require_validator_any_required.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/require_validator_any_required\n *\n * Flags every `validator.any()` schema chain that does not declare intent with `.required()`\n * or `.optional()`.\n *\n * Why: in `@nhtio/validation`, `.any()` ADMITS `null`/`undefined` unless you make it `.required()`.\n * That default is silent and easy to miss — a schema you believe rejects missing values quietly\n * accepts them, and any `.custom()` refinement is skipped for an absent value (a `.custom()` guard\n * is the usual way this surfaces, e.g. `implementsX(undefined) === true`). The fix is to make the\n * disposition an EXPLICIT declaration with no ambiguity — every `.any()` must say which it is:\n * - `.required()` → reject null/undefined\n * - `.optional()` → deliberately allow null/undefined\n * - `.default(x)` → allow absence, substituting a fallback value\n * - `.forbidden()` → the value must be absent\n * This applies whether the `.any()` is top-level or nested inside `items(...)` / `alternatives(...)`:\n * the enclosing schema being `.required()` does NOT govern an inner `.any()`'s null/undefined handling.\n *\n * The sharpest illustration is `.valid(null)`: an author writing `validator.any().valid(null)`\n * means \"must be exactly null\" — but because `.any()` admits `undefined`, that schema actually\n * accepts BOTH `null` and `undefined` (and `undefined !== null`). The fix is\n * `validator.any().required().valid(null)`.\n *\n * Opt-out (e.g. a bare `.any()` used purely as a type argument like `items(validator.any())`):\n * // eslint-disable-next-line adk/require-validator-any-required -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\n// The base identifier a member/call chain roots at, e.g. `validator` in `validator.any()` or\n// `validator.alternatives(...).any()`. Returns undefined if the chain doesn't root at a plain name.\nconst baseIdentifierName = (node: TSESTree.Node | undefined): string | undefined => {\n let cur: TSESTree.Node | undefined = node\n while (cur) {\n if (cur.type === 'Identifier') return cur.name\n if (cur.type === 'MemberExpression') {\n cur = cur.object\n continue\n }\n if (cur.type === 'CallExpression') {\n cur = cur.callee\n continue\n }\n return undefined\n }\n return undefined\n}\n\n// `validator.any()` (or a `validator.…().any()` chain) — NOT `expect.any()`, `_.any()`, etc.\nconst isAnyCall = (node: TSESTree.CallExpression): boolean =>\n node.callee.type === 'MemberExpression' &&\n node.callee.property.type === 'Identifier' &&\n node.callee.property.name === 'any' &&\n baseIdentifierName(node.callee.object) === 'validator'\n\n// Collect every CallExpression in the method chain `anyCall` belongs to — inward through the\n// callee object (`a.b().c()` -> `a.b()`) and outward through `.parent` links\n// (`x.any()` -> `x.any().required` -> `x.any().required()`).\nconst collectChainCalls = (anyCall: TSESTree.CallExpression): TSESTree.CallExpression[] => {\n const calls: TSESTree.CallExpression[] = []\n\n let cur: TSESTree.Node | null = anyCall\n while (cur && cur.type === 'CallExpression') {\n calls.push(cur)\n cur = cur.callee.type === 'MemberExpression' ? cur.callee.object : null\n }\n\n cur = anyCall\n while (cur) {\n const p: TSESTree.Node | undefined = cur.parent\n if (!p) break\n if (p.type === 'MemberExpression' && p.object === cur) {\n cur = p\n continue\n }\n if (p.type === 'CallExpression' && p.callee === cur) {\n calls.push(p)\n cur = p\n continue\n }\n break\n }\n\n return calls\n}\n\nconst chainCalls = (calls: TSESTree.CallExpression[], name: string): boolean =>\n calls.some(\n (c) =>\n c.callee.type === 'MemberExpression' &&\n c.callee.property.type === 'Identifier' &&\n c.callee.property.name === name\n )\n\n/** ESLint rule: flags a validator `any()` schema lacking an explicit required/optional/forbidden disposition. */\nconst requireValidatorAnyRequiredRule = createRule({\n name: 'require-validator-any-required',\n meta: {\n type: 'problem',\n docs: {\n description:\n '`validator.any()` admits null/undefined unless `.required()`; make the disposition explicit by ending every `.any()` in `.required()`, `.optional()`, or `.default(…)`. Opt out with a tactical disable comment + reason.',\n },\n schema: [],\n messages: {\n declareIntent:\n '`validator.any()` admits null/undefined unless made `.required()`. Make the disposition explicit: end this `.any()` in `.required()` (reject null/undefined), `.optional()` (deliberately allow it), or `.default(…)` (allow it with a fallback) — applies even when nested in items()/alternatives(). Or add an eslint-disable-next-line adk/require-validator-any-required comment with a reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression) {\n if (!isAnyCall(node)) return\n const calls = collectChainCalls(node)\n // An unambiguous disposition declaration clears the rule:\n // .required() — reject null/undefined\n // .optional() — deliberately allow null/undefined\n // .default(x) — allow absence, substituting a fallback\n // .forbidden() — the value must be absent\n if (\n chainCalls(calls, 'required') ||\n chainCalls(calls, 'optional') ||\n chainCalls(calls, 'default') ||\n chainCalls(calls, 'forbidden')\n ) {\n return\n }\n const reportNode = node.callee.type === 'MemberExpression' ? node.callee.property : node\n context.report({ node: reportNode, messageId: 'declareIntent' })\n },\n }\n },\n})\n\nexport default requireValidatorAnyRequiredRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAM,sBAAsB,SAAwD;CAClF,IAAI,MAAiC;CACrC,OAAO,KAAK;EACV,IAAI,IAAI,SAAS,cAAc,OAAO,IAAI;EAC1C,IAAI,IAAI,SAAS,oBAAoB;GACnC,MAAM,IAAI;GACV;EACF;EACA,IAAI,IAAI,SAAS,kBAAkB;GACjC,MAAM,IAAI;GACV;EACF;EACA;CACF;AAEF;AAGA,IAAM,aAAa,SACjB,KAAK,OAAO,SAAS,sBACrB,KAAK,OAAO,SAAS,SAAS,gBAC9B,KAAK,OAAO,SAAS,SAAS,SAC9B,mBAAmB,KAAK,OAAO,MAAM,MAAM;AAK7C,IAAM,qBAAqB,YAAgE;CACzF,MAAM,QAAmC,CAAC;CAE1C,IAAI,MAA4B;CAChC,OAAO,OAAO,IAAI,SAAS,kBAAkB;EAC3C,MAAM,KAAK,GAAG;EACd,MAAM,IAAI,OAAO,SAAS,qBAAqB,IAAI,OAAO,SAAS;CACrE;CAEA,MAAM;CACN,OAAO,KAAK;EACV,MAAM,IAA+B,IAAI;EACzC,IAAI,CAAC,GAAG;EACR,IAAI,EAAE,SAAS,sBAAsB,EAAE,WAAW,KAAK;GACrD,MAAM;GACN;EACF;EACA,IAAI,EAAE,SAAS,oBAAoB,EAAE,WAAW,KAAK;GACnD,MAAM,KAAK,CAAC;GACZ,MAAM;GACN;EACF;EACA;CACF;CAEA,OAAO;AACT;AAEA,IAAM,cAAc,OAAkC,SACpD,MAAM,MACH,MACC,EAAE,OAAO,SAAS,sBAClB,EAAE,OAAO,SAAS,SAAS,gBAC3B,EAAE,OAAO,SAAS,SAAS,IAC/B;;AAGF,IAAM,kCAAkC,eAAA,WAAW;CACjD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,4NACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,eACE,sYACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,eAAe,MAA+B;GAC5C,IAAI,CAAC,UAAU,IAAI,GAAG;GACtB,MAAM,QAAQ,kBAAkB,IAAI;GAMpC,IACE,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,SAAS,KAC3B,WAAW,OAAO,WAAW,GAE7B;GAEF,MAAM,aAAa,KAAK,OAAO,SAAS,qBAAqB,KAAK,OAAO,WAAW;GACpF,QAAQ,OAAO;IAAE,MAAM;IAAY,WAAW;GAAgB,CAAC;EACjE,EACF;CACF;AACF,CAAC"}
@@ -24,6 +24,7 @@
24
24
  * Opt-out (e.g. a bare `.any()` used purely as a type argument like `items(validator.any())`):
25
25
  * // eslint-disable-next-line adk/require-validator-any-required -- <reason>
26
26
  */
27
+ /** ESLint rule: flags a validator `any()` schema lacking an explicit required/optional/forbidden disposition. */
27
28
  declare const requireValidatorAnyRequiredRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"declareIntent", [
28
29
  ], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
29
30
  name: string;
@@ -67,6 +67,7 @@ var collectChainCalls = (anyCall) => {
67
67
  return calls;
68
68
  };
69
69
  var chainCalls = (calls, name) => calls.some((c) => c.callee.type === "MemberExpression" && c.callee.property.type === "Identifier" && c.callee.property.name === name);
70
+ /** ESLint rule: flags a validator `any()` schema lacking an explicit required/optional/forbidden disposition. */
70
71
  var requireValidatorAnyRequiredRule = createRule({
71
72
  name: "require-validator-any-required",
72
73
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"require_validator_any_required.mjs","names":[],"sources":["../../../src/eslint/rules/require_validator_any_required.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/require_validator_any_required\n *\n * Flags every `validator.any()` schema chain that does not declare intent with `.required()`\n * or `.optional()`.\n *\n * Why: in `@nhtio/validation`, `.any()` ADMITS `null`/`undefined` unless you make it `.required()`.\n * That default is silent and easy to miss — a schema you believe rejects missing values quietly\n * accepts them, and any `.custom()` refinement is skipped for an absent value (a `.custom()` guard\n * is the usual way this surfaces, e.g. `implementsX(undefined) === true`). The fix is to make the\n * disposition an EXPLICIT declaration with no ambiguity — every `.any()` must say which it is:\n * - `.required()` → reject null/undefined\n * - `.optional()` → deliberately allow null/undefined\n * - `.default(x)` → allow absence, substituting a fallback value\n * - `.forbidden()` → the value must be absent\n * This applies whether the `.any()` is top-level or nested inside `items(...)` / `alternatives(...)`:\n * the enclosing schema being `.required()` does NOT govern an inner `.any()`'s null/undefined handling.\n *\n * The sharpest illustration is `.valid(null)`: an author writing `validator.any().valid(null)`\n * means \"must be exactly null\" — but because `.any()` admits `undefined`, that schema actually\n * accepts BOTH `null` and `undefined` (and `undefined !== null`). The fix is\n * `validator.any().required().valid(null)`.\n *\n * Opt-out (e.g. a bare `.any()` used purely as a type argument like `items(validator.any())`):\n * // eslint-disable-next-line adk/require-validator-any-required -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\n// The base identifier a member/call chain roots at, e.g. `validator` in `validator.any()` or\n// `validator.alternatives(...).any()`. Returns undefined if the chain doesn't root at a plain name.\nconst baseIdentifierName = (node: TSESTree.Node | undefined): string | undefined => {\n let cur: TSESTree.Node | undefined = node\n while (cur) {\n if (cur.type === 'Identifier') return cur.name\n if (cur.type === 'MemberExpression') {\n cur = cur.object\n continue\n }\n if (cur.type === 'CallExpression') {\n cur = cur.callee\n continue\n }\n return undefined\n }\n return undefined\n}\n\n// `validator.any()` (or a `validator.…().any()` chain) — NOT `expect.any()`, `_.any()`, etc.\nconst isAnyCall = (node: TSESTree.CallExpression): boolean =>\n node.callee.type === 'MemberExpression' &&\n node.callee.property.type === 'Identifier' &&\n node.callee.property.name === 'any' &&\n baseIdentifierName(node.callee.object) === 'validator'\n\n// Collect every CallExpression in the method chain `anyCall` belongs to — inward through the\n// callee object (`a.b().c()` -> `a.b()`) and outward through `.parent` links\n// (`x.any()` -> `x.any().required` -> `x.any().required()`).\nconst collectChainCalls = (anyCall: TSESTree.CallExpression): TSESTree.CallExpression[] => {\n const calls: TSESTree.CallExpression[] = []\n\n let cur: TSESTree.Node | null = anyCall\n while (cur && cur.type === 'CallExpression') {\n calls.push(cur)\n cur = cur.callee.type === 'MemberExpression' ? cur.callee.object : null\n }\n\n cur = anyCall\n while (cur) {\n const p: TSESTree.Node | undefined = cur.parent\n if (!p) break\n if (p.type === 'MemberExpression' && p.object === cur) {\n cur = p\n continue\n }\n if (p.type === 'CallExpression' && p.callee === cur) {\n calls.push(p)\n cur = p\n continue\n }\n break\n }\n\n return calls\n}\n\nconst chainCalls = (calls: TSESTree.CallExpression[], name: string): boolean =>\n calls.some(\n (c) =>\n c.callee.type === 'MemberExpression' &&\n c.callee.property.type === 'Identifier' &&\n c.callee.property.name === name\n )\n\nconst requireValidatorAnyRequiredRule = createRule({\n name: 'require-validator-any-required',\n meta: {\n type: 'problem',\n docs: {\n description:\n '`validator.any()` admits null/undefined unless `.required()`; make the disposition explicit by ending every `.any()` in `.required()`, `.optional()`, or `.default(…)`. Opt out with a tactical disable comment + reason.',\n },\n schema: [],\n messages: {\n declareIntent:\n '`validator.any()` admits null/undefined unless made `.required()`. Make the disposition explicit: end this `.any()` in `.required()` (reject null/undefined), `.optional()` (deliberately allow it), or `.default(…)` (allow it with a fallback) — applies even when nested in items()/alternatives(). Or add an eslint-disable-next-line adk/require-validator-any-required comment with a reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression) {\n if (!isAnyCall(node)) return\n const calls = collectChainCalls(node)\n // An unambiguous disposition declaration clears the rule:\n // .required() — reject null/undefined\n // .optional() — deliberately allow null/undefined\n // .default(x) — allow absence, substituting a fallback\n // .forbidden() — the value must be absent\n if (\n chainCalls(calls, 'required') ||\n chainCalls(calls, 'optional') ||\n chainCalls(calls, 'default') ||\n chainCalls(calls, 'forbidden')\n ) {\n return\n }\n const reportNode = node.callee.type === 'MemberExpression' ? node.callee.property : node\n context.report({ node: reportNode, messageId: 'declareIntent' })\n },\n }\n },\n})\n\nexport default requireValidatorAnyRequiredRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAM,sBAAsB,SAAwD;CAClF,IAAI,MAAiC;CACrC,OAAO,KAAK;EACV,IAAI,IAAI,SAAS,cAAc,OAAO,IAAI;EAC1C,IAAI,IAAI,SAAS,oBAAoB;GACnC,MAAM,IAAI;GACV;EACF;EACA,IAAI,IAAI,SAAS,kBAAkB;GACjC,MAAM,IAAI;GACV;EACF;EACA;CACF;AAEF;AAGA,IAAM,aAAa,SACjB,KAAK,OAAO,SAAS,sBACrB,KAAK,OAAO,SAAS,SAAS,gBAC9B,KAAK,OAAO,SAAS,SAAS,SAC9B,mBAAmB,KAAK,OAAO,MAAM,MAAM;AAK7C,IAAM,qBAAqB,YAAgE;CACzF,MAAM,QAAmC,CAAC;CAE1C,IAAI,MAA4B;CAChC,OAAO,OAAO,IAAI,SAAS,kBAAkB;EAC3C,MAAM,KAAK,GAAG;EACd,MAAM,IAAI,OAAO,SAAS,qBAAqB,IAAI,OAAO,SAAS;CACrE;CAEA,MAAM;CACN,OAAO,KAAK;EACV,MAAM,IAA+B,IAAI;EACzC,IAAI,CAAC,GAAG;EACR,IAAI,EAAE,SAAS,sBAAsB,EAAE,WAAW,KAAK;GACrD,MAAM;GACN;EACF;EACA,IAAI,EAAE,SAAS,oBAAoB,EAAE,WAAW,KAAK;GACnD,MAAM,KAAK,CAAC;GACZ,MAAM;GACN;EACF;EACA;CACF;CAEA,OAAO;AACT;AAEA,IAAM,cAAc,OAAkC,SACpD,MAAM,MACH,MACC,EAAE,OAAO,SAAS,sBAClB,EAAE,OAAO,SAAS,SAAS,gBAC3B,EAAE,OAAO,SAAS,SAAS,IAC/B;AAEF,IAAM,kCAAkC,WAAW;CACjD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,4NACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,eACE,sYACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,eAAe,MAA+B;GAC5C,IAAI,CAAC,UAAU,IAAI,GAAG;GACtB,MAAM,QAAQ,kBAAkB,IAAI;GAMpC,IACE,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,SAAS,KAC3B,WAAW,OAAO,WAAW,GAE7B;GAEF,MAAM,aAAa,KAAK,OAAO,SAAS,qBAAqB,KAAK,OAAO,WAAW;GACpF,QAAQ,OAAO;IAAE,MAAM;IAAY,WAAW;GAAgB,CAAC;EACjE,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"require_validator_any_required.mjs","names":[],"sources":["../../../src/eslint/rules/require_validator_any_required.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/require_validator_any_required\n *\n * Flags every `validator.any()` schema chain that does not declare intent with `.required()`\n * or `.optional()`.\n *\n * Why: in `@nhtio/validation`, `.any()` ADMITS `null`/`undefined` unless you make it `.required()`.\n * That default is silent and easy to miss — a schema you believe rejects missing values quietly\n * accepts them, and any `.custom()` refinement is skipped for an absent value (a `.custom()` guard\n * is the usual way this surfaces, e.g. `implementsX(undefined) === true`). The fix is to make the\n * disposition an EXPLICIT declaration with no ambiguity — every `.any()` must say which it is:\n * - `.required()` → reject null/undefined\n * - `.optional()` → deliberately allow null/undefined\n * - `.default(x)` → allow absence, substituting a fallback value\n * - `.forbidden()` → the value must be absent\n * This applies whether the `.any()` is top-level or nested inside `items(...)` / `alternatives(...)`:\n * the enclosing schema being `.required()` does NOT govern an inner `.any()`'s null/undefined handling.\n *\n * The sharpest illustration is `.valid(null)`: an author writing `validator.any().valid(null)`\n * means \"must be exactly null\" — but because `.any()` admits `undefined`, that schema actually\n * accepts BOTH `null` and `undefined` (and `undefined !== null`). The fix is\n * `validator.any().required().valid(null)`.\n *\n * Opt-out (e.g. a bare `.any()` used purely as a type argument like `items(validator.any())`):\n * // eslint-disable-next-line adk/require-validator-any-required -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\n// The base identifier a member/call chain roots at, e.g. `validator` in `validator.any()` or\n// `validator.alternatives(...).any()`. Returns undefined if the chain doesn't root at a plain name.\nconst baseIdentifierName = (node: TSESTree.Node | undefined): string | undefined => {\n let cur: TSESTree.Node | undefined = node\n while (cur) {\n if (cur.type === 'Identifier') return cur.name\n if (cur.type === 'MemberExpression') {\n cur = cur.object\n continue\n }\n if (cur.type === 'CallExpression') {\n cur = cur.callee\n continue\n }\n return undefined\n }\n return undefined\n}\n\n// `validator.any()` (or a `validator.…().any()` chain) — NOT `expect.any()`, `_.any()`, etc.\nconst isAnyCall = (node: TSESTree.CallExpression): boolean =>\n node.callee.type === 'MemberExpression' &&\n node.callee.property.type === 'Identifier' &&\n node.callee.property.name === 'any' &&\n baseIdentifierName(node.callee.object) === 'validator'\n\n// Collect every CallExpression in the method chain `anyCall` belongs to — inward through the\n// callee object (`a.b().c()` -> `a.b()`) and outward through `.parent` links\n// (`x.any()` -> `x.any().required` -> `x.any().required()`).\nconst collectChainCalls = (anyCall: TSESTree.CallExpression): TSESTree.CallExpression[] => {\n const calls: TSESTree.CallExpression[] = []\n\n let cur: TSESTree.Node | null = anyCall\n while (cur && cur.type === 'CallExpression') {\n calls.push(cur)\n cur = cur.callee.type === 'MemberExpression' ? cur.callee.object : null\n }\n\n cur = anyCall\n while (cur) {\n const p: TSESTree.Node | undefined = cur.parent\n if (!p) break\n if (p.type === 'MemberExpression' && p.object === cur) {\n cur = p\n continue\n }\n if (p.type === 'CallExpression' && p.callee === cur) {\n calls.push(p)\n cur = p\n continue\n }\n break\n }\n\n return calls\n}\n\nconst chainCalls = (calls: TSESTree.CallExpression[], name: string): boolean =>\n calls.some(\n (c) =>\n c.callee.type === 'MemberExpression' &&\n c.callee.property.type === 'Identifier' &&\n c.callee.property.name === name\n )\n\n/** ESLint rule: flags a validator `any()` schema lacking an explicit required/optional/forbidden disposition. */\nconst requireValidatorAnyRequiredRule = createRule({\n name: 'require-validator-any-required',\n meta: {\n type: 'problem',\n docs: {\n description:\n '`validator.any()` admits null/undefined unless `.required()`; make the disposition explicit by ending every `.any()` in `.required()`, `.optional()`, or `.default(…)`. Opt out with a tactical disable comment + reason.',\n },\n schema: [],\n messages: {\n declareIntent:\n '`validator.any()` admits null/undefined unless made `.required()`. Make the disposition explicit: end this `.any()` in `.required()` (reject null/undefined), `.optional()` (deliberately allow it), or `.default(…)` (allow it with a fallback) — applies even when nested in items()/alternatives(). Or add an eslint-disable-next-line adk/require-validator-any-required comment with a reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n CallExpression(node: TSESTree.CallExpression) {\n if (!isAnyCall(node)) return\n const calls = collectChainCalls(node)\n // An unambiguous disposition declaration clears the rule:\n // .required() — reject null/undefined\n // .optional() — deliberately allow null/undefined\n // .default(x) — allow absence, substituting a fallback\n // .forbidden() — the value must be absent\n if (\n chainCalls(calls, 'required') ||\n chainCalls(calls, 'optional') ||\n chainCalls(calls, 'default') ||\n chainCalls(calls, 'forbidden')\n ) {\n return\n }\n const reportNode = node.callee.type === 'MemberExpression' ? node.callee.property : node\n context.report({ node: reportNode, messageId: 'declareIntent' })\n },\n }\n },\n})\n\nexport default requireValidatorAnyRequiredRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAM,sBAAsB,SAAwD;CAClF,IAAI,MAAiC;CACrC,OAAO,KAAK;EACV,IAAI,IAAI,SAAS,cAAc,OAAO,IAAI;EAC1C,IAAI,IAAI,SAAS,oBAAoB;GACnC,MAAM,IAAI;GACV;EACF;EACA,IAAI,IAAI,SAAS,kBAAkB;GACjC,MAAM,IAAI;GACV;EACF;EACA;CACF;AAEF;AAGA,IAAM,aAAa,SACjB,KAAK,OAAO,SAAS,sBACrB,KAAK,OAAO,SAAS,SAAS,gBAC9B,KAAK,OAAO,SAAS,SAAS,SAC9B,mBAAmB,KAAK,OAAO,MAAM,MAAM;AAK7C,IAAM,qBAAqB,YAAgE;CACzF,MAAM,QAAmC,CAAC;CAE1C,IAAI,MAA4B;CAChC,OAAO,OAAO,IAAI,SAAS,kBAAkB;EAC3C,MAAM,KAAK,GAAG;EACd,MAAM,IAAI,OAAO,SAAS,qBAAqB,IAAI,OAAO,SAAS;CACrE;CAEA,MAAM;CACN,OAAO,KAAK;EACV,MAAM,IAA+B,IAAI;EACzC,IAAI,CAAC,GAAG;EACR,IAAI,EAAE,SAAS,sBAAsB,EAAE,WAAW,KAAK;GACrD,MAAM;GACN;EACF;EACA,IAAI,EAAE,SAAS,oBAAoB,EAAE,WAAW,KAAK;GACnD,MAAM,KAAK,CAAC;GACZ,MAAM;GACN;EACF;EACA;CACF;CAEA,OAAO;AACT;AAEA,IAAM,cAAc,OAAkC,SACpD,MAAM,MACH,MACC,EAAE,OAAO,SAAS,sBAClB,EAAE,OAAO,SAAS,SAAS,gBAC3B,EAAE,OAAO,SAAS,SAAS,IAC/B;;AAGF,IAAM,kCAAkC,WAAW;CACjD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,4NACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,eACE,sYACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,eAAe,MAA+B;GAC5C,IAAI,CAAC,UAAU,IAAI,GAAG;GACtB,MAAM,QAAQ,kBAAkB,IAAI;GAMpC,IACE,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,SAAS,KAC3B,WAAW,OAAO,WAAW,GAE7B;GAEF,MAAM,aAAa,KAAK,OAAO,SAAS,qBAAqB,KAAK,OAAO,WAAW;GACpF,QAAQ,OAAO;IAAE,MAAM;IAAY,WAAW;GAAgB,CAAC;EACjE,EACF;CACF;AACF,CAAC"}
@@ -32,6 +32,7 @@ var literalKey = (prop) => {
32
32
  if (prop.key.type === "Literal" && typeof prop.key.value === "string") return prop.key.value;
33
33
  };
34
34
  var isUndefinedValue = (node) => node.type === "Identifier" && node.name === "undefined";
35
+ /** ESLint rule: flags a Thought constructed with a payload but no replayCompatibility tag. */
35
36
  var thoughtPayloadRequiresReplayTagRule = require_common.createRule({
36
37
  name: "thought-payload-requires-replay-tag",
37
38
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"thought_payload_requires_replay_tag.cjs","names":[],"sources":["../../../src/eslint/rules/thought_payload_requires_replay_tag.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/thought_payload_requires_replay_tag\n *\n * Flags `new Thought({ … })` whose options literal sets a `payload` but omits a\n * `replayCompatibility` tag.\n *\n * Why: a `Thought` may carry a vendor-opaque `payload` that the harness cannot interpret, to be\n * replayed back to a matching model wire. The ADK can only route that payload if the thought also\n * declares which adapter wire-shape it is replayable into, via `replayCompatibility`. A `payload`\n * with no `replayCompatibility` is a footgun: the harness has no way to know which adapter can\n * consume it, so it is dropped silently. The `Thought` constructor enforces this cross-field\n * invariant at runtime (`payload` present ⇒ `replayCompatibility` required); this rule surfaces it\n * statically at the construction site so it fails lint, not just at runtime.\n *\n * Detects the common literal form: a `new Thought({ … })` options object that has a `payload`\n * property but no `replayCompatibility` property. Spreads or computed keys are not analyzable here —\n * those fall back to the runtime check.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/thought-payload-requires-replay-tag -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\n// True when the property value is statically `undefined` (the absent case) — `payload: undefined`\n// is equivalent to omitting it, so it should not trigger the rule.\nconst isUndefinedValue = (node: TSESTree.Node): boolean =>\n node.type === 'Identifier' && node.name === 'undefined'\n\nconst thoughtPayloadRequiresReplayTagRule = createRule({\n name: 'thought-payload-requires-replay-tag',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A `Thought` carrying a `payload` must declare `replayCompatibility`; otherwise the harness cannot route the opaque payload to a matching adapter and drops it. Enforced at runtime by the Thought constructor; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n requireReplayTag:\n '`new Thought({ payload })` requires a `replayCompatibility` tag — without it the harness cannot route the opaque payload to an adapter and silently drops it. Add `replayCompatibility: \"<wire-shape-id>\"`, or remove the payload. Opt out with an eslint-disable-next-line adk/thought-payload-requires-replay-tag comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier' || node.callee.name !== 'Thought') return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n let payloadProp: TSESTree.Property | undefined\n let hasReplayTag = false\n let hasSpread = false\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') {\n hasSpread = true\n continue\n }\n const key = literalKey(p)\n if (key === 'payload' && !isUndefinedValue(p.value)) payloadProp = p\n else if (key === 'replayCompatibility' && !isUndefinedValue(p.value)) hasReplayTag = true\n }\n\n // A spread could supply replayCompatibility we can't see — stay conservative, don't flag.\n if (payloadProp && !hasReplayTag && !hasSpread) {\n context.report({ node: payloadProp, messageId: 'requireReplayTag' })\n }\n },\n }\n },\n})\n\nexport default thoughtPayloadRequiresReplayTagRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAIA,IAAM,oBAAoB,SACxB,KAAK,SAAS,gBAAgB,KAAK,SAAS;AAE9C,IAAM,sCAAsC,eAAA,WAAW;CACrD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,4PACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,kBACE,0UACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,WAAW;GACzE,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,IAAI;GACJ,IAAI,eAAe;GACnB,IAAI,YAAY;GAChB,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;KAC9B,YAAY;KACZ;IACF;IACA,MAAM,MAAM,WAAW,CAAC;IACxB,IAAI,QAAQ,aAAa,CAAC,iBAAiB,EAAE,KAAK,GAAG,cAAc;SAC9D,IAAI,QAAQ,yBAAyB,CAAC,iBAAiB,EAAE,KAAK,GAAG,eAAe;GACvF;GAGA,IAAI,eAAe,CAAC,gBAAgB,CAAC,WACnC,QAAQ,OAAO;IAAE,MAAM;IAAa,WAAW;GAAmB,CAAC;EAEvE,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"thought_payload_requires_replay_tag.cjs","names":[],"sources":["../../../src/eslint/rules/thought_payload_requires_replay_tag.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/thought_payload_requires_replay_tag\n *\n * Flags `new Thought({ … })` whose options literal sets a `payload` but omits a\n * `replayCompatibility` tag.\n *\n * Why: a `Thought` may carry a vendor-opaque `payload` that the harness cannot interpret, to be\n * replayed back to a matching model wire. The ADK can only route that payload if the thought also\n * declares which adapter wire-shape it is replayable into, via `replayCompatibility`. A `payload`\n * with no `replayCompatibility` is a footgun: the harness has no way to know which adapter can\n * consume it, so it is dropped silently. The `Thought` constructor enforces this cross-field\n * invariant at runtime (`payload` present ⇒ `replayCompatibility` required); this rule surfaces it\n * statically at the construction site so it fails lint, not just at runtime.\n *\n * Detects the common literal form: a `new Thought({ … })` options object that has a `payload`\n * property but no `replayCompatibility` property. Spreads or computed keys are not analyzable here —\n * those fall back to the runtime check.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/thought-payload-requires-replay-tag -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\n// True when the property value is statically `undefined` (the absent case) — `payload: undefined`\n// is equivalent to omitting it, so it should not trigger the rule.\nconst isUndefinedValue = (node: TSESTree.Node): boolean =>\n node.type === 'Identifier' && node.name === 'undefined'\n\n/** ESLint rule: flags a Thought constructed with a payload but no replayCompatibility tag. */\nconst thoughtPayloadRequiresReplayTagRule = createRule({\n name: 'thought-payload-requires-replay-tag',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A `Thought` carrying a `payload` must declare `replayCompatibility`; otherwise the harness cannot route the opaque payload to a matching adapter and drops it. Enforced at runtime by the Thought constructor; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n requireReplayTag:\n '`new Thought({ payload })` requires a `replayCompatibility` tag — without it the harness cannot route the opaque payload to an adapter and silently drops it. Add `replayCompatibility: \"<wire-shape-id>\"`, or remove the payload. Opt out with an eslint-disable-next-line adk/thought-payload-requires-replay-tag comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier' || node.callee.name !== 'Thought') return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n let payloadProp: TSESTree.Property | undefined\n let hasReplayTag = false\n let hasSpread = false\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') {\n hasSpread = true\n continue\n }\n const key = literalKey(p)\n if (key === 'payload' && !isUndefinedValue(p.value)) payloadProp = p\n else if (key === 'replayCompatibility' && !isUndefinedValue(p.value)) hasReplayTag = true\n }\n\n // A spread could supply replayCompatibility we can't see — stay conservative, don't flag.\n if (payloadProp && !hasReplayTag && !hasSpread) {\n context.report({ node: payloadProp, messageId: 'requireReplayTag' })\n }\n },\n }\n },\n})\n\nexport default thoughtPayloadRequiresReplayTagRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAIA,IAAM,oBAAoB,SACxB,KAAK,SAAS,gBAAgB,KAAK,SAAS;;AAG9C,IAAM,sCAAsC,eAAA,WAAW;CACrD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,4PACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,kBACE,0UACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,WAAW;GACzE,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,IAAI;GACJ,IAAI,eAAe;GACnB,IAAI,YAAY;GAChB,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;KAC9B,YAAY;KACZ;IACF;IACA,MAAM,MAAM,WAAW,CAAC;IACxB,IAAI,QAAQ,aAAa,CAAC,iBAAiB,EAAE,KAAK,GAAG,cAAc;SAC9D,IAAI,QAAQ,yBAAyB,CAAC,iBAAiB,EAAE,KAAK,GAAG,eAAe;GACvF;GAGA,IAAI,eAAe,CAAC,gBAAgB,CAAC,WACnC,QAAQ,OAAO;IAAE,MAAM;IAAa,WAAW;GAAmB,CAAC;EAEvE,EACF;CACF;AACF,CAAC"}
@@ -19,6 +19,7 @@
19
19
  * Opt-out:
20
20
  * // eslint-disable-next-line adk/thought-payload-requires-replay-tag -- <reason>
21
21
  */
22
+ /** ESLint rule: flags a Thought constructed with a payload but no replayCompatibility tag. */
22
23
  declare const thoughtPayloadRequiresReplayTagRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"requireReplayTag", [
23
24
  ], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
24
25
  name: string;
@@ -27,6 +27,7 @@ var literalKey = (prop) => {
27
27
  if (prop.key.type === "Literal" && typeof prop.key.value === "string") return prop.key.value;
28
28
  };
29
29
  var isUndefinedValue = (node) => node.type === "Identifier" && node.name === "undefined";
30
+ /** ESLint rule: flags a Thought constructed with a payload but no replayCompatibility tag. */
30
31
  var thoughtPayloadRequiresReplayTagRule = createRule({
31
32
  name: "thought-payload-requires-replay-tag",
32
33
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"thought_payload_requires_replay_tag.mjs","names":[],"sources":["../../../src/eslint/rules/thought_payload_requires_replay_tag.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/thought_payload_requires_replay_tag\n *\n * Flags `new Thought({ … })` whose options literal sets a `payload` but omits a\n * `replayCompatibility` tag.\n *\n * Why: a `Thought` may carry a vendor-opaque `payload` that the harness cannot interpret, to be\n * replayed back to a matching model wire. The ADK can only route that payload if the thought also\n * declares which adapter wire-shape it is replayable into, via `replayCompatibility`. A `payload`\n * with no `replayCompatibility` is a footgun: the harness has no way to know which adapter can\n * consume it, so it is dropped silently. The `Thought` constructor enforces this cross-field\n * invariant at runtime (`payload` present ⇒ `replayCompatibility` required); this rule surfaces it\n * statically at the construction site so it fails lint, not just at runtime.\n *\n * Detects the common literal form: a `new Thought({ … })` options object that has a `payload`\n * property but no `replayCompatibility` property. Spreads or computed keys are not analyzable here —\n * those fall back to the runtime check.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/thought-payload-requires-replay-tag -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\n// True when the property value is statically `undefined` (the absent case) — `payload: undefined`\n// is equivalent to omitting it, so it should not trigger the rule.\nconst isUndefinedValue = (node: TSESTree.Node): boolean =>\n node.type === 'Identifier' && node.name === 'undefined'\n\nconst thoughtPayloadRequiresReplayTagRule = createRule({\n name: 'thought-payload-requires-replay-tag',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A `Thought` carrying a `payload` must declare `replayCompatibility`; otherwise the harness cannot route the opaque payload to a matching adapter and drops it. Enforced at runtime by the Thought constructor; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n requireReplayTag:\n '`new Thought({ payload })` requires a `replayCompatibility` tag — without it the harness cannot route the opaque payload to an adapter and silently drops it. Add `replayCompatibility: \"<wire-shape-id>\"`, or remove the payload. Opt out with an eslint-disable-next-line adk/thought-payload-requires-replay-tag comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier' || node.callee.name !== 'Thought') return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n let payloadProp: TSESTree.Property | undefined\n let hasReplayTag = false\n let hasSpread = false\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') {\n hasSpread = true\n continue\n }\n const key = literalKey(p)\n if (key === 'payload' && !isUndefinedValue(p.value)) payloadProp = p\n else if (key === 'replayCompatibility' && !isUndefinedValue(p.value)) hasReplayTag = true\n }\n\n // A spread could supply replayCompatibility we can't see — stay conservative, don't flag.\n if (payloadProp && !hasReplayTag && !hasSpread) {\n context.report({ node: payloadProp, messageId: 'requireReplayTag' })\n }\n },\n }\n },\n})\n\nexport default thoughtPayloadRequiresReplayTagRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAIA,IAAM,oBAAoB,SACxB,KAAK,SAAS,gBAAgB,KAAK,SAAS;AAE9C,IAAM,sCAAsC,WAAW;CACrD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,4PACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,kBACE,0UACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,WAAW;GACzE,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,IAAI;GACJ,IAAI,eAAe;GACnB,IAAI,YAAY;GAChB,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;KAC9B,YAAY;KACZ;IACF;IACA,MAAM,MAAM,WAAW,CAAC;IACxB,IAAI,QAAQ,aAAa,CAAC,iBAAiB,EAAE,KAAK,GAAG,cAAc;SAC9D,IAAI,QAAQ,yBAAyB,CAAC,iBAAiB,EAAE,KAAK,GAAG,eAAe;GACvF;GAGA,IAAI,eAAe,CAAC,gBAAgB,CAAC,WACnC,QAAQ,OAAO;IAAE,MAAM;IAAa,WAAW;GAAmB,CAAC;EAEvE,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"thought_payload_requires_replay_tag.mjs","names":[],"sources":["../../../src/eslint/rules/thought_payload_requires_replay_tag.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/thought_payload_requires_replay_tag\n *\n * Flags `new Thought({ … })` whose options literal sets a `payload` but omits a\n * `replayCompatibility` tag.\n *\n * Why: a `Thought` may carry a vendor-opaque `payload` that the harness cannot interpret, to be\n * replayed back to a matching model wire. The ADK can only route that payload if the thought also\n * declares which adapter wire-shape it is replayable into, via `replayCompatibility`. A `payload`\n * with no `replayCompatibility` is a footgun: the harness has no way to know which adapter can\n * consume it, so it is dropped silently. The `Thought` constructor enforces this cross-field\n * invariant at runtime (`payload` present ⇒ `replayCompatibility` required); this rule surfaces it\n * statically at the construction site so it fails lint, not just at runtime.\n *\n * Detects the common literal form: a `new Thought({ … })` options object that has a `payload`\n * property but no `replayCompatibility` property. Spreads or computed keys are not analyzable here —\n * those fall back to the runtime check.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/thought-payload-requires-replay-tag -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\n// True when the property value is statically `undefined` (the absent case) — `payload: undefined`\n// is equivalent to omitting it, so it should not trigger the rule.\nconst isUndefinedValue = (node: TSESTree.Node): boolean =>\n node.type === 'Identifier' && node.name === 'undefined'\n\n/** ESLint rule: flags a Thought constructed with a payload but no replayCompatibility tag. */\nconst thoughtPayloadRequiresReplayTagRule = createRule({\n name: 'thought-payload-requires-replay-tag',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A `Thought` carrying a `payload` must declare `replayCompatibility`; otherwise the harness cannot route the opaque payload to a matching adapter and drops it. Enforced at runtime by the Thought constructor; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n requireReplayTag:\n '`new Thought({ payload })` requires a `replayCompatibility` tag — without it the harness cannot route the opaque payload to an adapter and silently drops it. Add `replayCompatibility: \"<wire-shape-id>\"`, or remove the payload. Opt out with an eslint-disable-next-line adk/thought-payload-requires-replay-tag comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier' || node.callee.name !== 'Thought') return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n let payloadProp: TSESTree.Property | undefined\n let hasReplayTag = false\n let hasSpread = false\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') {\n hasSpread = true\n continue\n }\n const key = literalKey(p)\n if (key === 'payload' && !isUndefinedValue(p.value)) payloadProp = p\n else if (key === 'replayCompatibility' && !isUndefinedValue(p.value)) hasReplayTag = true\n }\n\n // A spread could supply replayCompatibility we can't see — stay conservative, don't flag.\n if (payloadProp && !hasReplayTag && !hasSpread) {\n context.report({ node: payloadProp, messageId: 'requireReplayTag' })\n }\n },\n }\n },\n})\n\nexport default thoughtPayloadRequiresReplayTagRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAIA,IAAM,oBAAoB,SACxB,KAAK,SAAS,gBAAgB,KAAK,SAAS;;AAG9C,IAAM,sCAAsC,WAAW;CACrD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,4PACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,kBACE,0UACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,gBAAgB,KAAK,OAAO,SAAS,WAAW;GACzE,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,IAAI;GACJ,IAAI,eAAe;GACnB,IAAI,YAAY;GAChB,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;KAC9B,YAAY;KACZ;IACF;IACA,MAAM,MAAM,WAAW,CAAC;IACxB,IAAI,QAAQ,aAAa,CAAC,iBAAiB,EAAE,KAAK,GAAG,cAAc;SAC9D,IAAI,QAAQ,yBAAyB,CAAC,iBAAiB,EAAE,KAAK,GAAG,eAAe;GACvF;GAGA,IAAI,eAAe,CAAC,gBAAgB,CAAC,WACnC,QAAQ,OAAO;IAAE,MAAM;IAAa,WAAW;GAAmB,CAAC;EAEvE,EACF;CACF;AACF,CAAC"}
@@ -30,6 +30,7 @@ var literalKey = (prop) => {
30
30
  if (prop.key.type === "Literal" && typeof prop.key.value === "string") return prop.key.value;
31
31
  };
32
32
  var isNullOrUndefined = (node) => node.type === "Literal" && node.value === null || node.type === "Identifier" && node.name === "undefined";
33
+ /** ESLint rule: flags setting a tokenEncoding without also setting a contextWindow. */
33
34
  var tokenEncodingRequiresContextWindowRule = require_common.createRule({
34
35
  name: "token-encoding-requires-context-window",
35
36
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"token_encoding_requires_context_window.cjs","names":[],"sources":["../../../src/eslint/rules/token_encoding_requires_context_window.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/token_encoding_requires_context_window\n *\n * Flags a Chat Completions adapter options literal that sets a non-null `tokenEncoding` but omits\n * `contextWindow`.\n *\n * Why: the OpenAI / WebLLM Chat Completions batteries only perform local token counting + overflow\n * protection when BOTH `tokenEncoding` (how to count) and `contextWindow` (the budget to count\n * against) are provided. Setting `tokenEncoding` alone is a footgun — the encoding is configured but\n * there is no ceiling to enforce, so the overflow guard silently never runs. The adapters throw on\n * this cross-field mismatch at iteration time; this rule surfaces it at the construction site.\n *\n * Detects `new OpenAIChatCompletionsAdapter({ … })` / `new WebLLMChatCompletionsAdapter({ … })`\n * (and any `*ChatCompletionsAdapter`) where `tokenEncoding` is present and not `null`/`undefined`\n * while `contextWindow` is absent.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/token-encoding-requires-context-window -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst isNullOrUndefined = (node: TSESTree.Node): boolean =>\n (node.type === 'Literal' && node.value === null) ||\n (node.type === 'Identifier' && node.name === 'undefined')\n\nconst tokenEncodingRequiresContextWindowRule = createRule({\n name: 'token-encoding-requires-context-window',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A Chat Completions adapter configured with a non-null `tokenEncoding` must also set `contextWindow`; otherwise token counting is configured but the overflow guard has no budget and never runs. The adapters enforce this at runtime; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n requireContextWindow:\n '`tokenEncoding` is set but `contextWindow` is missing — the adapter counts tokens with no budget to enforce, so the context-overflow guard never runs. Add `contextWindow`, or drop `tokenEncoding`. Opt out with an eslint-disable-next-line adk/token-encoding-requires-context-window comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier') return\n if (!/ChatCompletionsAdapter$/.test(node.callee.name)) return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n let tokenEncodingProp: TSESTree.Property | undefined\n let hasContextWindow = false\n let hasSpread = false\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') {\n hasSpread = true\n continue\n }\n const key = literalKey(p)\n if (key === 'tokenEncoding' && !isNullOrUndefined(p.value)) tokenEncodingProp = p\n else if (key === 'contextWindow' && !isNullOrUndefined(p.value)) hasContextWindow = true\n }\n\n // A spread could supply contextWindow we can't see — stay conservative, don't flag.\n if (tokenEncodingProp && !hasContextWindow && !hasSpread) {\n context.report({ node: tokenEncodingProp, messageId: 'requireContextWindow' })\n }\n },\n }\n },\n})\n\nexport default tokenEncodingRequiresContextWindowRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,qBAAqB,SACxB,KAAK,SAAS,aAAa,KAAK,UAAU,QAC1C,KAAK,SAAS,gBAAgB,KAAK,SAAS;AAE/C,IAAM,yCAAyC,eAAA,WAAW;CACxD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,oRACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,sBACE,6SACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,cAAc;GACvC,IAAI,CAAC,0BAA0B,KAAK,KAAK,OAAO,IAAI,GAAG;GACvD,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,IAAI;GACJ,IAAI,mBAAmB;GACvB,IAAI,YAAY;GAChB,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;KAC9B,YAAY;KACZ;IACF;IACA,MAAM,MAAM,WAAW,CAAC;IACxB,IAAI,QAAQ,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,GAAG,oBAAoB;SAC3E,IAAI,QAAQ,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,GAAG,mBAAmB;GACtF;GAGA,IAAI,qBAAqB,CAAC,oBAAoB,CAAC,WAC7C,QAAQ,OAAO;IAAE,MAAM;IAAmB,WAAW;GAAuB,CAAC;EAEjF,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"token_encoding_requires_context_window.cjs","names":[],"sources":["../../../src/eslint/rules/token_encoding_requires_context_window.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/token_encoding_requires_context_window\n *\n * Flags a Chat Completions adapter options literal that sets a non-null `tokenEncoding` but omits\n * `contextWindow`.\n *\n * Why: the OpenAI / WebLLM Chat Completions batteries only perform local token counting + overflow\n * protection when BOTH `tokenEncoding` (how to count) and `contextWindow` (the budget to count\n * against) are provided. Setting `tokenEncoding` alone is a footgun — the encoding is configured but\n * there is no ceiling to enforce, so the overflow guard silently never runs. The adapters throw on\n * this cross-field mismatch at iteration time; this rule surfaces it at the construction site.\n *\n * Detects `new OpenAIChatCompletionsAdapter({ … })` / `new WebLLMChatCompletionsAdapter({ … })`\n * (and any `*ChatCompletionsAdapter`) where `tokenEncoding` is present and not `null`/`undefined`\n * while `contextWindow` is absent.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/token-encoding-requires-context-window -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst isNullOrUndefined = (node: TSESTree.Node): boolean =>\n (node.type === 'Literal' && node.value === null) ||\n (node.type === 'Identifier' && node.name === 'undefined')\n\n/** ESLint rule: flags setting a tokenEncoding without also setting a contextWindow. */\nconst tokenEncodingRequiresContextWindowRule = createRule({\n name: 'token-encoding-requires-context-window',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A Chat Completions adapter configured with a non-null `tokenEncoding` must also set `contextWindow`; otherwise token counting is configured but the overflow guard has no budget and never runs. The adapters enforce this at runtime; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n requireContextWindow:\n '`tokenEncoding` is set but `contextWindow` is missing — the adapter counts tokens with no budget to enforce, so the context-overflow guard never runs. Add `contextWindow`, or drop `tokenEncoding`. Opt out with an eslint-disable-next-line adk/token-encoding-requires-context-window comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier') return\n if (!/ChatCompletionsAdapter$/.test(node.callee.name)) return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n let tokenEncodingProp: TSESTree.Property | undefined\n let hasContextWindow = false\n let hasSpread = false\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') {\n hasSpread = true\n continue\n }\n const key = literalKey(p)\n if (key === 'tokenEncoding' && !isNullOrUndefined(p.value)) tokenEncodingProp = p\n else if (key === 'contextWindow' && !isNullOrUndefined(p.value)) hasContextWindow = true\n }\n\n // A spread could supply contextWindow we can't see — stay conservative, don't flag.\n if (tokenEncodingProp && !hasContextWindow && !hasSpread) {\n context.report({ node: tokenEncodingProp, messageId: 'requireContextWindow' })\n }\n },\n }\n },\n})\n\nexport default tokenEncodingRequiresContextWindowRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,qBAAqB,SACxB,KAAK,SAAS,aAAa,KAAK,UAAU,QAC1C,KAAK,SAAS,gBAAgB,KAAK,SAAS;;AAG/C,IAAM,yCAAyC,eAAA,WAAW;CACxD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,oRACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,sBACE,6SACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,cAAc;GACvC,IAAI,CAAC,0BAA0B,KAAK,KAAK,OAAO,IAAI,GAAG;GACvD,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,IAAI;GACJ,IAAI,mBAAmB;GACvB,IAAI,YAAY;GAChB,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;KAC9B,YAAY;KACZ;IACF;IACA,MAAM,MAAM,WAAW,CAAC;IACxB,IAAI,QAAQ,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,GAAG,oBAAoB;SAC3E,IAAI,QAAQ,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,GAAG,mBAAmB;GACtF;GAGA,IAAI,qBAAqB,CAAC,oBAAoB,CAAC,WAC7C,QAAQ,OAAO;IAAE,MAAM;IAAmB,WAAW;GAAuB,CAAC;EAEjF,EACF;CACF;AACF,CAAC"}
@@ -17,6 +17,7 @@
17
17
  * Opt-out:
18
18
  * // eslint-disable-next-line adk/token-encoding-requires-context-window -- <reason>
19
19
  */
20
+ /** ESLint rule: flags setting a tokenEncoding without also setting a contextWindow. */
20
21
  declare const tokenEncodingRequiresContextWindowRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"requireContextWindow", [
21
22
  ], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
22
23
  name: string;
@@ -25,6 +25,7 @@ var literalKey = (prop) => {
25
25
  if (prop.key.type === "Literal" && typeof prop.key.value === "string") return prop.key.value;
26
26
  };
27
27
  var isNullOrUndefined = (node) => node.type === "Literal" && node.value === null || node.type === "Identifier" && node.name === "undefined";
28
+ /** ESLint rule: flags setting a tokenEncoding without also setting a contextWindow. */
28
29
  var tokenEncodingRequiresContextWindowRule = createRule({
29
30
  name: "token-encoding-requires-context-window",
30
31
  meta: {
@@ -1 +1 @@
1
- {"version":3,"file":"token_encoding_requires_context_window.mjs","names":[],"sources":["../../../src/eslint/rules/token_encoding_requires_context_window.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/token_encoding_requires_context_window\n *\n * Flags a Chat Completions adapter options literal that sets a non-null `tokenEncoding` but omits\n * `contextWindow`.\n *\n * Why: the OpenAI / WebLLM Chat Completions batteries only perform local token counting + overflow\n * protection when BOTH `tokenEncoding` (how to count) and `contextWindow` (the budget to count\n * against) are provided. Setting `tokenEncoding` alone is a footgun — the encoding is configured but\n * there is no ceiling to enforce, so the overflow guard silently never runs. The adapters throw on\n * this cross-field mismatch at iteration time; this rule surfaces it at the construction site.\n *\n * Detects `new OpenAIChatCompletionsAdapter({ … })` / `new WebLLMChatCompletionsAdapter({ … })`\n * (and any `*ChatCompletionsAdapter`) where `tokenEncoding` is present and not `null`/`undefined`\n * while `contextWindow` is absent.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/token-encoding-requires-context-window -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst isNullOrUndefined = (node: TSESTree.Node): boolean =>\n (node.type === 'Literal' && node.value === null) ||\n (node.type === 'Identifier' && node.name === 'undefined')\n\nconst tokenEncodingRequiresContextWindowRule = createRule({\n name: 'token-encoding-requires-context-window',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A Chat Completions adapter configured with a non-null `tokenEncoding` must also set `contextWindow`; otherwise token counting is configured but the overflow guard has no budget and never runs. The adapters enforce this at runtime; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n requireContextWindow:\n '`tokenEncoding` is set but `contextWindow` is missing — the adapter counts tokens with no budget to enforce, so the context-overflow guard never runs. Add `contextWindow`, or drop `tokenEncoding`. Opt out with an eslint-disable-next-line adk/token-encoding-requires-context-window comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier') return\n if (!/ChatCompletionsAdapter$/.test(node.callee.name)) return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n let tokenEncodingProp: TSESTree.Property | undefined\n let hasContextWindow = false\n let hasSpread = false\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') {\n hasSpread = true\n continue\n }\n const key = literalKey(p)\n if (key === 'tokenEncoding' && !isNullOrUndefined(p.value)) tokenEncodingProp = p\n else if (key === 'contextWindow' && !isNullOrUndefined(p.value)) hasContextWindow = true\n }\n\n // A spread could supply contextWindow we can't see — stay conservative, don't flag.\n if (tokenEncodingProp && !hasContextWindow && !hasSpread) {\n context.report({ node: tokenEncodingProp, messageId: 'requireContextWindow' })\n }\n },\n }\n },\n})\n\nexport default tokenEncodingRequiresContextWindowRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,qBAAqB,SACxB,KAAK,SAAS,aAAa,KAAK,UAAU,QAC1C,KAAK,SAAS,gBAAgB,KAAK,SAAS;AAE/C,IAAM,yCAAyC,WAAW;CACxD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,oRACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,sBACE,6SACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,cAAc;GACvC,IAAI,CAAC,0BAA0B,KAAK,KAAK,OAAO,IAAI,GAAG;GACvD,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,IAAI;GACJ,IAAI,mBAAmB;GACvB,IAAI,YAAY;GAChB,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;KAC9B,YAAY;KACZ;IACF;IACA,MAAM,MAAM,WAAW,CAAC;IACxB,IAAI,QAAQ,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,GAAG,oBAAoB;SAC3E,IAAI,QAAQ,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,GAAG,mBAAmB;GACtF;GAGA,IAAI,qBAAqB,CAAC,oBAAoB,CAAC,WAC7C,QAAQ,OAAO;IAAE,MAAM;IAAmB,WAAW;GAAuB,CAAC;EAEjF,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"token_encoding_requires_context_window.mjs","names":[],"sources":["../../../src/eslint/rules/token_encoding_requires_context_window.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/eslint/rules/token_encoding_requires_context_window\n *\n * Flags a Chat Completions adapter options literal that sets a non-null `tokenEncoding` but omits\n * `contextWindow`.\n *\n * Why: the OpenAI / WebLLM Chat Completions batteries only perform local token counting + overflow\n * protection when BOTH `tokenEncoding` (how to count) and `contextWindow` (the budget to count\n * against) are provided. Setting `tokenEncoding` alone is a footgun — the encoding is configured but\n * there is no ceiling to enforce, so the overflow guard silently never runs. The adapters throw on\n * this cross-field mismatch at iteration time; this rule surfaces it at the construction site.\n *\n * Detects `new OpenAIChatCompletionsAdapter({ … })` / `new WebLLMChatCompletionsAdapter({ … })`\n * (and any `*ChatCompletionsAdapter`) where `tokenEncoding` is present and not `null`/`undefined`\n * while `contextWindow` is absent.\n *\n * Opt-out:\n * // eslint-disable-next-line adk/token-encoding-requires-context-window -- <reason>\n */\n\nimport { createRule } from './common'\n\nimport type { TSESTree } from '@typescript-eslint/utils'\n\nconst literalKey = (prop: TSESTree.Property): string | undefined => {\n if (prop.computed) return undefined\n if (prop.key.type === 'Identifier') return prop.key.name\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') return prop.key.value\n return undefined\n}\n\nconst isNullOrUndefined = (node: TSESTree.Node): boolean =>\n (node.type === 'Literal' && node.value === null) ||\n (node.type === 'Identifier' && node.name === 'undefined')\n\n/** ESLint rule: flags setting a tokenEncoding without also setting a contextWindow. */\nconst tokenEncodingRequiresContextWindowRule = createRule({\n name: 'token-encoding-requires-context-window',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'A Chat Completions adapter configured with a non-null `tokenEncoding` must also set `contextWindow`; otherwise token counting is configured but the overflow guard has no budget and never runs. The adapters enforce this at runtime; this surfaces it at the construction site.',\n },\n schema: [],\n messages: {\n requireContextWindow:\n '`tokenEncoding` is set but `contextWindow` is missing — the adapter counts tokens with no budget to enforce, so the context-overflow guard never runs. Add `contextWindow`, or drop `tokenEncoding`. Opt out with an eslint-disable-next-line adk/token-encoding-requires-context-window comment + reason.',\n },\n },\n defaultOptions: [],\n create(context) {\n return {\n NewExpression(node: TSESTree.NewExpression) {\n if (node.callee.type !== 'Identifier') return\n if (!/ChatCompletionsAdapter$/.test(node.callee.name)) return\n const arg = node.arguments[0]\n if (!arg || arg.type !== 'ObjectExpression') return\n\n let tokenEncodingProp: TSESTree.Property | undefined\n let hasContextWindow = false\n let hasSpread = false\n for (const p of arg.properties) {\n if (p.type === 'SpreadElement') {\n hasSpread = true\n continue\n }\n const key = literalKey(p)\n if (key === 'tokenEncoding' && !isNullOrUndefined(p.value)) tokenEncodingProp = p\n else if (key === 'contextWindow' && !isNullOrUndefined(p.value)) hasContextWindow = true\n }\n\n // A spread could supply contextWindow we can't see — stay conservative, don't flag.\n if (tokenEncodingProp && !hasContextWindow && !hasSpread) {\n context.report({ node: tokenEncodingProp, messageId: 'requireContextWindow' })\n }\n },\n }\n },\n})\n\nexport default tokenEncodingRequiresContextWindowRule\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,IAAM,cAAc,SAAgD;CAClE,IAAI,KAAK,UAAU,OAAO,KAAA;CAC1B,IAAI,KAAK,IAAI,SAAS,cAAc,OAAO,KAAK,IAAI;CACpD,IAAI,KAAK,IAAI,SAAS,aAAa,OAAO,KAAK,IAAI,UAAU,UAAU,OAAO,KAAK,IAAI;AAEzF;AAEA,IAAM,qBAAqB,SACxB,KAAK,SAAS,aAAa,KAAK,UAAU,QAC1C,KAAK,SAAS,gBAAgB,KAAK,SAAS;;AAG/C,IAAM,yCAAyC,WAAW;CACxD,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,oRACJ;EACA,QAAQ,CAAC;EACT,UAAU,EACR,sBACE,6SACJ;CACF;CACA,gBAAgB,CAAC;CACjB,OAAO,SAAS;EACd,OAAO,EACL,cAAc,MAA8B;GAC1C,IAAI,KAAK,OAAO,SAAS,cAAc;GACvC,IAAI,CAAC,0BAA0B,KAAK,KAAK,OAAO,IAAI,GAAG;GACvD,MAAM,MAAM,KAAK,UAAU;GAC3B,IAAI,CAAC,OAAO,IAAI,SAAS,oBAAoB;GAE7C,IAAI;GACJ,IAAI,mBAAmB;GACvB,IAAI,YAAY;GAChB,KAAK,MAAM,KAAK,IAAI,YAAY;IAC9B,IAAI,EAAE,SAAS,iBAAiB;KAC9B,YAAY;KACZ;IACF;IACA,MAAM,MAAM,WAAW,CAAC;IACxB,IAAI,QAAQ,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,GAAG,oBAAoB;SAC3E,IAAI,QAAQ,mBAAmB,CAAC,kBAAkB,EAAE,KAAK,GAAG,mBAAmB;GACtF;GAGA,IAAI,qBAAqB,CAAC,oBAAoB,CAAC,WAC7C,QAAQ,OAAO;IAAE,MAAM;IAAmB,WAAW;GAAuB,CAAC;EAEjF,EACF;CACF;AACF,CAAC"}
package/eslint.cjs CHANGED
@@ -49,7 +49,7 @@ var rules = {
49
49
  var plugin = {
50
50
  meta: {
51
51
  name: "@nhtio/adk/eslint",
52
- version: "1.20260607.2"
52
+ version: "1.20260609.0"
53
53
  },
54
54
  rules
55
55
  };
package/eslint.mjs CHANGED
@@ -44,7 +44,7 @@ var rules = {
44
44
  var plugin = {
45
45
  meta: {
46
46
  name: "@nhtio/adk/eslint",
47
- version: "1.20260607.2"
47
+ version: "1.20260609.0"
48
48
  },
49
49
  rules
50
50
  };
@@ -62,6 +62,7 @@ var BaseException = class BaseException extends Error {
62
62
  if (help !== void 0) this.help = help;
63
63
  Error.captureStackTrace(this, ErrorConstructor);
64
64
  }
65
+ /** Tag used by `Object.prototype.toString` — reports the concrete exception class name. */
65
66
  get [Symbol.toStringTag]() {
66
67
  return this.constructor.name;
67
68
  }
@@ -203,7 +204,7 @@ var asyncValidateOrThrow = async (schema, value, convert = false) => {
203
204
  * @typeParam T - Tuple of printf format argument types. Pass a non-empty tuple to require
204
205
  * callers to supply interpolation values at the throw site.
205
206
  *
206
- * @param name - The `name` property set on thrown instances (used by {@link isNamedException}).
207
+ * @param name - The `name` property set on thrown instances (used by `isNamedException`).
207
208
  * @param message - Printf-style template string for the error message.
208
209
  * @param code - Machine-readable error code stored on the static and instance `code` property.
209
210
  * @param status - HTTP status code associated with this exception class.
@@ -241,4 +242,4 @@ var createException = (name, message, code, status, fatal) => {
241
242
  //#endregion
242
243
  export { validateOrThrow as a, passesSchema as i, ValidationException as n, BaseException as o, asyncValidateOrThrow as r, createException as t };
243
244
 
244
- //# sourceMappingURL=exceptions-BeWH2FwP.mjs.map
245
+ //# sourceMappingURL=exceptions-BDhN0Xzr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exceptions-BDhN0Xzr.mjs","names":[],"sources":["../src/lib/classes/base_exception.ts","../src/lib/utils/validation.ts","../src/lib/utils/exceptions.ts"],"sourcesContent":["/**\n * Base class for all structured exceptions in the ADK.\n *\n * @remarks\n * Subclasses should declare static `code`, `status`, `fatal`, and optionally `help` to avoid\n * repeating those values on every instance. Instance-level options always take precedence over\n * static defaults, so a single exception class can still be thrown with per-site overrides when\n * needed.\n *\n * The runtime cross-realm guard is inlined here rather than imported from `../utils/guards`\n * to break a circular-import chain: `guards` depends on `validation`, which extends\n * `BaseException`. Importing the shared `isInstanceOf` helper into this file would create a\n * load-order cycle that leaves `BaseException` undefined when `ValidationException extends\n * BaseException` evaluates.\n */\nexport class BaseException extends Error {\n /**\n * Returns `true` if `value` is a {@link BaseException} instance.\n *\n * @remarks\n * Performs cross-realm-safe detection: tries `instanceof`, then `Symbol.hasInstance`, then\n * constructor-name comparison. The ADK does not export the `BaseException` class itself\n * as a constructable value — use this guard plus the {@link BaseException} type for runtime\n * detection and TypeScript narrowing.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a {@link BaseException} instance.\n */\n public static isBaseException(value: unknown): value is BaseException {\n // eslint-disable-next-line adk/use-is-instance-of -- module cycle (guards ↔ validation ↔ BaseException); the cross-realm fallback is inlined below\n if (value instanceof BaseException) return true\n if (\n typeof BaseException[Symbol.hasInstance] === 'function' &&\n BaseException[Symbol.hasInstance](value)\n )\n return true\n // eslint-disable-next-line adk/prefer-is-object -- module cycle (guards ↔ validation ↔ BaseException); isObject would create a load-order cycle\n if (typeof value === 'object' && value !== null) {\n const ctorName = (value as { constructor?: { name?: string } }).constructor?.name\n if (ctorName === 'BaseException') return true\n }\n return false\n }\n /**\n * Default help text inherited by all instances unless overridden at the throw site.\n */\n declare static help?: string\n /**\n * Default machine-readable error code inherited by all instances.\n */\n declare static code?: string\n /**\n * Default HTTP status code inherited by all instances.\n */\n declare static status?: number\n /**\n * Whether exceptions of this class are fatal by default.\n */\n declare static fatal?: boolean\n /**\n * Default message used when no message is supplied to the constructor.\n */\n declare static message?: string\n\n /**\n * Name of the class that raised the exception.\n */\n name: string\n\n /**\n * Human-readable guidance for resolving or reporting this error.\n */\n declare help?: string\n\n /**\n * Machine-readable error code for narrowing exception-handling logic.\n */\n declare code?: string\n\n /**\n * HTTP status code associated with this error.\n */\n declare status?: number\n\n /**\n * When `true`, the ADK treats this error as unrecoverable and should halt the agent loop.\n */\n declare fatal?: boolean\n\n /**\n * @param message - Human-readable error message. Falls back to the static `message` on the\n * subclass if omitted.\n * @param options - Standard `ErrorOptions` extended with `code`, `status`, and `fatal`\n * overrides. Static defaults on the subclass are used when these are absent.\n */\n constructor(\n message?: string,\n options?: ErrorOptions & { code?: string; status?: number; fatal?: boolean }\n ) {\n super(message, options)\n\n const ErrorConstructor = this.constructor as typeof BaseException\n\n this.name = ErrorConstructor.name\n this.message = message || ErrorConstructor.message || ''\n\n const code = options?.code || ErrorConstructor.code\n if (code !== undefined) {\n this.code = code\n }\n\n const status = options?.status || ErrorConstructor.status\n if (status !== undefined) {\n this.status = status\n }\n\n const fatal = options?.fatal ?? ErrorConstructor.fatal\n if (fatal !== undefined) {\n this.fatal = fatal\n }\n\n const help = ErrorConstructor.help\n if (help !== undefined) {\n this.help = help\n }\n\n Error.captureStackTrace(this, ErrorConstructor)\n }\n\n /** Tag used by `Object.prototype.toString` — reports the concrete exception class name. */\n get [Symbol.toStringTag]() {\n return this.constructor.name\n }\n\n toString() {\n if (this.code) {\n return `${this.name} [${this.code}]: ${this.message}`\n }\n return `${this.name}: ${this.message}`\n }\n}\n","import { BaseException } from '../classes/base_exception'\nimport { validator, ValidationError } from '@nhtio/validation'\nimport type { Schema } from '@nhtio/validation'\n\n/**\n * Returns `true` if `value` satisfies `schema` without throwing.\n *\n * @remarks\n * Aborts on the first validation error. Use {@link validateOrThrow} or\n * {@link asyncValidateOrThrow} when you need the full set of field errors.\n *\n * @param schema - The schema to validate against.\n * @param value - The value to test.\n * @returns `true` when `value` passes the schema; `false` otherwise.\n */\nexport const passesSchema = (schema: Schema, value: unknown): boolean => {\n const { error } = schema.validate(value, { abortEarly: true })\n return !error\n}\n\n/**\n * Returns `true` if `value` is a `ValidationError` or satisfies its minimum duck-type shape.\n *\n * @remarks\n * The duck-typing path handles `ValidationError` objects that cross module or realm boundaries\n * where `instanceof` would return `false`.\n *\n * @param value - The value to test.\n * @returns `true` when `value` conforms to the `ValidationError` shape.\n */\nexport const isValidationError = (value: unknown): value is ValidationError => {\n const schema = validator.alternatives(\n validator.object().instance(ValidationError as any),\n validator.function().instance(ValidationError as any),\n validator\n .object({\n message: validator.string().required(),\n details: validator\n .array()\n .items(\n validator.object({\n message: validator.string().required(),\n path: validator\n .array()\n .items(validator.alternatives(validator.string(), validator.number()))\n .required(),\n type: validator.string().required(),\n context: validator.object().unknown(true).required(),\n })\n )\n .required(),\n })\n .unknown(true)\n )\n return passesSchema(schema, value)\n}\n\nconst messageFromValidationError = (reason: ValidationError | undefined, fallback: string) => {\n return reason ? reason.details.map((d) => d.message).join(' and ') : fallback\n}\n\n/**\n * Thrown when input fails schema validation.\n *\n * @remarks\n * Carries the full `details` array from the underlying `ValidationError` so callers can surface\n * field-level messages without unwrapping the `cause` manually.\n */\nexport class ValidationException extends BaseException {\n static status = 422\n static code = 'VALIDATION_EXCEPTION'\n static fatal = false\n\n /** The raw field-level error details from the underlying `ValidationError`. */\n declare readonly details?: ValidationError['details']\n\n /**\n * @param reason - The `ValidationError` thrown by the schema; its `details` are surfaced\n * directly on this exception and its messages are joined to form the human-readable message.\n */\n constructor(reason: ValidationError) {\n const message = messageFromValidationError(reason, 'Validation failed')\n super(message, {\n code: ValidationException.code,\n status: ValidationException.status,\n fatal: ValidationException.fatal,\n cause: reason,\n })\n Object.defineProperty(this, 'details', {\n value: reason.details,\n enumerable: true,\n configurable: false,\n writable: false,\n })\n }\n}\n\n/**\n * Validates `value` against `schema` synchronously and returns the coerced result typed as `T`.\n *\n * @remarks\n * Collects all field errors before throwing. Use {@link asyncValidateOrThrow} for schemas that\n * include async custom validators.\n *\n * @typeParam T - The expected type of `value` after successful validation.\n * @param schema - The schema to validate against.\n * @param value - The value to validate.\n * @param convert - When `true`, the validator coerces values to their target types (e.g. string\n * `\"1\"` → number `1`). Defaults to `false` to prevent silent type coercion.\n * @returns The validated (and optionally coerced) value typed as `T`.\n * @throws {@link ValidationException} when `value` does not satisfy `schema`.\n */\nexport const validateOrThrow = <T>(schema: Schema, value: unknown, convert: boolean = false): T => {\n const { value: returnable, error } = schema.validate(value, { abortEarly: false, convert })\n if (error) {\n throw new ValidationException(error)\n }\n return returnable as T\n}\n\n/**\n * Validates `value` against `schema` asynchronously and returns the coerced result typed as `T`.\n *\n * @remarks\n * Collects all field errors before throwing. Prefer this over {@link validateOrThrow} when the\n * schema includes async custom validators.\n *\n * @typeParam T - The expected type of the validated and coerced return value.\n * @param schema - The schema to validate against.\n * @param value - The value to validate.\n * @param convert - When `true`, the validator coerces values to their target types (e.g. string\n * `\"1\"` → number `1`). Defaults to `false` to prevent silent type coercion.\n * @returns The validated (and optionally coerced) value typed as `T`.\n * @throws {@link ValidationException} when `value` does not satisfy `schema`.\n */\nexport const asyncValidateOrThrow = async <T>(\n schema: Schema,\n value: unknown,\n convert: boolean = false\n): Promise<T> => {\n try {\n return await schema.validateAsync(value, { abortEarly: false, convert })\n } catch (error) {\n if (isValidationError(error)) {\n throw new ValidationException(error)\n }\n throw error\n }\n}\n","import { passesSchema } from './validation'\nimport { validator } from '@nhtio/validation'\nimport { printf as format } from 'fast-printf'\nimport { BaseException } from '../classes/base_exception'\n\n/**\n * Options accepted by {@link @nhtio/adk!BaseException} (and factory-created exceptions) beyond the\n * standard `ErrorOptions`.\n *\n * @remarks\n * These mirror the static defaults on {@link @nhtio/adk!BaseException} but allow per-throw overrides so a\n * single exception class can carry different metadata at different throw sites.\n */\nexport type ExceptionOptions = ErrorOptions & {\n code?: string\n status?: number\n fatal?: boolean\n}\n\n/**\n * Constructor signature of an exception class produced by {@link createException}.\n *\n * @typeParam T - Tuple of printf-style format argument types. When `T` is an empty tuple the\n * constructor takes no positional message arguments; when non-empty the first argument must be\n * an array of values matching `T`.\n */\nexport type CreatedException<T extends any[] = []> = typeof BaseException &\n (T extends []\n ? {\n new (options?: ExceptionOptions): BaseException\n }\n : { new (args: T, options?: ExceptionOptions): BaseException })\n\n/**\n * Factory that produces a named {@link @nhtio/adk!BaseException} subclass with a fixed printf-style message\n * template, error code, HTTP status, and fatality flag.\n *\n * @remarks\n * Prefer this over hand-writing subclasses for simple, static exception definitions.\n *\n * @typeParam T - Tuple of printf format argument types. Pass a non-empty tuple to require\n * callers to supply interpolation values at the throw site.\n *\n * @param name - The `name` property set on thrown instances (used by `isNamedException`).\n * @param message - Printf-style template string for the error message.\n * @param code - Machine-readable error code stored on the static and instance `code` property.\n * @param status - HTTP status code associated with this exception class.\n * @param fatal - When `true`, signals that the error is unrecoverable.\n * @returns A constructor for a {@link @nhtio/adk!BaseException} subclass with the given metadata baked in.\n *\n * @example\n * ```ts\n * export const E_NOT_FOUND = createException<[string]>(\n * 'E_NOT_FOUND', 'Resource %s not found', 'E_NOT_FOUND', 404, false\n * )\n * throw new E_NOT_FOUND(['my-id'])\n * ```\n */\nexport const createException = <T extends any[] = []>(\n name: string,\n message: string,\n code: string,\n status?: number,\n fatal?: boolean\n): CreatedException<T> => {\n const Ctor = class extends BaseException {\n static message = message\n static code = code\n static status = status\n static fatal = fatal\n constructor(args?: T | ExceptionOptions, options?: ExceptionOptions) {\n const hasMessageArgs = Array.isArray(args)\n const messageArgs = hasMessageArgs ? args : []\n const errorOptions = hasMessageArgs ? options : args\n\n super(format(message, ...messageArgs), errorOptions)\n this.name = name\n }\n }\n // Without this, the factory returns an anonymous class — constructor.name is \"\" and\n // cross-realm `isInstanceOf(err, 'E_FOO')` (which falls back to constructor-name comparison)\n // never matches. Setting the name on the class itself makes the identity carry through.\n Object.defineProperty(Ctor, 'name', { value: name, configurable: true })\n return Ctor as unknown as CreatedException<T>\n}\n\n/**\n * Returns `true` if `value` is a {@link @nhtio/adk!BaseException} or satisfies its minimum duck-type shape.\n *\n * @remarks\n * The duck-typing path handles exceptions that cross module or realm boundaries where\n * `instanceof` would return `false` for structurally identical objects.\n *\n * @param value - The value to test.\n * @returns `true` when `value` conforms to the {@link @nhtio/adk!BaseException} shape.\n */\nexport const isException = (value: unknown): value is BaseException => {\n const schema = validator.alternatives(\n validator.object().instance(BaseException as any),\n validator.function().instance(BaseException as any),\n validator\n .object({\n name: validator.string().required(),\n message: validator.string().required(),\n help: validator.string().optional(),\n code: validator.string().optional(),\n status: validator.number().optional(),\n fatal: validator.boolean().optional(),\n })\n .unknown(true)\n )\n return passesSchema(schema, value)\n}\n\n/**\n * Narrows `value` to a {@link @nhtio/adk!BaseException} whose `name` property matches `name` exactly.\n *\n * @remarks\n * Useful for catching a specific factory-created exception by its string identifier when\n * `instanceof` checks are not available (e.g. across module boundaries).\n *\n * @param value - The value to test.\n * @param name - The exact string to compare against `value.name`.\n * @returns `true` when `value` is a {@link @nhtio/adk!BaseException} with the given `name`.\n */\nexport const isNamedException = (value: unknown, name: string): value is BaseException => {\n return isException(value) && value.name === name\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAeA,IAAa,gBAAb,MAAa,sBAAsB,MAAM;;;;;;;;;;;;;CAavC,OAAc,gBAAgB,OAAwC;EAEpE,IAAI,iBAAiB,eAAe,OAAO;EAC3C,IACE,OAAO,cAAc,OAAO,iBAAiB,cAC7C,cAAc,OAAO,aAAa,KAAK,GAEvC,OAAO;EAET,IAAI,OAAO,UAAU,YAAY,UAAU;OACvB,MAA8C,aAAa,SAC5D,iBAAiB,OAAO;EAAA;EAE3C,OAAO;CACT;;;;CAyBA;;;;;;;CA4BA,YACE,SACA,SACA;EACA,MAAM,SAAS,OAAO;EAEtB,MAAM,mBAAmB,KAAK;EAE9B,KAAK,OAAO,iBAAiB;EAC7B,KAAK,UAAU,WAAW,iBAAiB,WAAW;EAEtD,MAAM,OAAO,SAAS,QAAQ,iBAAiB;EAC/C,IAAI,SAAS,KAAA,GACX,KAAK,OAAO;EAGd,MAAM,SAAS,SAAS,UAAU,iBAAiB;EACnD,IAAI,WAAW,KAAA,GACb,KAAK,SAAS;EAGhB,MAAM,QAAQ,SAAS,SAAS,iBAAiB;EACjD,IAAI,UAAU,KAAA,GACZ,KAAK,QAAQ;EAGf,MAAM,OAAO,iBAAiB;EAC9B,IAAI,SAAS,KAAA,GACX,KAAK,OAAO;EAGd,MAAM,kBAAkB,MAAM,gBAAgB;CAChD;;CAGA,KAAK,OAAO,eAAe;EACzB,OAAO,KAAK,YAAY;CAC1B;CAEA,WAAW;EACT,IAAI,KAAK,MACP,OAAO,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK;EAE9C,OAAO,GAAG,KAAK,KAAK,IAAI,KAAK;CAC/B;AACF;;;;;;;;;;;;;;AC7HA,IAAa,gBAAgB,QAAgB,UAA4B;CACvE,MAAM,EAAE,UAAU,OAAO,SAAS,OAAO,EAAE,YAAY,KAAK,CAAC;CAC7D,OAAO,CAAC;AACV;;;;;;;;;;;AAYA,IAAa,qBAAqB,UAA6C;CAwB7E,OAAO,aAvBQ,UAAU,aACvB,UAAU,OAAO,EAAE,SAAS,eAAsB,GAClD,UAAU,SAAS,EAAE,SAAS,eAAsB,GACpD,UACG,OAAO;EACN,SAAS,UAAU,OAAO,EAAE,SAAS;EACrC,SAAS,UACN,MAAM,EACN,MACC,UAAU,OAAO;GACf,SAAS,UAAU,OAAO,EAAE,SAAS;GACrC,MAAM,UACH,MAAM,EACN,MAAM,UAAU,aAAa,UAAU,OAAO,GAAG,UAAU,OAAO,CAAC,CAAC,EACpE,SAAS;GACZ,MAAM,UAAU,OAAO,EAAE,SAAS;GAClC,SAAS,UAAU,OAAO,EAAE,QAAQ,IAAI,EAAE,SAAS;EACrD,CAAC,CACH,EACC,SAAS;CACd,CAAC,EACA,QAAQ,IAAI,CAEG,GAAQ,KAAK;AACnC;AAEA,IAAM,8BAA8B,QAAqC,aAAqB;CAC5F,OAAO,SAAS,OAAO,QAAQ,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,IAAI;AACvE;;;;;;;;AASA,IAAa,sBAAb,MAAa,4BAA4B,cAAc;CACrD,OAAO,SAAS;CAChB,OAAO,OAAO;CACd,OAAO,QAAQ;;;;;CASf,YAAY,QAAyB;EACnC,MAAM,UAAU,2BAA2B,QAAQ,mBAAmB;EACtE,MAAM,SAAS;GACb,MAAM,oBAAoB;GAC1B,QAAQ,oBAAoB;GAC5B,OAAO,oBAAoB;GAC3B,OAAO;EACT,CAAC;EACD,OAAO,eAAe,MAAM,WAAW;GACrC,OAAO,OAAO;GACd,YAAY;GACZ,cAAc;GACd,UAAU;EACZ,CAAC;CACH;AACF;;;;;;;;;;;;;;;;AAiBA,IAAa,mBAAsB,QAAgB,OAAgB,UAAmB,UAAa;CACjG,MAAM,EAAE,OAAO,YAAY,UAAU,OAAO,SAAS,OAAO;EAAE,YAAY;EAAO;CAAQ,CAAC;CAC1F,IAAI,OACF,MAAM,IAAI,oBAAoB,KAAK;CAErC,OAAO;AACT;;;;;;;;;;;;;;;;AAiBA,IAAa,uBAAuB,OAClC,QACA,OACA,UAAmB,UACJ;CACf,IAAI;EACF,OAAO,MAAM,OAAO,cAAc,OAAO;GAAE,YAAY;GAAO;EAAQ,CAAC;CACzE,SAAS,OAAO;EACd,IAAI,kBAAkB,KAAK,GACzB,MAAM,IAAI,oBAAoB,KAAK;EAErC,MAAM;CACR;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1FA,IAAa,mBACX,MACA,SACA,MACA,QACA,UACwB;CACxB,MAAM,OAAO,cAAc,cAAc;EACvC,OAAO,UAAU;EACjB,OAAO,OAAO;EACd,OAAO,SAAS;EAChB,OAAO,QAAQ;EACf,YAAY,MAA6B,SAA4B;GACnE,MAAM,iBAAiB,MAAM,QAAQ,IAAI;GACzC,MAAM,cAAc,iBAAiB,OAAO,CAAC;GAC7C,MAAM,eAAe,iBAAiB,UAAU;GAEhD,MAAM,OAAO,SAAS,GAAG,WAAW,GAAG,YAAY;GACnD,KAAK,OAAO;EACd;CACF;CAIA,OAAO,eAAe,MAAM,QAAQ;EAAE,OAAO;EAAM,cAAc;CAAK,CAAC;CACvE,OAAO;AACT"}
@@ -63,6 +63,7 @@ var BaseException = class BaseException extends Error {
63
63
  if (help !== void 0) this.help = help;
64
64
  Error.captureStackTrace(this, ErrorConstructor);
65
65
  }
66
+ /** Tag used by `Object.prototype.toString` — reports the concrete exception class name. */
66
67
  get [Symbol.toStringTag]() {
67
68
  return this.constructor.name;
68
69
  }
@@ -204,7 +205,7 @@ var asyncValidateOrThrow = async (schema, value, convert = false) => {
204
205
  * @typeParam T - Tuple of printf format argument types. Pass a non-empty tuple to require
205
206
  * callers to supply interpolation values at the throw site.
206
207
  *
207
- * @param name - The `name` property set on thrown instances (used by {@link isNamedException}).
208
+ * @param name - The `name` property set on thrown instances (used by `isNamedException`).
208
209
  * @param message - Printf-style template string for the error message.
209
210
  * @param code - Machine-readable error code stored on the static and instance `code` property.
210
211
  * @param status - HTTP status code associated with this exception class.
@@ -277,4 +278,4 @@ Object.defineProperty(exports, "validateOrThrow", {
277
278
  }
278
279
  });
279
280
 
280
- //# sourceMappingURL=exceptions-CitH5wZI.js.map
281
+ //# sourceMappingURL=exceptions-BRXrUKiW.js.map