@nhtio/adk 0.1.0-master-f0aa531d

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 (297) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +3 -0
  3. package/batteries/index.d.ts +28 -0
  4. package/batteries/llm/index.d.ts +11 -0
  5. package/batteries/llm/openai_chat_completions/adapter.cjs +916 -0
  6. package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -0
  7. package/batteries/llm/openai_chat_completions/adapter.d.ts +101 -0
  8. package/batteries/llm/openai_chat_completions/adapter.mjs +914 -0
  9. package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -0
  10. package/batteries/llm/openai_chat_completions/exceptions.cjs +89 -0
  11. package/batteries/llm/openai_chat_completions/exceptions.cjs.map +1 -0
  12. package/batteries/llm/openai_chat_completions/exceptions.d.ts +97 -0
  13. package/batteries/llm/openai_chat_completions/exceptions.mjs +81 -0
  14. package/batteries/llm/openai_chat_completions/exceptions.mjs.map +1 -0
  15. package/batteries/llm/openai_chat_completions/helpers.cjs +819 -0
  16. package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -0
  17. package/batteries/llm/openai_chat_completions/helpers.d.ts +233 -0
  18. package/batteries/llm/openai_chat_completions/helpers.mjs +783 -0
  19. package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -0
  20. package/batteries/llm/openai_chat_completions/index.d.ts +27 -0
  21. package/batteries/llm/openai_chat_completions/types.cjs +1 -0
  22. package/batteries/llm/openai_chat_completions/types.d.ts +524 -0
  23. package/batteries/llm/openai_chat_completions/types.mjs +0 -0
  24. package/batteries/llm/openai_chat_completions/validation.cjs +190 -0
  25. package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -0
  26. package/batteries/llm/openai_chat_completions/validation.d.ts +31 -0
  27. package/batteries/llm/openai_chat_completions/validation.mjs +187 -0
  28. package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -0
  29. package/batteries/llm/openai_chat_completions.cjs +51 -0
  30. package/batteries/llm/openai_chat_completions.mjs +5 -0
  31. package/batteries/llm/webllm_chat_completions/adapter.cjs +658 -0
  32. package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -0
  33. package/batteries/llm/webllm_chat_completions/adapter.d.ts +103 -0
  34. package/batteries/llm/webllm_chat_completions/adapter.mjs +656 -0
  35. package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -0
  36. package/batteries/llm/webllm_chat_completions/exceptions.cjs +70 -0
  37. package/batteries/llm/webllm_chat_completions/exceptions.cjs.map +1 -0
  38. package/batteries/llm/webllm_chat_completions/exceptions.d.ts +74 -0
  39. package/batteries/llm/webllm_chat_completions/exceptions.mjs +65 -0
  40. package/batteries/llm/webllm_chat_completions/exceptions.mjs.map +1 -0
  41. package/batteries/llm/webllm_chat_completions/helpers.cjs +38 -0
  42. package/batteries/llm/webllm_chat_completions/helpers.d.ts +6 -0
  43. package/batteries/llm/webllm_chat_completions/helpers.mjs +2 -0
  44. package/batteries/llm/webllm_chat_completions/index.d.ts +25 -0
  45. package/batteries/llm/webllm_chat_completions/types.d.ts +31 -0
  46. package/batteries/llm/webllm_chat_completions/validation.cjs +115 -0
  47. package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -0
  48. package/batteries/llm/webllm_chat_completions/validation.d.ts +8 -0
  49. package/batteries/llm/webllm_chat_completions/validation.mjs +112 -0
  50. package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -0
  51. package/batteries/llm/webllm_chat_completions.cjs +50 -0
  52. package/batteries/llm/webllm_chat_completions.mjs +6 -0
  53. package/batteries/llm.cjs +63 -0
  54. package/batteries/llm.mjs +10 -0
  55. package/batteries/storage/flydrive/index.d.ts +167 -0
  56. package/batteries/storage/flydrive.cjs +249 -0
  57. package/batteries/storage/flydrive.cjs.map +1 -0
  58. package/batteries/storage/flydrive.mjs +249 -0
  59. package/batteries/storage/flydrive.mjs.map +1 -0
  60. package/batteries/storage/in_memory/index.d.ts +106 -0
  61. package/batteries/storage/in_memory.cjs +121 -0
  62. package/batteries/storage/in_memory.cjs.map +1 -0
  63. package/batteries/storage/in_memory.mjs +119 -0
  64. package/batteries/storage/in_memory.mjs.map +1 -0
  65. package/batteries/storage/index.d.ts +18 -0
  66. package/batteries/storage/opfs/index.d.ts +299 -0
  67. package/batteries/storage/opfs.cjs +368 -0
  68. package/batteries/storage/opfs.cjs.map +1 -0
  69. package/batteries/storage/opfs.mjs +366 -0
  70. package/batteries/storage/opfs.mjs.map +1 -0
  71. package/batteries/storage.cjs +4 -0
  72. package/batteries/storage.mjs +2 -0
  73. package/batteries/tools/color/index.d.ts +37 -0
  74. package/batteries/tools/color.cjs +659 -0
  75. package/batteries/tools/color.cjs.map +1 -0
  76. package/batteries/tools/color.mjs +655 -0
  77. package/batteries/tools/color.mjs.map +1 -0
  78. package/batteries/tools/comparison/index.d.ts +29 -0
  79. package/batteries/tools/comparison.cjs +171 -0
  80. package/batteries/tools/comparison.cjs.map +1 -0
  81. package/batteries/tools/comparison.mjs +168 -0
  82. package/batteries/tools/comparison.mjs.map +1 -0
  83. package/batteries/tools/data_structure/index.d.ts +30 -0
  84. package/batteries/tools/data_structure.cjs +270 -0
  85. package/batteries/tools/data_structure.cjs.map +1 -0
  86. package/batteries/tools/data_structure.mjs +267 -0
  87. package/batteries/tools/data_structure.mjs.map +1 -0
  88. package/batteries/tools/datetime_extended/index.d.ts +51 -0
  89. package/batteries/tools/datetime_extended.cjs +309 -0
  90. package/batteries/tools/datetime_extended.cjs.map +1 -0
  91. package/batteries/tools/datetime_extended.mjs +302 -0
  92. package/batteries/tools/datetime_extended.mjs.map +1 -0
  93. package/batteries/tools/datetime_math/index.d.ts +36 -0
  94. package/batteries/tools/datetime_math.cjs +175 -0
  95. package/batteries/tools/datetime_math.cjs.map +1 -0
  96. package/batteries/tools/datetime_math.mjs +171 -0
  97. package/batteries/tools/datetime_math.mjs.map +1 -0
  98. package/batteries/tools/encoding/index.d.ts +36 -0
  99. package/batteries/tools/encoding.cjs +156 -0
  100. package/batteries/tools/encoding.cjs.map +1 -0
  101. package/batteries/tools/encoding.mjs +152 -0
  102. package/batteries/tools/encoding.mjs.map +1 -0
  103. package/batteries/tools/formatting/index.d.ts +28 -0
  104. package/batteries/tools/formatting.cjs +120 -0
  105. package/batteries/tools/formatting.cjs.map +1 -0
  106. package/batteries/tools/formatting.mjs +117 -0
  107. package/batteries/tools/formatting.mjs.map +1 -0
  108. package/batteries/tools/geo_basics/index.d.ts +33 -0
  109. package/batteries/tools/geo_basics.cjs +136 -0
  110. package/batteries/tools/geo_basics.cjs.map +1 -0
  111. package/batteries/tools/geo_basics.mjs +132 -0
  112. package/batteries/tools/geo_basics.mjs.map +1 -0
  113. package/batteries/tools/index.d.ts +32 -0
  114. package/batteries/tools/math/index.d.ts +37 -0
  115. package/batteries/tools/math.cjs +136 -0
  116. package/batteries/tools/math.cjs.map +1 -0
  117. package/batteries/tools/math.mjs +133 -0
  118. package/batteries/tools/math.mjs.map +1 -0
  119. package/batteries/tools/memory/index.d.ts +73 -0
  120. package/batteries/tools/memory.cjs +193 -0
  121. package/batteries/tools/memory.cjs.map +1 -0
  122. package/batteries/tools/memory.mjs +187 -0
  123. package/batteries/tools/memory.mjs.map +1 -0
  124. package/batteries/tools/parsing/index.d.ts +47 -0
  125. package/batteries/tools/parsing.cjs +191 -0
  126. package/batteries/tools/parsing.cjs.map +1 -0
  127. package/batteries/tools/parsing.mjs +185 -0
  128. package/batteries/tools/parsing.mjs.map +1 -0
  129. package/batteries/tools/retrievables/index.d.ts +81 -0
  130. package/batteries/tools/retrievables.cjs +215 -0
  131. package/batteries/tools/retrievables.cjs.map +1 -0
  132. package/batteries/tools/retrievables.mjs +209 -0
  133. package/batteries/tools/retrievables.mjs.map +1 -0
  134. package/batteries/tools/standing_instructions/index.d.ts +64 -0
  135. package/batteries/tools/standing_instructions.cjs +126 -0
  136. package/batteries/tools/standing_instructions.cjs.map +1 -0
  137. package/batteries/tools/standing_instructions.mjs +121 -0
  138. package/batteries/tools/standing_instructions.mjs.map +1 -0
  139. package/batteries/tools/statistics/index.d.ts +46 -0
  140. package/batteries/tools/statistics.cjs +253 -0
  141. package/batteries/tools/statistics.cjs.map +1 -0
  142. package/batteries/tools/statistics.mjs +248 -0
  143. package/batteries/tools/statistics.mjs.map +1 -0
  144. package/batteries/tools/string_processing/index.d.ts +29 -0
  145. package/batteries/tools/string_processing.cjs +154 -0
  146. package/batteries/tools/string_processing.cjs.map +1 -0
  147. package/batteries/tools/string_processing.mjs +151 -0
  148. package/batteries/tools/string_processing.mjs.map +1 -0
  149. package/batteries/tools/structured_data/index.d.ts +34 -0
  150. package/batteries/tools/structured_data.cjs +189 -0
  151. package/batteries/tools/structured_data.cjs.map +1 -0
  152. package/batteries/tools/structured_data.mjs +185 -0
  153. package/batteries/tools/structured_data.mjs.map +1 -0
  154. package/batteries/tools/text_analysis/index.d.ts +31 -0
  155. package/batteries/tools/text_analysis.cjs +120 -0
  156. package/batteries/tools/text_analysis.cjs.map +1 -0
  157. package/batteries/tools/text_analysis.mjs +117 -0
  158. package/batteries/tools/text_analysis.mjs.map +1 -0
  159. package/batteries/tools/text_comparison/index.d.ts +28 -0
  160. package/batteries/tools/text_comparison.cjs +96 -0
  161. package/batteries/tools/text_comparison.cjs.map +1 -0
  162. package/batteries/tools/text_comparison.mjs +93 -0
  163. package/batteries/tools/text_comparison.mjs.map +1 -0
  164. package/batteries/tools/time/index.d.ts +27 -0
  165. package/batteries/tools/time.cjs +63 -0
  166. package/batteries/tools/time.cjs.map +1 -0
  167. package/batteries/tools/time.mjs +60 -0
  168. package/batteries/tools/time.mjs.map +1 -0
  169. package/batteries/tools/unit_conversion/index.d.ts +19 -0
  170. package/batteries/tools/unit_conversion.cjs +452 -0
  171. package/batteries/tools/unit_conversion.cjs.map +1 -0
  172. package/batteries/tools/unit_conversion.mjs +450 -0
  173. package/batteries/tools/unit_conversion.mjs.map +1 -0
  174. package/batteries/tools.cjs +80 -0
  175. package/batteries/tools.mjs +21 -0
  176. package/batteries.cjs +142 -0
  177. package/batteries.mjs +30 -0
  178. package/chunk-KmRHZBOW.js +35 -0
  179. package/common-DeZaonK1.mjs +208 -0
  180. package/common-DeZaonK1.mjs.map +1 -0
  181. package/common-Od8edUXU.js +232 -0
  182. package/common-Od8edUXU.js.map +1 -0
  183. package/common.cjs +31 -0
  184. package/common.d.ts +108 -0
  185. package/common.mjs +8 -0
  186. package/dispatch_runner-9j6bXHL3.mjs +1609 -0
  187. package/dispatch_runner-9j6bXHL3.mjs.map +1 -0
  188. package/dispatch_runner-CsoH0nld.js +1627 -0
  189. package/dispatch_runner-CsoH0nld.js.map +1 -0
  190. package/dispatch_runner.cjs +3 -0
  191. package/dispatch_runner.d.ts +17 -0
  192. package/dispatch_runner.mjs +2 -0
  193. package/exceptions-D5YrO9Vm.js +280 -0
  194. package/exceptions-D5YrO9Vm.js.map +1 -0
  195. package/exceptions-NrzIHw_R.mjs +244 -0
  196. package/exceptions-NrzIHw_R.mjs.map +1 -0
  197. package/exceptions.cjs +33 -0
  198. package/exceptions.d.ts +52 -0
  199. package/exceptions.mjs +3 -0
  200. package/factories.cjs +4 -0
  201. package/factories.d.ts +39 -0
  202. package/factories.mjs +2 -0
  203. package/forge.cjs +9 -0
  204. package/forge.d.ts +49 -0
  205. package/forge.mjs +5 -0
  206. package/guards.cjs +96 -0
  207. package/guards.cjs.map +1 -0
  208. package/guards.d.ts +83 -0
  209. package/guards.mjs +72 -0
  210. package/guards.mjs.map +1 -0
  211. package/index.cjs +107 -0
  212. package/index.cjs.map +1 -0
  213. package/index.d.ts +18 -0
  214. package/index.mjs +31 -0
  215. package/index.mjs.map +1 -0
  216. package/lib/classes/artifact_tool.d.ts +129 -0
  217. package/lib/classes/base_exception.d.ts +83 -0
  218. package/lib/classes/identity.d.ts +71 -0
  219. package/lib/classes/media.d.ts +326 -0
  220. package/lib/classes/memory.d.ts +72 -0
  221. package/lib/classes/message.d.ts +137 -0
  222. package/lib/classes/registry.d.ts +79 -0
  223. package/lib/classes/retrievable.d.ts +100 -0
  224. package/lib/classes/spooled_artifact.d.ts +296 -0
  225. package/lib/classes/spooled_json_artifact.d.ts +158 -0
  226. package/lib/classes/spooled_markdown_artifact.d.ts +202 -0
  227. package/lib/classes/thought.d.ts +142 -0
  228. package/lib/classes/tokenizable.d.ts +124 -0
  229. package/lib/classes/tool.d.ts +228 -0
  230. package/lib/classes/tool_call.d.ts +190 -0
  231. package/lib/classes/tool_registry.d.ts +159 -0
  232. package/lib/classes/turn_gate.d.ts +109 -0
  233. package/lib/contracts/dispatch_context.d.ts +345 -0
  234. package/lib/contracts/media_reader.d.ts +60 -0
  235. package/lib/contracts/spool_reader.d.ts +80 -0
  236. package/lib/contracts/spooled_artifact_constructor.d.ts +38 -0
  237. package/lib/contracts/turn_runner_config.d.ts +101 -0
  238. package/lib/contracts/turn_runner_context.d.ts +267 -0
  239. package/lib/dispatch_runner.d.ts +98 -0
  240. package/lib/exceptions/runtime.d.ts +370 -0
  241. package/lib/helpers/media_readers.d.ts +39 -0
  242. package/lib/turn_runner.d.ts +144 -0
  243. package/lib/types/dispatch_context.d.ts +233 -0
  244. package/lib/types/dispatch_runner.d.ts +387 -0
  245. package/lib/types/turn_runner.d.ts +322 -0
  246. package/lib/utils/canonical_json.d.ts +18 -0
  247. package/lib/utils/exceptions.d.ts +78 -0
  248. package/lib/utils/guards.d.ts +32 -0
  249. package/lib/utils/validation.d.ts +77 -0
  250. package/package.json +334 -0
  251. package/runtime-BJVkrGQe.js +519 -0
  252. package/runtime-BJVkrGQe.js.map +1 -0
  253. package/runtime-CrEPIFgr.mjs +346 -0
  254. package/runtime-CrEPIFgr.mjs.map +1 -0
  255. package/skills/adk-assembly/SKILL.md +109 -0
  256. package/skills/adk-assembly/references/assembly-contract.md +66 -0
  257. package/skills/adk-assembly/references/executors-tools-pipelines-events.md +113 -0
  258. package/skills/adk-assembly/references/first-integration.md +93 -0
  259. package/skills/adk-assembly/references/storage-and-context.md +102 -0
  260. package/spooled_artifact-C5ZtGxuJ.mjs +544 -0
  261. package/spooled_artifact-C5ZtGxuJ.mjs.map +1 -0
  262. package/spooled_artifact-Cm9Te22K.js +568 -0
  263. package/spooled_artifact-Cm9Te22K.js.map +1 -0
  264. package/spooled_artifact.cjs +7 -0
  265. package/spooled_artifact.d.ts +40 -0
  266. package/spooled_artifact.mjs +3 -0
  267. package/spooled_markdown_artifact-BpUJol0W.mjs +771 -0
  268. package/spooled_markdown_artifact-BpUJol0W.mjs.map +1 -0
  269. package/spooled_markdown_artifact-RRB113sy.js +786 -0
  270. package/spooled_markdown_artifact-RRB113sy.js.map +1 -0
  271. package/thought-CDb457b4.mjs +470 -0
  272. package/thought-CDb457b4.mjs.map +1 -0
  273. package/thought-DuN2PgdO.js +494 -0
  274. package/thought-DuN2PgdO.js.map +1 -0
  275. package/tool-COSeH8I6.js +302 -0
  276. package/tool-COSeH8I6.js.map +1 -0
  277. package/tool-D2WB1EA1.mjs +296 -0
  278. package/tool-D2WB1EA1.mjs.map +1 -0
  279. package/tool_call-BKyyxGaZ.mjs +578 -0
  280. package/tool_call-BKyyxGaZ.mjs.map +1 -0
  281. package/tool_call-DFgzcVcU.js +608 -0
  282. package/tool_call-DFgzcVcU.js.map +1 -0
  283. package/tool_registry-Dkfprsck.js +641 -0
  284. package/tool_registry-Dkfprsck.js.map +1 -0
  285. package/tool_registry-DqLOyGyG.mjs +592 -0
  286. package/tool_registry-DqLOyGyG.mjs.map +1 -0
  287. package/turn_runner-CMm2BHdX.js +615 -0
  288. package/turn_runner-CMm2BHdX.js.map +1 -0
  289. package/turn_runner-y7eyEcJH.mjs +603 -0
  290. package/turn_runner-y7eyEcJH.mjs.map +1 -0
  291. package/turn_runner.cjs +3 -0
  292. package/turn_runner.d.ts +21 -0
  293. package/turn_runner.mjs +2 -0
  294. package/types.cjs +1 -0
  295. package/types.d.ts +56 -0
  296. package/types.mjs +0 -0
  297. package/vite-env.d.ts +23 -0
