@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.
- package/LICENSE.md +9 -0
- package/README.md +3 -0
- package/batteries/index.d.ts +28 -0
- package/batteries/llm/index.d.ts +11 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs +916 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/adapter.d.ts +101 -0
- package/batteries/llm/openai_chat_completions/adapter.mjs +914 -0
- package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/exceptions.cjs +89 -0
- package/batteries/llm/openai_chat_completions/exceptions.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/exceptions.d.ts +97 -0
- package/batteries/llm/openai_chat_completions/exceptions.mjs +81 -0
- package/batteries/llm/openai_chat_completions/exceptions.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/helpers.cjs +819 -0
- package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/helpers.d.ts +233 -0
- package/batteries/llm/openai_chat_completions/helpers.mjs +783 -0
- package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/index.d.ts +27 -0
- package/batteries/llm/openai_chat_completions/types.cjs +1 -0
- package/batteries/llm/openai_chat_completions/types.d.ts +524 -0
- package/batteries/llm/openai_chat_completions/types.mjs +0 -0
- package/batteries/llm/openai_chat_completions/validation.cjs +190 -0
- package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/validation.d.ts +31 -0
- package/batteries/llm/openai_chat_completions/validation.mjs +187 -0
- package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions.cjs +51 -0
- package/batteries/llm/openai_chat_completions.mjs +5 -0
- package/batteries/llm/webllm_chat_completions/adapter.cjs +658 -0
- package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/adapter.d.ts +103 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs +656 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/exceptions.cjs +70 -0
- package/batteries/llm/webllm_chat_completions/exceptions.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/exceptions.d.ts +74 -0
- package/batteries/llm/webllm_chat_completions/exceptions.mjs +65 -0
- package/batteries/llm/webllm_chat_completions/exceptions.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/helpers.cjs +38 -0
- package/batteries/llm/webllm_chat_completions/helpers.d.ts +6 -0
- package/batteries/llm/webllm_chat_completions/helpers.mjs +2 -0
- package/batteries/llm/webllm_chat_completions/index.d.ts +25 -0
- package/batteries/llm/webllm_chat_completions/types.d.ts +31 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs +115 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/validation.d.ts +8 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs +112 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions.cjs +50 -0
- package/batteries/llm/webllm_chat_completions.mjs +6 -0
- package/batteries/llm.cjs +63 -0
- package/batteries/llm.mjs +10 -0
- package/batteries/storage/flydrive/index.d.ts +167 -0
- package/batteries/storage/flydrive.cjs +249 -0
- package/batteries/storage/flydrive.cjs.map +1 -0
- package/batteries/storage/flydrive.mjs +249 -0
- package/batteries/storage/flydrive.mjs.map +1 -0
- package/batteries/storage/in_memory/index.d.ts +106 -0
- package/batteries/storage/in_memory.cjs +121 -0
- package/batteries/storage/in_memory.cjs.map +1 -0
- package/batteries/storage/in_memory.mjs +119 -0
- package/batteries/storage/in_memory.mjs.map +1 -0
- package/batteries/storage/index.d.ts +18 -0
- package/batteries/storage/opfs/index.d.ts +299 -0
- package/batteries/storage/opfs.cjs +368 -0
- package/batteries/storage/opfs.cjs.map +1 -0
- package/batteries/storage/opfs.mjs +366 -0
- package/batteries/storage/opfs.mjs.map +1 -0
- package/batteries/storage.cjs +4 -0
- package/batteries/storage.mjs +2 -0
- package/batteries/tools/color/index.d.ts +37 -0
- package/batteries/tools/color.cjs +659 -0
- package/batteries/tools/color.cjs.map +1 -0
- package/batteries/tools/color.mjs +655 -0
- package/batteries/tools/color.mjs.map +1 -0
- package/batteries/tools/comparison/index.d.ts +29 -0
- package/batteries/tools/comparison.cjs +171 -0
- package/batteries/tools/comparison.cjs.map +1 -0
- package/batteries/tools/comparison.mjs +168 -0
- package/batteries/tools/comparison.mjs.map +1 -0
- package/batteries/tools/data_structure/index.d.ts +30 -0
- package/batteries/tools/data_structure.cjs +270 -0
- package/batteries/tools/data_structure.cjs.map +1 -0
- package/batteries/tools/data_structure.mjs +267 -0
- package/batteries/tools/data_structure.mjs.map +1 -0
- package/batteries/tools/datetime_extended/index.d.ts +51 -0
- package/batteries/tools/datetime_extended.cjs +309 -0
- package/batteries/tools/datetime_extended.cjs.map +1 -0
- package/batteries/tools/datetime_extended.mjs +302 -0
- package/batteries/tools/datetime_extended.mjs.map +1 -0
- package/batteries/tools/datetime_math/index.d.ts +36 -0
- package/batteries/tools/datetime_math.cjs +175 -0
- package/batteries/tools/datetime_math.cjs.map +1 -0
- package/batteries/tools/datetime_math.mjs +171 -0
- package/batteries/tools/datetime_math.mjs.map +1 -0
- package/batteries/tools/encoding/index.d.ts +36 -0
- package/batteries/tools/encoding.cjs +156 -0
- package/batteries/tools/encoding.cjs.map +1 -0
- package/batteries/tools/encoding.mjs +152 -0
- package/batteries/tools/encoding.mjs.map +1 -0
- package/batteries/tools/formatting/index.d.ts +28 -0
- package/batteries/tools/formatting.cjs +120 -0
- package/batteries/tools/formatting.cjs.map +1 -0
- package/batteries/tools/formatting.mjs +117 -0
- package/batteries/tools/formatting.mjs.map +1 -0
- package/batteries/tools/geo_basics/index.d.ts +33 -0
- package/batteries/tools/geo_basics.cjs +136 -0
- package/batteries/tools/geo_basics.cjs.map +1 -0
- package/batteries/tools/geo_basics.mjs +132 -0
- package/batteries/tools/geo_basics.mjs.map +1 -0
- package/batteries/tools/index.d.ts +32 -0
- package/batteries/tools/math/index.d.ts +37 -0
- package/batteries/tools/math.cjs +136 -0
- package/batteries/tools/math.cjs.map +1 -0
- package/batteries/tools/math.mjs +133 -0
- package/batteries/tools/math.mjs.map +1 -0
- package/batteries/tools/memory/index.d.ts +73 -0
- package/batteries/tools/memory.cjs +193 -0
- package/batteries/tools/memory.cjs.map +1 -0
- package/batteries/tools/memory.mjs +187 -0
- package/batteries/tools/memory.mjs.map +1 -0
- package/batteries/tools/parsing/index.d.ts +47 -0
- package/batteries/tools/parsing.cjs +191 -0
- package/batteries/tools/parsing.cjs.map +1 -0
- package/batteries/tools/parsing.mjs +185 -0
- package/batteries/tools/parsing.mjs.map +1 -0
- package/batteries/tools/retrievables/index.d.ts +81 -0
- package/batteries/tools/retrievables.cjs +215 -0
- package/batteries/tools/retrievables.cjs.map +1 -0
- package/batteries/tools/retrievables.mjs +209 -0
- package/batteries/tools/retrievables.mjs.map +1 -0
- package/batteries/tools/standing_instructions/index.d.ts +64 -0
- package/batteries/tools/standing_instructions.cjs +126 -0
- package/batteries/tools/standing_instructions.cjs.map +1 -0
- package/batteries/tools/standing_instructions.mjs +121 -0
- package/batteries/tools/standing_instructions.mjs.map +1 -0
- package/batteries/tools/statistics/index.d.ts +46 -0
- package/batteries/tools/statistics.cjs +253 -0
- package/batteries/tools/statistics.cjs.map +1 -0
- package/batteries/tools/statistics.mjs +248 -0
- package/batteries/tools/statistics.mjs.map +1 -0
- package/batteries/tools/string_processing/index.d.ts +29 -0
- package/batteries/tools/string_processing.cjs +154 -0
- package/batteries/tools/string_processing.cjs.map +1 -0
- package/batteries/tools/string_processing.mjs +151 -0
- package/batteries/tools/string_processing.mjs.map +1 -0
- package/batteries/tools/structured_data/index.d.ts +34 -0
- package/batteries/tools/structured_data.cjs +189 -0
- package/batteries/tools/structured_data.cjs.map +1 -0
- package/batteries/tools/structured_data.mjs +185 -0
- package/batteries/tools/structured_data.mjs.map +1 -0
- package/batteries/tools/text_analysis/index.d.ts +31 -0
- package/batteries/tools/text_analysis.cjs +120 -0
- package/batteries/tools/text_analysis.cjs.map +1 -0
- package/batteries/tools/text_analysis.mjs +117 -0
- package/batteries/tools/text_analysis.mjs.map +1 -0
- package/batteries/tools/text_comparison/index.d.ts +28 -0
- package/batteries/tools/text_comparison.cjs +96 -0
- package/batteries/tools/text_comparison.cjs.map +1 -0
- package/batteries/tools/text_comparison.mjs +93 -0
- package/batteries/tools/text_comparison.mjs.map +1 -0
- package/batteries/tools/time/index.d.ts +27 -0
- package/batteries/tools/time.cjs +63 -0
- package/batteries/tools/time.cjs.map +1 -0
- package/batteries/tools/time.mjs +60 -0
- package/batteries/tools/time.mjs.map +1 -0
- package/batteries/tools/unit_conversion/index.d.ts +19 -0
- package/batteries/tools/unit_conversion.cjs +452 -0
- package/batteries/tools/unit_conversion.cjs.map +1 -0
- package/batteries/tools/unit_conversion.mjs +450 -0
- package/batteries/tools/unit_conversion.mjs.map +1 -0
- package/batteries/tools.cjs +80 -0
- package/batteries/tools.mjs +21 -0
- package/batteries.cjs +142 -0
- package/batteries.mjs +30 -0
- package/chunk-KmRHZBOW.js +35 -0
- package/common-DeZaonK1.mjs +208 -0
- package/common-DeZaonK1.mjs.map +1 -0
- package/common-Od8edUXU.js +232 -0
- package/common-Od8edUXU.js.map +1 -0
- package/common.cjs +31 -0
- package/common.d.ts +108 -0
- package/common.mjs +8 -0
- package/dispatch_runner-9j6bXHL3.mjs +1609 -0
- package/dispatch_runner-9j6bXHL3.mjs.map +1 -0
- package/dispatch_runner-CsoH0nld.js +1627 -0
- package/dispatch_runner-CsoH0nld.js.map +1 -0
- package/dispatch_runner.cjs +3 -0
- package/dispatch_runner.d.ts +17 -0
- package/dispatch_runner.mjs +2 -0
- package/exceptions-D5YrO9Vm.js +280 -0
- package/exceptions-D5YrO9Vm.js.map +1 -0
- package/exceptions-NrzIHw_R.mjs +244 -0
- package/exceptions-NrzIHw_R.mjs.map +1 -0
- package/exceptions.cjs +33 -0
- package/exceptions.d.ts +52 -0
- package/exceptions.mjs +3 -0
- package/factories.cjs +4 -0
- package/factories.d.ts +39 -0
- package/factories.mjs +2 -0
- package/forge.cjs +9 -0
- package/forge.d.ts +49 -0
- package/forge.mjs +5 -0
- package/guards.cjs +96 -0
- package/guards.cjs.map +1 -0
- package/guards.d.ts +83 -0
- package/guards.mjs +72 -0
- package/guards.mjs.map +1 -0
- package/index.cjs +107 -0
- package/index.cjs.map +1 -0
- package/index.d.ts +18 -0
- package/index.mjs +31 -0
- package/index.mjs.map +1 -0
- package/lib/classes/artifact_tool.d.ts +129 -0
- package/lib/classes/base_exception.d.ts +83 -0
- package/lib/classes/identity.d.ts +71 -0
- package/lib/classes/media.d.ts +326 -0
- package/lib/classes/memory.d.ts +72 -0
- package/lib/classes/message.d.ts +137 -0
- package/lib/classes/registry.d.ts +79 -0
- package/lib/classes/retrievable.d.ts +100 -0
- package/lib/classes/spooled_artifact.d.ts +296 -0
- package/lib/classes/spooled_json_artifact.d.ts +158 -0
- package/lib/classes/spooled_markdown_artifact.d.ts +202 -0
- package/lib/classes/thought.d.ts +142 -0
- package/lib/classes/tokenizable.d.ts +124 -0
- package/lib/classes/tool.d.ts +228 -0
- package/lib/classes/tool_call.d.ts +190 -0
- package/lib/classes/tool_registry.d.ts +159 -0
- package/lib/classes/turn_gate.d.ts +109 -0
- package/lib/contracts/dispatch_context.d.ts +345 -0
- package/lib/contracts/media_reader.d.ts +60 -0
- package/lib/contracts/spool_reader.d.ts +80 -0
- package/lib/contracts/spooled_artifact_constructor.d.ts +38 -0
- package/lib/contracts/turn_runner_config.d.ts +101 -0
- package/lib/contracts/turn_runner_context.d.ts +267 -0
- package/lib/dispatch_runner.d.ts +98 -0
- package/lib/exceptions/runtime.d.ts +370 -0
- package/lib/helpers/media_readers.d.ts +39 -0
- package/lib/turn_runner.d.ts +144 -0
- package/lib/types/dispatch_context.d.ts +233 -0
- package/lib/types/dispatch_runner.d.ts +387 -0
- package/lib/types/turn_runner.d.ts +322 -0
- package/lib/utils/canonical_json.d.ts +18 -0
- package/lib/utils/exceptions.d.ts +78 -0
- package/lib/utils/guards.d.ts +32 -0
- package/lib/utils/validation.d.ts +77 -0
- package/package.json +334 -0
- package/runtime-BJVkrGQe.js +519 -0
- package/runtime-BJVkrGQe.js.map +1 -0
- package/runtime-CrEPIFgr.mjs +346 -0
- package/runtime-CrEPIFgr.mjs.map +1 -0
- package/skills/adk-assembly/SKILL.md +109 -0
- package/skills/adk-assembly/references/assembly-contract.md +66 -0
- package/skills/adk-assembly/references/executors-tools-pipelines-events.md +113 -0
- package/skills/adk-assembly/references/first-integration.md +93 -0
- package/skills/adk-assembly/references/storage-and-context.md +102 -0
- package/spooled_artifact-C5ZtGxuJ.mjs +544 -0
- package/spooled_artifact-C5ZtGxuJ.mjs.map +1 -0
- package/spooled_artifact-Cm9Te22K.js +568 -0
- package/spooled_artifact-Cm9Te22K.js.map +1 -0
- package/spooled_artifact.cjs +7 -0
- package/spooled_artifact.d.ts +40 -0
- package/spooled_artifact.mjs +3 -0
- package/spooled_markdown_artifact-BpUJol0W.mjs +771 -0
- package/spooled_markdown_artifact-BpUJol0W.mjs.map +1 -0
- package/spooled_markdown_artifact-RRB113sy.js +786 -0
- package/spooled_markdown_artifact-RRB113sy.js.map +1 -0
- package/thought-CDb457b4.mjs +470 -0
- package/thought-CDb457b4.mjs.map +1 -0
- package/thought-DuN2PgdO.js +494 -0
- package/thought-DuN2PgdO.js.map +1 -0
- package/tool-COSeH8I6.js +302 -0
- package/tool-COSeH8I6.js.map +1 -0
- package/tool-D2WB1EA1.mjs +296 -0
- package/tool-D2WB1EA1.mjs.map +1 -0
- package/tool_call-BKyyxGaZ.mjs +578 -0
- package/tool_call-BKyyxGaZ.mjs.map +1 -0
- package/tool_call-DFgzcVcU.js +608 -0
- package/tool_call-DFgzcVcU.js.map +1 -0
- package/tool_registry-Dkfprsck.js +641 -0
- package/tool_registry-Dkfprsck.js.map +1 -0
- package/tool_registry-DqLOyGyG.mjs +592 -0
- package/tool_registry-DqLOyGyG.mjs.map +1 -0
- package/turn_runner-CMm2BHdX.js +615 -0
- package/turn_runner-CMm2BHdX.js.map +1 -0
- package/turn_runner-y7eyEcJH.mjs +603 -0
- package/turn_runner-y7eyEcJH.mjs.map +1 -0
- package/turn_runner.cjs +3 -0
- package/turn_runner.d.ts +21 -0
- package/turn_runner.mjs +2 -0
- package/types.cjs +1 -0
- package/types.d.ts +56 -0
- package/types.mjs +0 -0
- 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":";;;;;;;;;;;;;;;AAcA,SAAS,UAAU,OAAwB;CACzC,MAAM,MAAM,UAAU,QAAQ,UAAU,KAAA,IAAY,KAAK,OAAO,KAAK;CACrE,IAAI,IAAI,SAAS,GAAG,KAAK,IAAI,SAAS,IAAG,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,IAAI,GACnF,OAAO,OAAM,IAAI,QAAQ,MAAM,MAAI,IAAI;CAEzC,OAAO;AACT;AAEA,SAAS,UAAU,OAAwB;CAEzC,QADY,UAAU,QAAQ,UAAU,KAAA,IAAY,KAAK,OAAO,KAAK,GAC1D,QAAQ,OAAO,GAAG,EAAE,QAAQ,UAAU,GAAG;AACtD;AAEA,SAAS,SAAS,OAAwB;CACxC,OAAO,OAAO,UAAU,QAAQ,UAAU,KAAA,IAAY,KAAK,KAAK,EAC7D,QAAQ,OAAO,KAAK,EACpB,QAAQ,UAAU,GAAG;AAC1B;;;;;;;;AASA,IAAa,kBAAkB,IAAI,KAAK;CACtC,MAAM;CACN,aACE;CACF,aAAa,UAAU,OAAO;EAC5B,MAAM,UAAU,OAAO,EAAE,SAAS,EAAE,YAAY,mCAAmC;EACnF,QAAQ,UACL,OAAO,EACP,MAAM,YAAY,OAAO,KAAK,EAC9B,SAAS,EACT,YAAY,eAAe;EAC9B,SAAS,UACN,MAAM,EACN,MAAM,UAAU,OAAO,CAAC,EACxB,SAAS,EACT,YACC,qFACF;CACJ,CAAC;CACD,SAAS,OAAO,SAAS;EACvB,MAAM,EACJ,MACA,QACA,SAAS,oBACP;EAMJ,IAAI;EACJ,IAAI;GACF,OAAO,KAAK,MAAM,IAAI;EACxB,QAAQ;GACN,OAAO;EACT;EAEA,IAAI,CAAC,MAAM,QAAQ,IAAI,GAAG,OAAO;EACjC,IAAI,KAAK,WAAW,GAAG,OAAO;EAE9B,MAAM,UAAU,mBAAmB,OAAO,KAAK,KAAK,EAA6B;EAEjF,IAAI,WAAW,OAAO;GACpB,MAAM,QAAQ,CAAC,QAAQ,IAAI,SAAS,EAAE,KAAK,GAAG,CAAC;GAC/C,KAAK,MAAM,OAAO,MAAM;IACtB,MAAM,MAAM;IACZ,MAAM,KAAK,QAAQ,KAAK,QAAQ,UAAU,IAAI,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC;GAChE;GACA,OAAO,MAAM,KAAK,IAAI;EACxB;EAEA,IAAI,WAAW,OAAO;GACpB,MAAM,QAAQ,CAAC,QAAQ,IAAI,SAAS,EAAE,KAAK,GAAI,CAAC;GAChD,KAAK,MAAM,OAAO,MAAM;IACtB,MAAM,MAAM;IACZ,MAAM,KAAK,QAAQ,KAAK,QAAQ,UAAU,IAAI,IAAI,CAAC,EAAE,KAAK,GAAI,CAAC;GACjE;GACA,OAAO,MAAM,KAAK,IAAI;EACxB;EAQA,OAAO;GANQ,OAAO,QAAQ,IAAI,QAAQ,EAAE,KAAK,KAAK,IAAI;GACxC,OAAO,QAAQ,UAAU,KAAK,EAAE,KAAK,KAAK,IAAI;GAKrC,GAJV,KAAK,KAAK,QAAQ;IACjC,MAAM,MAAM;IACZ,OAAO,OAAO,QAAQ,KAAK,QAAQ,SAAS,IAAI,IAAI,CAAC,EAAE,KAAK,KAAK,IAAI;GACvE,CAC8B;EAAQ,EAAE,KAAK,IAAI;CACnD;AACF,CAAC;;;;;;;;AASD,IAAa,iBAAiB,IAAI,KAAK;CACrC,MAAM;CACN,aAAa;CACb,aAAa,UAAU,OAAO;EAC5B,MAAM,UAAU,OAAO,EAAE,SAAS,EAAE,YAAY,uBAAuB;EACvE,QAAQ,UACL,OAAO,EACP,QAAQ,CAAC,EACT,YAAY,sDAAsD;CACvE,CAAC;CACD,SAAS,OAAO,SAAS;EACvB,MAAM,EAAE,MAAM,WAAW;EACzB,IAAI;GACF,MAAM,SAAS,KAAK,MAAM,IAAI;GAC9B,OAAO,KAAK,UAAU,QAAQ,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,CAAC,CAAC,CAAC;EAClF,SAAS,KAAK;GACZ,OAAO,yBAAyB,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG;EACzE;CACF;AACF,CAAC;AAED,IAAM,kBAAsE;CAC1E,OAAO;EACL,SAAS;EACT,OAAO;CACT;CACA,MAAM;EACJ,SAAS;EACT,OAAO;CACT;CACA,MAAM;EACJ,SAAS;EACT,OAAO;CACT;CACA,UAAU;EACR,SAAS;EACT,OAAO;CACT;CACA,cAAc;EACZ,SAAS;EACT,OAAO;CACT;CACA,WAAW;EACT,SAAS;EACT,OAAO;CACT;CACA,YAAY;EACV,SAAS;EACT,OAAO;CACT;CACA,QAAQ;EACN,SAAS;EACT,OAAO;CACT;CACA,SAAS;EACP,SAAS;EACT,OAAO;CACT;CACA,SAAS;EACP,SAAS;EACT,OAAO;CACT;CACA,cAAc;EACZ,SAAS;EACT,OAAO;CACT;CACA,MAAM;EACJ,SAAS;EACT,OAAO;CACT;CACA,KAAK;EACH,SAAS;EACT,OAAO;CACT;CACA,QAAQ;EACN,SAAS;EACT,OAAO;CACT;AACF;;;;;;;;AASA,IAAa,qBAAqB,IAAI,KAAK;CACzC,MAAM;CACN,aACE;CACF,aAAa,UAAU,OAAO;EAC5B,OAAO,UAAU,OAAO,EAAE,SAAS,EAAE,YAAY,wBAAwB;EACzE,QAAQ,UACL,OAAO,EACP,MAAM,GAAG,OAAO,KAAK,eAAe,CAAC,EACrC,SAAS,EACT,YACC,uCAAuC,OAAO,KAAK,eAAe,EAAE,KAAK,IAAI,GAC/E;CACJ,CAAC;CACD,SAAS,OAAO,SAAS;EACvB,MAAM,EAAE,OAAO,WAAW;EAC1B,MAAM,MAAM,gBAAgB;EAC5B,IAAI,CAAC,KACH,OAAO,0BAA0B,OAAO,gBAAgB,OAAO,KAAK,eAAe,EAAE,KAAK,IAAI;EAGhG,OADc,IAAI,QAAQ,KAAK,KACxB,IACH,WAAW,MAAM,eAAe,IAAI,MAAM,KAC1C,aAAa,MAAM,mBAAmB,IAAI,MAAM;CACtD;AACF,CAAC"}
|
|
@@ -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
|