@@ -0,0 +1,185 @@
1
+ import { o as isError } from "../../tool_registry-DqLOyGyG.mjs";
2
+ import "../../common-DeZaonK1.mjs";
3
+ import { t as Tool } from "../../tool-D2WB1EA1.mjs";
4
+ import "../../guards.mjs";
5
+ import { validator } from "@nhtio/validation";
6
+ //#region src/batteries/tools/structured_data/index.ts
7
+ /**
8
+ * Pre-constructed tools for transforming arrays and objects into tables and tabular text.
9
+ *
10
+ * @module @nhtio/adk/batteries/tools/structured_data
11
+ *
12
+ * @remarks
13
+ * Pre-constructed bundled tools for the `structured_data` category. Import individually, the whole
14
+ * category, or import every tool via `@nhtio/adk/batteries`.
15
+ */
16
+ function csvEscape(value) {
17
+ const str = value === null || value === void 0 ? "" : String(value);
18
+ if (str.includes(",") || str.includes("\"") || str.includes("\n") || str.includes("\r")) return "\"" + str.replace(/"/g, "\"\"") + "\"";
19
+ return str;
20
+ }
21
+ function tsvEscape(value) {
22
+ return (value === null || value === void 0 ? "" : String(value)).replace(/\t/g, " ").replace(/\r?\n/g, " ");
23
+ }
24
+ function mdEscape(value) {
25
+ return String(value === null || value === void 0 ? "" : value).replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
26
+ }
27
+ /**
28
+ * Convert a JSON array of objects into a formatted table.
29
+ *
30
+ * @remarks
31
+ * Supports `markdown`, `csv`, and `tsv` output. Columns default to the keys of the first row;
32
+ * supply `columns` to control which keys appear and in what order.
33
+ */
34
+ var formatTableTool = new Tool({
35
+ name: "format_table",
36
+ description: "Convert a JSON array of objects into a formatted table. Supports Markdown, CSV, and TSV output.",
37
+ inputSchema: validator.object({
38
+ data: validator.string().required().description("JSON array of objects as a string"),
39
+ format: validator.string().valid("markdown", "csv", "tsv").required().description("Output format"),
40
+ columns: validator.array().items(validator.string()).optional().description("Column keys to include, in order. If omitted, all keys from the first row are used.")
41
+ }),
42
+ handler: async (args) => {
43
+ const { data, format, columns: explicitColumns } = args;
44
+ let rows;
45
+ try {
46
+ rows = JSON.parse(data);
47
+ } catch {
48
+ return "Error: Invalid JSON input.";
49
+ }
50
+ if (!Array.isArray(rows)) return "Error: Input must be a JSON array.";
51
+ if (rows.length === 0) return "Empty array — no data to display.";
52
+ const columns = explicitColumns ?? Object.keys(rows[0]);
53
+ if (format === "csv") {
54
+ const lines = [columns.map(csvEscape).join(",")];
55
+ for (const row of rows) {
56
+ const obj = row;
57
+ lines.push(columns.map((col) => csvEscape(obj[col])).join(","));
58
+ }
59
+ return lines.join("\n");
60
+ }
61
+ if (format === "tsv") {
62
+ const lines = [columns.map(tsvEscape).join(" ")];
63
+ for (const row of rows) {
64
+ const obj = row;
65
+ lines.push(columns.map((col) => tsvEscape(obj[col])).join(" "));
66
+ }
67
+ return lines.join("\n");
68
+ }
69
+ return [
70
+ "| " + columns.map(mdEscape).join(" | ") + " |",
71
+ "| " + columns.map(() => "---").join(" | ") + " |",
72
+ ...rows.map((row) => {
73
+ const obj = row;
74
+ return "| " + columns.map((col) => mdEscape(obj[col])).join(" | ") + " |";
75
+ })
76
+ ].join("\n");
77
+ }
78
+ });
79
+ /**
80
+ * Pretty-print or minify a JSON string.
81
+ *
82
+ * @remarks
83
+ * Validates the input as JSON, then re-serialises it with the requested indentation. `indent` is
84
+ * clamped to the range [0, 8]; `0` produces minified output.
85
+ */
86
+ var jsonFormatTool = new Tool({
87
+ name: "json_format",
88
+ description: "Pretty-print or minify a JSON string. Validates JSON and normalises whitespace.",
89
+ inputSchema: validator.object({
90
+ data: validator.string().required().description("JSON string to format"),
91
+ indent: validator.number().default(2).description("Indentation spaces (0 = minify, default: 2). Max: 8.")
92
+ }),
93
+ handler: async (args) => {
94
+ const { data, indent } = args;
95
+ try {
96
+ const parsed = JSON.parse(data);
97
+ return JSON.stringify(parsed, null, Math.max(0, Math.min(8, Math.floor(indent))));
98
+ } catch (err) {
99
+ return `Error: Invalid JSON — ${isError(err) ? err.message : String(err)}`;
100
+ }
101
+ }
102
+ });
103
+ var FORMAT_PATTERNS = {
104
+ email: {
105
+ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
106
+ label: "email address"
107
+ },
108
+ uuid: {
109
+ pattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
110
+ label: "UUID (v1–v5)"
111
+ },
112
+ ipv4: {
113
+ pattern: /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
114
+ label: "IPv4 address"
115
+ },
116
+ iso_date: {
117
+ pattern: /^\d{4}-\d{2}-\d{2}$/,
118
+ label: "ISO 8601 date (YYYY-MM-DD)"
119
+ },
120
+ iso_datetime: {
121
+ pattern: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?$/,
122
+ label: "ISO 8601 datetime"
123
+ },
124
+ hex_color: {
125
+ pattern: /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/,
126
+ label: "CSS hex color"
127
+ },
128
+ phone_e164: {
129
+ pattern: /^\+[1-9]\d{1,14}$/,
130
+ label: "E.164 phone number"
131
+ },
132
+ semver: {
133
+ pattern: /^\d+\.\d+\.\d+(-[0-9A-Za-z-.]+)?(\+[0-9A-Za-z-.]+)?$/,
134
+ label: "Semantic Version (SemVer)"
135
+ },
136
+ integer: {
137
+ pattern: /^-?\d+$/,
138
+ label: "integer"
139
+ },
140
+ decimal: {
141
+ pattern: /^-?\d+(\.\d+)?$/,
142
+ label: "decimal number"
143
+ },
144
+ alphanumeric: {
145
+ pattern: /^[a-zA-Z0-9]+$/,
146
+ label: "alphanumeric string"
147
+ },
148
+ slug: {
149
+ pattern: /^[a-z0-9]+(-[a-z0-9]+)*$/,
150
+ label: "URL slug"
151
+ },
152
+ hex: {
153
+ pattern: /^(0x)?[0-9a-fA-F]+$/,
154
+ label: "hexadecimal string"
155
+ },
156
+ base64: {
157
+ pattern: /^[A-Za-z0-9+/]*={0,2}$/,
158
+ label: "base64-encoded string"
159
+ }
160
+ };
161
+ /**
162
+ * Check whether a string matches a known format.
163
+ *
164
+ * @remarks
165
+ * Supported formats: `email`, `uuid` (v1–v5), `ipv4`, `iso_date`, `iso_datetime`, `hex_color`,
166
+ * `phone_e164`, `semver`, `integer`, `decimal`, `alphanumeric`, `slug`, `hex`, `base64`.
167
+ */
168
+ var validateFormatTool = new Tool({
169
+ name: "validate_format",
170
+ description: "Check whether a string matches a known format (email, UUID, ISO date, hex colour, phone number, semver, slug, etc.).",
171
+ inputSchema: validator.object({
172
+ value: validator.string().required().description("The string to validate"),
173
+ format: validator.string().valid(...Object.keys(FORMAT_PATTERNS)).required().description(`Format to validate against. One of: ${Object.keys(FORMAT_PATTERNS).join(", ")}`)
174
+ }),
175
+ handler: async (args) => {
176
+ const { value, format } = args;
177
+ const def = FORMAT_PATTERNS[format];
178
+ if (!def) return `Error: Unknown format "${format}". Supported: ${Object.keys(FORMAT_PATTERNS).join(", ")}`;
179
+ return def.pattern.test(value) ? `Valid: "${value}" is a valid ${def.label}.` : `Invalid: "${value}" is not a valid ${def.label}.`;
180
+ }
181
+ });
182
+ //#endregion
183
+ export { formatTableTool, jsonFormatTool, validateFormatTool };
184
+
185
+ //# sourceMappingURL=structured_data.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured_data.mjs","names":[],"sources":["../../../src/batteries/tools/structured_data/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for transforming arrays and objects into tables and tabular text.\n *\n * @module @nhtio/adk/batteries/tools/structured_data\n *\n * @remarks\n * Pre-constructed bundled tools for the `structured_data` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { isError } from '@nhtio/adk/guards'\nimport { validator } from '@nhtio/validation'\n\nfunction csvEscape(value: unknown): string {\n const str = value === null || value === undefined ? '' : String(value)\n if (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r')) {\n return '\"' + str.replace(/\"/g, '\"\"') + '\"'\n }\n return str\n}\n\nfunction tsvEscape(value: unknown): string {\n const str = value === null || value === undefined ? '' : String(value)\n return str.replace(/\\t/g, ' ').replace(/\\r?\\n/g, ' ')\n}\n\nfunction mdEscape(value: unknown): string {\n return String(value === null || value === undefined ? '' : value)\n .replace(/\\|/g, '\\\\|')\n .replace(/\\r?\\n/g, ' ')\n}\n\n/**\n * Convert a JSON array of objects into a formatted table.\n *\n * @remarks\n * Supports `markdown`, `csv`, and `tsv` output. Columns default to the keys of the first row;\n * supply `columns` to control which keys appear and in what order.\n */\nexport const formatTableTool = new Tool({\n name: 'format_table',\n description:\n 'Convert a JSON array of objects into a formatted table. Supports Markdown, CSV, and TSV output.',\n inputSchema: validator.object({\n data: validator.string().required().description('JSON array of objects as a string'),\n format: validator\n .string()\n .valid('markdown', 'csv', 'tsv')\n .required()\n .description('Output format'),\n columns: validator\n .array()\n .items(validator.string())\n .optional()\n .description(\n 'Column keys to include, in order. If omitted, all keys from the first row are used.'\n ),\n }),\n handler: async (args) => {\n const {\n data,\n format,\n columns: explicitColumns,\n } = args as {\n data: string\n format: 'markdown' | 'csv' | 'tsv'\n columns?: string[]\n }\n\n let rows: unknown[]\n try {\n rows = JSON.parse(data)\n } catch {\n return 'Error: Invalid JSON input.'\n }\n\n if (!Array.isArray(rows)) return 'Error: Input must be a JSON array.'\n if (rows.length === 0) return 'Empty array — no data to display.'\n\n const columns = explicitColumns ?? Object.keys(rows[0] as Record<string, unknown>)\n\n if (format === 'csv') {\n const lines = [columns.map(csvEscape).join(',')]\n for (const row of rows) {\n const obj = row as Record<string, unknown>\n lines.push(columns.map((col) => csvEscape(obj[col])).join(','))\n }\n return lines.join('\\n')\n }\n\n if (format === 'tsv') {\n const lines = [columns.map(tsvEscape).join('\\t')]\n for (const row of rows) {\n const obj = row as Record<string, unknown>\n lines.push(columns.map((col) => tsvEscape(obj[col])).join('\\t'))\n }\n return lines.join('\\n')\n }\n\n const header = '| ' + columns.map(mdEscape).join(' | ') + ' |'\n const separator = '| ' + columns.map(() => '---').join(' | ') + ' |'\n const dataRows = rows.map((row) => {\n const obj = row as Record<string, unknown>\n return '| ' + columns.map((col) => mdEscape(obj[col])).join(' | ') + ' |'\n })\n return [header, separator, ...dataRows].join('\\n')\n },\n})\n\n/**\n * Pretty-print or minify a JSON string.\n *\n * @remarks\n * Validates the input as JSON, then re-serialises it with the requested indentation. `indent` is\n * clamped to the range [0, 8]; `0` produces minified output.\n */\nexport const jsonFormatTool = new Tool({\n name: 'json_format',\n description: 'Pretty-print or minify a JSON string. Validates JSON and normalises whitespace.',\n inputSchema: validator.object({\n data: validator.string().required().description('JSON string to format'),\n indent: validator\n .number()\n .default(2)\n .description('Indentation spaces (0 = minify, default: 2). Max: 8.'),\n }),\n handler: async (args) => {\n const { data, indent } = args as { data: string; indent: number }\n try {\n const parsed = JSON.parse(data)\n return JSON.stringify(parsed, null, Math.max(0, Math.min(8, Math.floor(indent))))\n } catch (err) {\n return `Error: Invalid JSON — ${isError(err) ? err.message : String(err)}`\n }\n },\n})\n\nconst FORMAT_PATTERNS: Record<string, { pattern: RegExp; label: string }> = {\n email: {\n pattern: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/,\n label: 'email address',\n },\n uuid: {\n pattern: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n label: 'UUID (v1–v5)',\n },\n ipv4: {\n pattern: /^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$/,\n label: 'IPv4 address',\n },\n iso_date: {\n pattern: /^\\d{4}-\\d{2}-\\d{2}$/,\n label: 'ISO 8601 date (YYYY-MM-DD)',\n },\n iso_datetime: {\n pattern: /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})?$/,\n label: 'ISO 8601 datetime',\n },\n hex_color: {\n pattern: /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/,\n label: 'CSS hex color',\n },\n phone_e164: {\n pattern: /^\\+[1-9]\\d{1,14}$/,\n label: 'E.164 phone number',\n },\n semver: {\n pattern: /^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-.]+)?(\\+[0-9A-Za-z-.]+)?$/,\n label: 'Semantic Version (SemVer)',\n },\n integer: {\n pattern: /^-?\\d+$/,\n label: 'integer',\n },\n decimal: {\n pattern: /^-?\\d+(\\.\\d+)?$/,\n label: 'decimal number',\n },\n alphanumeric: {\n pattern: /^[a-zA-Z0-9]+$/,\n label: 'alphanumeric string',\n },\n slug: {\n pattern: /^[a-z0-9]+(-[a-z0-9]+)*$/,\n label: 'URL slug',\n },\n hex: {\n pattern: /^(0x)?[0-9a-fA-F]+$/,\n label: 'hexadecimal string',\n },\n base64: {\n pattern: /^[A-Za-z0-9+/]*={0,2}$/,\n label: 'base64-encoded string',\n },\n}\n\n/**\n * Check whether a string matches a known format.\n *\n * @remarks\n * Supported formats: `email`, `uuid` (v1–v5), `ipv4`, `iso_date`, `iso_datetime`, `hex_color`,\n * `phone_e164`, `semver`, `integer`, `decimal`, `alphanumeric`, `slug`, `hex`, `base64`.\n */\nexport const validateFormatTool = new Tool({\n name: 'validate_format',\n description:\n 'Check whether a string matches a known format (email, UUID, ISO date, hex colour, phone number, semver, slug, etc.).',\n inputSchema: validator.object({\n value: validator.string().required().description('The string to validate'),\n format: validator\n .string()\n .valid(...Object.keys(FORMAT_PATTERNS))\n .required()\n .description(\n `Format to validate against. One of: ${Object.keys(FORMAT_PATTERNS).join(', ')}`\n ),\n }),\n handler: async (args) => {\n const { value, format } = args as { value: string; format: string }\n const def = FORMAT_PATTERNS[format]\n if (!def) {\n return `Error: Unknown format \"${format}\". Supported: ${Object.keys(FORMAT_PATTERNS).join(', ')}`\n }\n const valid = def.pattern.test(value)\n return valid\n ? `Valid: \"${value}\" is a valid ${def.label}.`\n : `Invalid: \"${value}\" is not a valid ${def.label}.`\n },\n})\n"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Pre-constructed tools for extracting counts, token estimates, and character statistics from text.
3
+ *
4
+ * @module @nhtio/adk/batteries/tools/text_analysis
5
+ *
6
+ * @remarks
7
+ * Pre-constructed bundled tools for the `text_analysis` category. Import individually, the whole
8
+ * category, or import every tool via `@nhtio/adk/batteries`.
9
+ */
10
+ import { Tool, SpooledJsonArtifact } from "../../../common";
11
+ /**
12
+ * Analyze text and return statistics as a JSON document.
13
+ *
14
+ * @remarks
15
+ * Reports character counts (with and without spaces), word/sentence/paragraph/line counts,
16
+ * unique word count, average word length, a rough token estimate (4 chars/token), and a set
17
+ * of character-class booleans (`is_all_alpha`, `is_all_ascii`, etc.).
18
+ *
19
+ * Output is JSON, so the artifact constructor is set to {@link @nhtio/adk!SpooledJsonArtifact} — consumer
20
+ * code can read the result back as a parsed record without re-parsing.
21
+ */
22
+ export declare const textAnalyzeTool: Tool<SpooledJsonArtifact<unknown>>;
23
+ /**
24
+ * Operate on text treated as a list of lines.
25
+ *
26
+ * @remarks
27
+ * Operations: `sort`, `sort_desc`, `reverse`, `deduplicate`, `filter_empty`, `trim_each`,
28
+ * `number` (prefix each line with `1.`, `2.`, …), `count`. Sort and deduplicate respect the
29
+ * optional `case_insensitive` flag.
30
+ */
31
+ export declare const textLinesTool: Tool<import("../../../common").SpooledArtifact>;
@@ -0,0 +1,120 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../chunk-KmRHZBOW.js");
3
+ require("../../common-Od8edUXU.js");
4
+ const require_tool = require("../../tool-COSeH8I6.js");
5
+ const require_spooled_markdown_artifact = require("../../spooled_markdown_artifact-RRB113sy.js");
6
+ let _nhtio_validation = require("@nhtio/validation");
7
+ //#region src/batteries/tools/text_analysis/index.ts
8
+ /**
9
+ * Pre-constructed tools for extracting counts, token estimates, and character statistics from text.
10
+ *
11
+ * @module @nhtio/adk/batteries/tools/text_analysis
12
+ *
13
+ * @remarks
14
+ * Pre-constructed bundled tools for the `text_analysis` category. Import individually, the whole
15
+ * category, or import every tool via `@nhtio/adk/batteries`.
16
+ */
17
+ /**
18
+ * Analyze text and return statistics as a JSON document.
19
+ *
20
+ * @remarks
21
+ * Reports character counts (with and without spaces), word/sentence/paragraph/line counts,
22
+ * unique word count, average word length, a rough token estimate (4 chars/token), and a set
23
+ * of character-class booleans (`is_all_alpha`, `is_all_ascii`, etc.).
24
+ *
25
+ * Output is JSON, so the artifact constructor is set to {@link @nhtio/adk!SpooledJsonArtifact} — consumer
26
+ * code can read the result back as a parsed record without re-parsing.
27
+ */
28
+ var textAnalyzeTool = new require_tool.Tool({
29
+ name: "text_analyze",
30
+ description: "Analyze text and return statistics: character counts, word/sentence/paragraph/line counts, unique word count, average word length, token estimate, and character-set properties.",
31
+ inputSchema: _nhtio_validation.validator.object({ text: _nhtio_validation.validator.string().required().description("The text to analyze") }),
32
+ artifactConstructor: () => require_spooled_markdown_artifact.SpooledJsonArtifact,
33
+ handler: async (args) => {
34
+ const { text } = args;
35
+ const charCount = text.length;
36
+ const charCountNoSpaces = text.replace(/\s/g, "").length;
37
+ const words = text.trim() === "" ? [] : text.trim().split(/\s+/);
38
+ const wordCount = words.length;
39
+ const sentenceMatches = text.match(/[.!?]+(?:\s|$)/g);
40
+ const sentenceCount = sentenceMatches ? sentenceMatches.length : text.trim().length > 0 ? 1 : 0;
41
+ const paragraphCount = text.split(/\n[ \t]*\n/).filter((p) => p.trim().length > 0).length || (text.trim().length > 0 ? 1 : 0);
42
+ const lineCount = text === "" ? 0 : text.split("\n").length;
43
+ const tokenEstimate = Math.ceil(text.length / 4);
44
+ const uniqueWordCount = new Set(words.map((w) => w.toLowerCase().replace(/[^a-z0-9]/g, "")).filter(Boolean)).size;
45
+ const totalWordLen = words.reduce((sum, w) => sum + w.length, 0);
46
+ const avgWordLength = wordCount > 0 ? Number.parseFloat((totalWordLen / wordCount).toFixed(2)) : 0;
47
+ const isAllAlpha = text.trim().length > 0 && /^[a-zA-Z\s]*$/.test(text);
48
+ const isAllNumeric = /^\d+$/.test(text.trim());
49
+ const isAllAlphanumeric = text.trim().length > 0 && /^[a-zA-Z0-9\s]*$/.test(text);
50
+ const isAllAscii = [...text].every((c) => c.charCodeAt(0) < 128);
51
+ const isAllLowercase = text === text.toLowerCase() && /[a-z]/.test(text);
52
+ const isAllUppercase = text === text.toUpperCase() && /[A-Z]/.test(text);
53
+ return JSON.stringify({
54
+ char_count: charCount,
55
+ char_count_no_spaces: charCountNoSpaces,
56
+ word_count: wordCount,
57
+ unique_word_count: uniqueWordCount,
58
+ sentence_count: sentenceCount,
59
+ paragraph_count: paragraphCount,
60
+ line_count: lineCount,
61
+ avg_word_length: avgWordLength,
62
+ token_estimate: tokenEstimate,
63
+ is_all_alpha: isAllAlpha,
64
+ is_all_numeric: isAllNumeric,
65
+ is_all_alphanumeric: isAllAlphanumeric,
66
+ is_all_ascii: isAllAscii,
67
+ is_all_lowercase: isAllLowercase,
68
+ is_all_uppercase: isAllUppercase,
69
+ has_unicode: !isAllAscii
70
+ }, null, 2);
71
+ }
72
+ });
73
+ /**
74
+ * Operate on text treated as a list of lines.
75
+ *
76
+ * @remarks
77
+ * Operations: `sort`, `sort_desc`, `reverse`, `deduplicate`, `filter_empty`, `trim_each`,
78
+ * `number` (prefix each line with `1.`, `2.`, …), `count`. Sort and deduplicate respect the
79
+ * optional `case_insensitive` flag.
80
+ */
81
+ var textLinesTool = new require_tool.Tool({
82
+ name: "text_lines",
83
+ description: "Perform operations on text treated as a list of lines: sort, deduplicate, reverse, filter empty lines, trim each line, number each line, or count.",
84
+ inputSchema: _nhtio_validation.validator.object({
85
+ text: _nhtio_validation.validator.string().required().description("Multi-line text to process"),
86
+ operation: _nhtio_validation.validator.string().valid("sort", "sort_desc", "reverse", "deduplicate", "filter_empty", "trim_each", "number", "count").required().description("Operation to apply to lines"),
87
+ case_insensitive: _nhtio_validation.validator.boolean().default(false).description("For sort / deduplicate: ignore case (default: false)")
88
+ }),
89
+ handler: async (args) => {
90
+ const { text, operation, case_insensitive: ci } = args;
91
+ const lines = text.split("\n");
92
+ switch (operation) {
93
+ case "sort": return [...lines].sort((a, b) => (ci ? a.toLowerCase() : a).localeCompare(ci ? b.toLowerCase() : b)).join("\n");
94
+ case "sort_desc": return [...lines].sort((a, b) => (ci ? b.toLowerCase() : b).localeCompare(ci ? a.toLowerCase() : a)).join("\n");
95
+ case "reverse": return [...lines].reverse().join("\n");
96
+ case "deduplicate": {
97
+ const seen = /* @__PURE__ */ new Set();
98
+ return lines.filter((line) => {
99
+ const key = ci ? line.toLowerCase() : line;
100
+ if (seen.has(key)) return false;
101
+ seen.add(key);
102
+ return true;
103
+ }).join("\n");
104
+ }
105
+ case "filter_empty": return lines.filter((l) => l.trim() !== "").join("\n");
106
+ case "trim_each": return lines.map((l) => l.trim()).join("\n");
107
+ case "number": return lines.map((l, i) => `${i + 1}. ${l}`).join("\n");
108
+ case "count": {
109
+ const nonEmpty = lines.filter((l) => l.trim() !== "").length;
110
+ return `${lines.length} lines (${nonEmpty} non-empty, ${lines.length - nonEmpty} empty)`;
111
+ }
112
+ default: return `Error: Unknown operation "${operation}".`;
113
+ }
114
+ }
115
+ });
116
+ //#endregion
117
+ exports.textAnalyzeTool = textAnalyzeTool;
118
+ exports.textLinesTool = textLinesTool;
119
+
120
+ //# sourceMappingURL=text_analysis.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text_analysis.cjs","names":[],"sources":["../../../src/batteries/tools/text_analysis/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for extracting counts, token estimates, and character statistics from text.\n *\n * @module @nhtio/adk/batteries/tools/text_analysis\n *\n * @remarks\n * Pre-constructed bundled tools for the `text_analysis` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { validator } from '@nhtio/validation'\nimport { Tool, SpooledJsonArtifact } from '@nhtio/adk/common'\n\n/**\n * Analyze text and return statistics as a JSON document.\n *\n * @remarks\n * Reports character counts (with and without spaces), word/sentence/paragraph/line counts,\n * unique word count, average word length, a rough token estimate (4 chars/token), and a set\n * of character-class booleans (`is_all_alpha`, `is_all_ascii`, etc.).\n *\n * Output is JSON, so the artifact constructor is set to {@link @nhtio/adk!SpooledJsonArtifact} — consumer\n * code can read the result back as a parsed record without re-parsing.\n */\nexport const textAnalyzeTool = new Tool({\n name: 'text_analyze',\n description:\n 'Analyze text and return statistics: character counts, word/sentence/paragraph/line counts, unique word count, average word length, token estimate, and character-set properties.',\n inputSchema: validator.object({\n text: validator.string().required().description('The text to analyze'),\n }),\n artifactConstructor: () => SpooledJsonArtifact,\n handler: async (args) => {\n const { text } = args as { text: string }\n\n const charCount = text.length\n const charCountNoSpaces = text.replace(/\\s/g, '').length\n\n const words = text.trim() === '' ? [] : text.trim().split(/\\s+/)\n const wordCount = words.length\n\n const sentenceMatches = text.match(/[.!?]+(?:\\s|$)/g)\n const sentenceCount = sentenceMatches ? sentenceMatches.length : text.trim().length > 0 ? 1 : 0\n\n const paragraphs = text.split(/\\n[ \\t]*\\n/).filter((p) => p.trim().length > 0)\n const paragraphCount = paragraphs.length || (text.trim().length > 0 ? 1 : 0)\n\n const lineCount = text === '' ? 0 : text.split('\\n').length\n\n const tokenEstimate = Math.ceil(text.length / 4)\n\n const uniqueWords = new Set(\n words.map((w) => w.toLowerCase().replace(/[^a-z0-9]/g, '')).filter(Boolean)\n )\n const uniqueWordCount = uniqueWords.size\n\n const totalWordLen = words.reduce((sum, w) => sum + w.length, 0)\n const avgWordLength =\n wordCount > 0 ? Number.parseFloat((totalWordLen / wordCount).toFixed(2)) : 0\n\n const isAllAlpha = text.trim().length > 0 && /^[a-zA-Z\\s]*$/.test(text)\n const isAllNumeric = /^\\d+$/.test(text.trim())\n const isAllAlphanumeric = text.trim().length > 0 && /^[a-zA-Z0-9\\s]*$/.test(text)\n const isAllAscii = [...text].every((c) => c.charCodeAt(0) < 128)\n const isAllLowercase = text === text.toLowerCase() && /[a-z]/.test(text)\n const isAllUppercase = text === text.toUpperCase() && /[A-Z]/.test(text)\n\n return JSON.stringify(\n {\n char_count: charCount,\n char_count_no_spaces: charCountNoSpaces,\n word_count: wordCount,\n unique_word_count: uniqueWordCount,\n sentence_count: sentenceCount,\n paragraph_count: paragraphCount,\n line_count: lineCount,\n avg_word_length: avgWordLength,\n token_estimate: tokenEstimate,\n is_all_alpha: isAllAlpha,\n is_all_numeric: isAllNumeric,\n is_all_alphanumeric: isAllAlphanumeric,\n is_all_ascii: isAllAscii,\n is_all_lowercase: isAllLowercase,\n is_all_uppercase: isAllUppercase,\n has_unicode: !isAllAscii,\n },\n null,\n 2\n )\n },\n})\n\n/**\n * Operate on text treated as a list of lines.\n *\n * @remarks\n * Operations: `sort`, `sort_desc`, `reverse`, `deduplicate`, `filter_empty`, `trim_each`,\n * `number` (prefix each line with `1.`, `2.`, …), `count`. Sort and deduplicate respect the\n * optional `case_insensitive` flag.\n */\nexport const textLinesTool = new Tool({\n name: 'text_lines',\n description:\n 'Perform operations on text treated as a list of lines: sort, deduplicate, reverse, filter empty lines, trim each line, number each line, or count.',\n inputSchema: validator.object({\n text: validator.string().required().description('Multi-line text to process'),\n operation: validator\n .string()\n .valid(\n 'sort',\n 'sort_desc',\n 'reverse',\n 'deduplicate',\n 'filter_empty',\n 'trim_each',\n 'number',\n 'count'\n )\n .required()\n .description('Operation to apply to lines'),\n case_insensitive: validator\n .boolean()\n .default(false)\n .description('For sort / deduplicate: ignore case (default: false)'),\n }),\n handler: async (args) => {\n const {\n text,\n operation,\n case_insensitive: ci,\n } = args as {\n text: string\n operation: string\n case_insensitive: boolean\n }\n const lines = text.split('\\n')\n\n switch (operation) {\n case 'sort':\n return [...lines]\n .sort((a, b) => (ci ? a.toLowerCase() : a).localeCompare(ci ? b.toLowerCase() : b))\n .join('\\n')\n case 'sort_desc':\n return [...lines]\n .sort((a, b) => (ci ? b.toLowerCase() : b).localeCompare(ci ? a.toLowerCase() : a))\n .join('\\n')\n case 'reverse':\n return [...lines].reverse().join('\\n')\n case 'deduplicate': {\n const seen = new Set<string>()\n return lines\n .filter((line) => {\n const key = ci ? line.toLowerCase() : line\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n .join('\\n')\n }\n case 'filter_empty':\n return lines.filter((l) => l.trim() !== '').join('\\n')\n case 'trim_each':\n return lines.map((l) => l.trim()).join('\\n')\n case 'number':\n return lines.map((l, i) => `${i + 1}. ${l}`).join('\\n')\n case 'count': {\n const nonEmpty = lines.filter((l) => l.trim() !== '').length\n return `${lines.length} lines (${nonEmpty} non-empty, ${lines.length - nonEmpty} empty)`\n }\n default:\n return `Error: Unknown operation \"${operation}\".`\n }\n },\n})\n"],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import "../../common-DeZaonK1.mjs";
2
+ import { t as Tool } from "../../tool-D2WB1EA1.mjs";
3
+ import { n as SpooledJsonArtifact } from "../../spooled_markdown_artifact-BpUJol0W.mjs";
4
+ import { validator } from "@nhtio/validation";
5
+ //#region src/batteries/tools/text_analysis/index.ts
6
+ /**
7
+ * Pre-constructed tools for extracting counts, token estimates, and character statistics from text.
8
+ *
9
+ * @module @nhtio/adk/batteries/tools/text_analysis
10
+ *
11
+ * @remarks
12
+ * Pre-constructed bundled tools for the `text_analysis` category. Import individually, the whole
13
+ * category, or import every tool via `@nhtio/adk/batteries`.
14
+ */
15
+ /**
16
+ * Analyze text and return statistics as a JSON document.
17
+ *
18
+ * @remarks
19
+ * Reports character counts (with and without spaces), word/sentence/paragraph/line counts,
20
+ * unique word count, average word length, a rough token estimate (4 chars/token), and a set
21
+ * of character-class booleans (`is_all_alpha`, `is_all_ascii`, etc.).
22
+ *
23
+ * Output is JSON, so the artifact constructor is set to {@link @nhtio/adk!SpooledJsonArtifact} — consumer
24
+ * code can read the result back as a parsed record without re-parsing.
25
+ */
26
+ var textAnalyzeTool = new Tool({
27
+ name: "text_analyze",
28
+ description: "Analyze text and return statistics: character counts, word/sentence/paragraph/line counts, unique word count, average word length, token estimate, and character-set properties.",
29
+ inputSchema: validator.object({ text: validator.string().required().description("The text to analyze") }),
30
+ artifactConstructor: () => SpooledJsonArtifact,
31
+ handler: async (args) => {
32
+ const { text } = args;
33
+ const charCount = text.length;
34
+ const charCountNoSpaces = text.replace(/\s/g, "").length;
35
+ const words = text.trim() === "" ? [] : text.trim().split(/\s+/);
36
+ const wordCount = words.length;
37
+ const sentenceMatches = text.match(/[.!?]+(?:\s|$)/g);
38
+ const sentenceCount = sentenceMatches ? sentenceMatches.length : text.trim().length > 0 ? 1 : 0;
39
+ const paragraphCount = text.split(/\n[ \t]*\n/).filter((p) => p.trim().length > 0).length || (text.trim().length > 0 ? 1 : 0);
40
+ const lineCount = text === "" ? 0 : text.split("\n").length;
41
+ const tokenEstimate = Math.ceil(text.length / 4);
42
+ const uniqueWordCount = new Set(words.map((w) => w.toLowerCase().replace(/[^a-z0-9]/g, "")).filter(Boolean)).size;
43
+ const totalWordLen = words.reduce((sum, w) => sum + w.length, 0);
44
+ const avgWordLength = wordCount > 0 ? Number.parseFloat((totalWordLen / wordCount).toFixed(2)) : 0;
45
+ const isAllAlpha = text.trim().length > 0 && /^[a-zA-Z\s]*$/.test(text);
46
+ const isAllNumeric = /^\d+$/.test(text.trim());
47
+ const isAllAlphanumeric = text.trim().length > 0 && /^[a-zA-Z0-9\s]*$/.test(text);
48
+ const isAllAscii = [...text].every((c) => c.charCodeAt(0) < 128);
49
+ const isAllLowercase = text === text.toLowerCase() && /[a-z]/.test(text);
50
+ const isAllUppercase = text === text.toUpperCase() && /[A-Z]/.test(text);
51
+ return JSON.stringify({
52
+ char_count: charCount,
53
+ char_count_no_spaces: charCountNoSpaces,
54
+ word_count: wordCount,
55
+ unique_word_count: uniqueWordCount,
56
+ sentence_count: sentenceCount,
57
+ paragraph_count: paragraphCount,
58
+ line_count: lineCount,
59
+ avg_word_length: avgWordLength,
60
+ token_estimate: tokenEstimate,
61
+ is_all_alpha: isAllAlpha,
62
+ is_all_numeric: isAllNumeric,
63
+ is_all_alphanumeric: isAllAlphanumeric,
64
+ is_all_ascii: isAllAscii,
65
+ is_all_lowercase: isAllLowercase,
66
+ is_all_uppercase: isAllUppercase,
67
+ has_unicode: !isAllAscii
68
+ }, null, 2);
69
+ }
70
+ });
71
+ /**
72
+ * Operate on text treated as a list of lines.
73
+ *
74
+ * @remarks
75
+ * Operations: `sort`, `sort_desc`, `reverse`, `deduplicate`, `filter_empty`, `trim_each`,
76
+ * `number` (prefix each line with `1.`, `2.`, …), `count`. Sort and deduplicate respect the
77
+ * optional `case_insensitive` flag.
78
+ */
79
+ var textLinesTool = new Tool({
80
+ name: "text_lines",
81
+ description: "Perform operations on text treated as a list of lines: sort, deduplicate, reverse, filter empty lines, trim each line, number each line, or count.",
82
+ inputSchema: validator.object({
83
+ text: validator.string().required().description("Multi-line text to process"),
84
+ operation: validator.string().valid("sort", "sort_desc", "reverse", "deduplicate", "filter_empty", "trim_each", "number", "count").required().description("Operation to apply to lines"),
85
+ case_insensitive: validator.boolean().default(false).description("For sort / deduplicate: ignore case (default: false)")
86
+ }),
87
+ handler: async (args) => {
88
+ const { text, operation, case_insensitive: ci } = args;
89
+ const lines = text.split("\n");
90
+ switch (operation) {
91
+ case "sort": return [...lines].sort((a, b) => (ci ? a.toLowerCase() : a).localeCompare(ci ? b.toLowerCase() : b)).join("\n");
92
+ case "sort_desc": return [...lines].sort((a, b) => (ci ? b.toLowerCase() : b).localeCompare(ci ? a.toLowerCase() : a)).join("\n");
93
+ case "reverse": return [...lines].reverse().join("\n");
94
+ case "deduplicate": {
95
+ const seen = /* @__PURE__ */ new Set();
96
+ return lines.filter((line) => {
97
+ const key = ci ? line.toLowerCase() : line;
98
+ if (seen.has(key)) return false;
99
+ seen.add(key);
100
+ return true;
101
+ }).join("\n");
102
+ }
103
+ case "filter_empty": return lines.filter((l) => l.trim() !== "").join("\n");
104
+ case "trim_each": return lines.map((l) => l.trim()).join("\n");
105
+ case "number": return lines.map((l, i) => `${i + 1}. ${l}`).join("\n");
106
+ case "count": {
107
+ const nonEmpty = lines.filter((l) => l.trim() !== "").length;
108
+ return `${lines.length} lines (${nonEmpty} non-empty, ${lines.length - nonEmpty} empty)`;
109
+ }
110
+ default: return `Error: Unknown operation "${operation}".`;
111
+ }
112
+ }
113
+ });
114
+ //#endregion
115
+ export { textAnalyzeTool, textLinesTool };
116
+
117
+ //# sourceMappingURL=text_analysis.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text_analysis.mjs","names":[],"sources":["../../../src/batteries/tools/text_analysis/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for extracting counts, token estimates, and character statistics from text.\n *\n * @module @nhtio/adk/batteries/tools/text_analysis\n *\n * @remarks\n * Pre-constructed bundled tools for the `text_analysis` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { validator } from '@nhtio/validation'\nimport { Tool, SpooledJsonArtifact } from '@nhtio/adk/common'\n\n/**\n * Analyze text and return statistics as a JSON document.\n *\n * @remarks\n * Reports character counts (with and without spaces), word/sentence/paragraph/line counts,\n * unique word count, average word length, a rough token estimate (4 chars/token), and a set\n * of character-class booleans (`is_all_alpha`, `is_all_ascii`, etc.).\n *\n * Output is JSON, so the artifact constructor is set to {@link @nhtio/adk!SpooledJsonArtifact} — consumer\n * code can read the result back as a parsed record without re-parsing.\n */\nexport const textAnalyzeTool = new Tool({\n name: 'text_analyze',\n description:\n 'Analyze text and return statistics: character counts, word/sentence/paragraph/line counts, unique word count, average word length, token estimate, and character-set properties.',\n inputSchema: validator.object({\n text: validator.string().required().description('The text to analyze'),\n }),\n artifactConstructor: () => SpooledJsonArtifact,\n handler: async (args) => {\n const { text } = args as { text: string }\n\n const charCount = text.length\n const charCountNoSpaces = text.replace(/\\s/g, '').length\n\n const words = text.trim() === '' ? [] : text.trim().split(/\\s+/)\n const wordCount = words.length\n\n const sentenceMatches = text.match(/[.!?]+(?:\\s|$)/g)\n const sentenceCount = sentenceMatches ? sentenceMatches.length : text.trim().length > 0 ? 1 : 0\n\n const paragraphs = text.split(/\\n[ \\t]*\\n/).filter((p) => p.trim().length > 0)\n const paragraphCount = paragraphs.length || (text.trim().length > 0 ? 1 : 0)\n\n const lineCount = text === '' ? 0 : text.split('\\n').length\n\n const tokenEstimate = Math.ceil(text.length / 4)\n\n const uniqueWords = new Set(\n words.map((w) => w.toLowerCase().replace(/[^a-z0-9]/g, '')).filter(Boolean)\n )\n const uniqueWordCount = uniqueWords.size\n\n const totalWordLen = words.reduce((sum, w) => sum + w.length, 0)\n const avgWordLength =\n wordCount > 0 ? Number.parseFloat((totalWordLen / wordCount).toFixed(2)) : 0\n\n const isAllAlpha = text.trim().length > 0 && /^[a-zA-Z\\s]*$/.test(text)\n const isAllNumeric = /^\\d+$/.test(text.trim())\n const isAllAlphanumeric = text.trim().length > 0 && /^[a-zA-Z0-9\\s]*$/.test(text)\n const isAllAscii = [...text].every((c) => c.charCodeAt(0) < 128)\n const isAllLowercase = text === text.toLowerCase() && /[a-z]/.test(text)\n const isAllUppercase = text === text.toUpperCase() && /[A-Z]/.test(text)\n\n return JSON.stringify(\n {\n char_count: charCount,\n char_count_no_spaces: charCountNoSpaces,\n word_count: wordCount,\n unique_word_count: uniqueWordCount,\n sentence_count: sentenceCount,\n paragraph_count: paragraphCount,\n line_count: lineCount,\n avg_word_length: avgWordLength,\n token_estimate: tokenEstimate,\n is_all_alpha: isAllAlpha,\n is_all_numeric: isAllNumeric,\n is_all_alphanumeric: isAllAlphanumeric,\n is_all_ascii: isAllAscii,\n is_all_lowercase: isAllLowercase,\n is_all_uppercase: isAllUppercase,\n has_unicode: !isAllAscii,\n },\n null,\n 2\n )\n },\n})\n\n/**\n * Operate on text treated as a list of lines.\n *\n * @remarks\n * Operations: `sort`, `sort_desc`, `reverse`, `deduplicate`, `filter_empty`, `trim_each`,\n * `number` (prefix each line with `1.`, `2.`, …), `count`. Sort and deduplicate respect the\n * optional `case_insensitive` flag.\n */\nexport const textLinesTool = new Tool({\n name: 'text_lines',\n description:\n 'Perform operations on text treated as a list of lines: sort, deduplicate, reverse, filter empty lines, trim each line, number each line, or count.',\n inputSchema: validator.object({\n text: validator.string().required().description('Multi-line text to process'),\n operation: validator\n .string()\n .valid(\n 'sort',\n 'sort_desc',\n 'reverse',\n 'deduplicate',\n 'filter_empty',\n 'trim_each',\n 'number',\n 'count'\n )\n .required()\n .description('Operation to apply to lines'),\n case_insensitive: validator\n .boolean()\n .default(false)\n .description('For sort / deduplicate: ignore case (default: false)'),\n }),\n handler: async (args) => {\n const {\n text,\n operation,\n case_insensitive: ci,\n } = args as {\n text: string\n operation: string\n case_insensitive: boolean\n }\n const lines = text.split('\\n')\n\n switch (operation) {\n case 'sort':\n return [...lines]\n .sort((a, b) => (ci ? a.toLowerCase() : a).localeCompare(ci ? b.toLowerCase() : b))\n .join('\\n')\n case 'sort_desc':\n return [...lines]\n .sort((a, b) => (ci ? b.toLowerCase() : b).localeCompare(ci ? a.toLowerCase() : a))\n .join('\\n')\n case 'reverse':\n return [...lines].reverse().join('\\n')\n case 'deduplicate': {\n const seen = new Set<string>()\n return lines\n .filter((line) => {\n const key = ci ? line.toLowerCase() : line\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n .join('\\n')\n }\n case 'filter_empty':\n return lines.filter((l) => l.trim() !== '').join('\\n')\n case 'trim_each':\n return lines.map((l) => l.trim()).join('\\n')\n case 'number':\n return lines.map((l, i) => `${i + 1}. ${l}`).join('\\n')\n case 'count': {\n const nonEmpty = lines.filter((l) => l.trim() !== '').length\n return `${lines.length} lines (${nonEmpty} non-empty, ${lines.length - nonEmpty} empty)`\n }\n default:\n return `Error: Unknown operation \"${operation}\".`\n }\n },\n})\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Pre-constructed tools for text diffs, similarity checks, and edit-distance comparisons.
3
+ *
4
+ * @module @nhtio/adk/batteries/tools/text_comparison
5
+ *
6
+ * @remarks
7
+ * Pre-constructed bundled tools for the `text_comparison` category. Import individually, the whole
8
+ * category, or import every tool via `@nhtio/adk/batteries`.
9
+ */
10
+ import { Tool } from "../../../common";
11
+ /**
12
+ * Compare two texts and emit a unified-style diff plus an additions/removals summary.
13
+ *
14
+ * @remarks
15
+ * `mode: 'lines'` (default) compares line-by-line; `mode: 'words'` compares word-by-word. The
16
+ * output is clipped at 60 diff lines — the suffix `… (N more lines truncated)` is appended if
17
+ * the diff is larger. Identical inputs short-circuit with `Texts are identical`.
18
+ */
19
+ export declare const textDiffTool: Tool<import("../../../common").SpooledArtifact>;
20
+ /**
21
+ * Report the Levenshtein edit distance and a similarity percentage between two strings.
22
+ *
23
+ * @remarks
24
+ * Useful for fuzzy matching. The percentage is `(1 - distance / max(len_a, len_b)) * 100`, with
25
+ * a human-readable label appended (`identical` / `very similar` / `similar` / `somewhat
26
+ * similar` / `different` / `very different`).
27
+ */
28
+ export declare const stringSimilarityTool: Tool<import("../../../common").SpooledArtifact>;
@@ -0,0 +1,96 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../chunk-KmRHZBOW.js");
3
+ require("../../common-Od8edUXU.js");
4
+ const require_tool = require("../../tool-COSeH8I6.js");
5
+ let _nhtio_validation = require("@nhtio/validation");
6
+ let diff = require("diff");
7
+ let fastest_levenshtein = require("fastest-levenshtein");
8
+ //#region src/batteries/tools/text_comparison/index.ts
9
+ /**
10
+ * Pre-constructed tools for text diffs, similarity checks, and edit-distance comparisons.
11
+ *
12
+ * @module @nhtio/adk/batteries/tools/text_comparison
13
+ *
14
+ * @remarks
15
+ * Pre-constructed bundled tools for the `text_comparison` category. Import individually, the whole
16
+ * category, or import every tool via `@nhtio/adk/batteries`.
17
+ */
18
+ /**
19
+ * Compare two texts and emit a unified-style diff plus an additions/removals summary.
20
+ *
21
+ * @remarks
22
+ * `mode: 'lines'` (default) compares line-by-line; `mode: 'words'` compares word-by-word. The
23
+ * output is clipped at 60 diff lines — the suffix `… (N more lines truncated)` is appended if
24
+ * the diff is larger. Identical inputs short-circuit with `Texts are identical`.
25
+ */
26
+ var textDiffTool = new require_tool.Tool({
27
+ name: "text_diff",
28
+ description: "Compare two texts and show what changed. Returns a summary of additions, deletions, and a unified-style diff.",
29
+ inputSchema: _nhtio_validation.validator.object({
30
+ text_a: _nhtio_validation.validator.string().required().allow("").description("Original text (before)"),
31
+ text_b: _nhtio_validation.validator.string().required().allow("").description("New text (after)"),
32
+ mode: _nhtio_validation.validator.string().valid("lines", "words").default("lines").description("Compare line-by-line or word-by-word (default: lines)")
33
+ }),
34
+ handler: async (args) => {
35
+ const { text_a: a, text_b: b, mode } = args;
36
+ if (a === b) return "Texts are identical — no differences found.";
37
+ const changes = mode === "words" ? (0, diff.diffWords)(a, b) : (0, diff.diffLines)(a, b);
38
+ let added = 0;
39
+ let removed = 0;
40
+ let unchanged = 0;
41
+ const diffOutput = [];
42
+ for (const part of changes) {
43
+ const unit = mode === "words" ? (part.value.match(/\S+/g) ?? []).length : part.count ?? 1;
44
+ if (part.added) {
45
+ added += unit;
46
+ for (const line of part.value.split("\n").filter((l) => l !== "" || mode === "words")) if (line !== "") diffOutput.push(`+ ${line}`);
47
+ } else if (part.removed) {
48
+ removed += unit;
49
+ for (const line of part.value.split("\n").filter((l) => l !== "" || mode === "words")) if (line !== "") diffOutput.push(`- ${line}`);
50
+ } else unchanged += unit;
51
+ }
52
+ const unit = mode === "lines" ? "line" : "word";
53
+ const summary = `+${added} ${unit}${added !== 1 ? "s" : ""} added, -${removed} ${unit}${removed !== 1 ? "s" : ""} removed, ${unchanged} unchanged`;
54
+ const MAX_DIFF_LINES = 60;
55
+ const truncated = diffOutput.length > MAX_DIFF_LINES ? `\n… (${diffOutput.length - MAX_DIFF_LINES} more lines truncated)` : "";
56
+ return [
57
+ summary,
58
+ "",
59
+ ...diffOutput.slice(0, MAX_DIFF_LINES)
60
+ ].join("\n") + truncated;
61
+ }
62
+ });
63
+ /**
64
+ * Report the Levenshtein edit distance and a similarity percentage between two strings.
65
+ *
66
+ * @remarks
67
+ * Useful for fuzzy matching. The percentage is `(1 - distance / max(len_a, len_b)) * 100`, with
68
+ * a human-readable label appended (`identical` / `very similar` / `similar` / `somewhat
69
+ * similar` / `different` / `very different`).
70
+ */
71
+ var stringSimilarityTool = new require_tool.Tool({
72
+ name: "string_similarity",
73
+ description: "Calculate edit distance and similarity percentage between two strings using Levenshtein distance. Useful for fuzzy matching.",
74
+ inputSchema: _nhtio_validation.validator.object({
75
+ a: _nhtio_validation.validator.string().required().allow("").description("First string"),
76
+ b: _nhtio_validation.validator.string().required().allow("").description("Second string"),
77
+ case_insensitive: _nhtio_validation.validator.boolean().default(false).description("Ignore case when comparing (default: false)")
78
+ }),
79
+ handler: async (args) => {
80
+ let { a, b } = args;
81
+ const { case_insensitive: ci } = args;
82
+ if (ci) {
83
+ a = a.toLowerCase();
84
+ b = b.toLowerCase();
85
+ }
86
+ const dist = (0, fastest_levenshtein.distance)(a, b);
87
+ const maxLen = Math.max(a.length, b.length);
88
+ const pct = maxLen === 0 ? 100 : Number.parseFloat(((1 - dist / maxLen) * 100).toFixed(1));
89
+ return `Edit distance: ${dist}\nSimilarity: ${pct}% (${pct === 100 ? "identical" : pct >= 90 ? "very similar" : pct >= 70 ? "similar" : pct >= 50 ? "somewhat similar" : pct >= 30 ? "different" : "very different"})`;
90
+ }
91
+ });
92
+ //#endregion
93
+ exports.stringSimilarityTool = stringSimilarityTool;
94
+ exports.textDiffTool = textDiffTool;
95
+
96
+ //# sourceMappingURL=text_comparison.cjs.map