@agentforge/tools 0.6.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -235,26 +235,18 @@ var extractImages = toolBuilder().name("extract-images").description("Extract al
235
235
  }).build();
236
236
  var urlValidator = toolBuilder().name("url-validator").description("Validate and parse URLs. Returns detailed information about the URL structure including protocol, hostname, path, query parameters, and hash.").category(ToolCategory.WEB).tags(["url", "validator", "parse", "validate"]).schema(z.object({
237
237
  url: z.string().describe("The URL to validate and parse")
238
- })).implement(async (input) => {
239
- try {
240
- const parsed = new URL(input.url);
241
- return {
242
- valid: true,
243
- url: parsed.href,
244
- protocol: parsed.protocol,
245
- hostname: parsed.hostname,
246
- port: parsed.port,
247
- pathname: parsed.pathname,
248
- search: parsed.search,
249
- hash: parsed.hash,
250
- origin: parsed.origin
251
- };
252
- } catch (error) {
253
- return {
254
- valid: false,
255
- error: error instanceof Error ? error.message : "Invalid URL"
256
- };
257
- }
238
+ })).implementSafe(async (input) => {
239
+ const parsed = new URL(input.url);
240
+ return {
241
+ url: parsed.href,
242
+ protocol: parsed.protocol,
243
+ hostname: parsed.hostname,
244
+ port: parsed.port,
245
+ pathname: parsed.pathname,
246
+ search: parsed.search,
247
+ hash: parsed.hash,
248
+ origin: parsed.origin
249
+ };
258
250
  }).build();
259
251
  var urlBuilder = toolBuilder().name("url-builder").description("Build a URL from components (protocol, hostname, path, query parameters, hash).").category(ToolCategory.WEB).tags(["url", "builder", "construct"]).schema(z.object({
260
252
  protocol: z.string().default("https").describe("Protocol (http, https, etc.)"),
@@ -667,89 +659,55 @@ var webSearch = toolBuilder().name("web-search").description(
667
659
  var jsonParser = toolBuilder().name("json-parser").description("Parse JSON string into an object. Validates JSON syntax and returns parsed data or error details.").category(ToolCategory.UTILITY).tags(["json", "parse", "data"]).schema(z.object({
668
660
  json: z.string().describe("JSON string to parse"),
669
661
  strict: z.boolean().default(true).describe("Use strict JSON parsing (no trailing commas, etc.)")
670
- })).implement(async (input) => {
671
- try {
672
- const parsed = JSON.parse(input.json);
673
- return {
674
- success: true,
675
- data: parsed,
676
- type: Array.isArray(parsed) ? "array" : typeof parsed
677
- };
678
- } catch (error) {
679
- return {
680
- success: false,
681
- error: error instanceof Error ? error.message : "Failed to parse JSON"
682
- };
683
- }
662
+ })).implementSafe(async (input) => {
663
+ const parsed = JSON.parse(input.json);
664
+ return {
665
+ data: parsed,
666
+ type: Array.isArray(parsed) ? "array" : typeof parsed
667
+ };
684
668
  }).build();
685
669
  var jsonStringify = toolBuilder().name("json-stringify").description("Convert an object to a JSON string with optional formatting (pretty print).").category(ToolCategory.UTILITY).tags(["json", "stringify", "format", "data"]).schema(z.object({
686
670
  data: z.any().describe("Data to convert to JSON string"),
687
671
  pretty: z.boolean().default(false).describe("Format with indentation for readability"),
688
672
  indent: z.number().default(2).describe("Number of spaces for indentation (when pretty is true)")
689
- })).implement(async (input) => {
690
- try {
691
- const json = input.pretty ? JSON.stringify(input.data, null, input.indent) : JSON.stringify(input.data);
692
- return {
693
- success: true,
694
- json,
695
- length: json.length
696
- };
697
- } catch (error) {
698
- return {
699
- success: false,
700
- error: error instanceof Error ? error.message : "Failed to stringify data"
701
- };
702
- }
673
+ })).implementSafe(async (input) => {
674
+ const json = input.pretty ? JSON.stringify(input.data, null, input.indent) : JSON.stringify(input.data);
675
+ return {
676
+ json,
677
+ length: json.length
678
+ };
703
679
  }).build();
704
680
  var jsonQuery = toolBuilder().name("json-query").description('Query JSON data using dot notation path (e.g., "user.address.city"). Supports array indexing.').category(ToolCategory.UTILITY).tags(["json", "query", "path", "data"]).schema(z.object({
705
681
  data: z.any().describe("JSON data to query"),
706
682
  path: z.string().describe('Dot notation path to query (e.g., "user.name" or "items[0].id")')
707
- })).implement(async (input) => {
708
- try {
709
- const parts = input.path.split(".");
710
- let current = input.data;
711
- for (const part of parts) {
712
- const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
713
- if (arrayMatch) {
714
- const [, key, index] = arrayMatch;
715
- current = current[key][parseInt(index, 10)];
716
- } else {
717
- current = current[part];
718
- }
719
- if (current === void 0) {
720
- return {
721
- success: false,
722
- error: `Path not found: ${input.path}`
723
- };
724
- }
683
+ })).implementSafe(async (input) => {
684
+ const parts = input.path.split(".");
685
+ let current = input.data;
686
+ for (const part of parts) {
687
+ const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
688
+ if (arrayMatch) {
689
+ const [, key, index] = arrayMatch;
690
+ current = current[key][parseInt(index, 10)];
691
+ } else {
692
+ current = current[part];
693
+ }
694
+ if (current === void 0) {
695
+ throw new Error(`Path not found: ${input.path}`);
725
696
  }
726
- return {
727
- success: true,
728
- value: current,
729
- type: Array.isArray(current) ? "array" : typeof current
730
- };
731
- } catch (error) {
732
- return {
733
- success: false,
734
- error: error instanceof Error ? error.message : "Failed to query JSON"
735
- };
736
697
  }
698
+ return {
699
+ value: current,
700
+ type: Array.isArray(current) ? "array" : typeof current
701
+ };
737
702
  }).build();
738
703
  var jsonValidator = toolBuilder().name("json-validator").description("Validate JSON string syntax without parsing. Returns whether the JSON is valid and any error details.").category(ToolCategory.UTILITY).tags(["json", "validate", "check", "data"]).schema(z.object({
739
704
  json: z.string().describe("JSON string to validate")
740
- })).implement(async (input) => {
741
- try {
742
- JSON.parse(input.json);
743
- return {
744
- valid: true,
745
- message: "Valid JSON"
746
- };
747
- } catch (error) {
748
- return {
749
- valid: false,
750
- error: error instanceof Error ? error.message : "Invalid JSON"
751
- };
752
- }
705
+ })).implementSafe(async (input) => {
706
+ JSON.parse(input.json);
707
+ return {
708
+ valid: true,
709
+ message: "Valid JSON"
710
+ };
753
711
  }).build();
754
712
  var jsonMerge = toolBuilder().name("json-merge").description("Merge two or more JSON objects. Later objects override earlier ones for conflicting keys.").category(ToolCategory.UTILITY).tags(["json", "merge", "combine", "data"]).schema(z.object({
755
713
  objects: z.array(z.any().describe("Object to merge")).describe("Array of objects to merge"),
@@ -1095,90 +1053,54 @@ var objectOmit = toolBuilder().name("object-omit").description("Create a new obj
1095
1053
  var fileReader = toolBuilder().name("file-reader").description("Read the contents of a file from the file system. Supports text and binary files with various encodings.").category(ToolCategory.FILE_SYSTEM).tags(["file", "read", "io", "filesystem"]).schema(z.object({
1096
1054
  path: z.string().describe("Path to the file to read"),
1097
1055
  encoding: z.enum(["utf8", "utf-8", "ascii", "base64", "hex", "binary"]).default("utf8").describe("File encoding")
1098
- })).implement(async (input) => {
1099
- try {
1100
- const content = await promises.readFile(input.path, input.encoding);
1101
- const stats = await promises.stat(input.path);
1102
- return {
1103
- success: true,
1104
- content,
1105
- size: stats.size,
1106
- path: input.path,
1107
- encoding: input.encoding
1108
- };
1109
- } catch (error) {
1110
- return {
1111
- success: false,
1112
- error: error instanceof Error ? error.message : "Failed to read file",
1113
- path: input.path
1114
- };
1115
- }
1056
+ })).implementSafe(async (input) => {
1057
+ const content = await promises.readFile(input.path, input.encoding);
1058
+ const stats = await promises.stat(input.path);
1059
+ return {
1060
+ content,
1061
+ size: stats.size,
1062
+ path: input.path,
1063
+ encoding: input.encoding
1064
+ };
1116
1065
  }).build();
1117
1066
  var fileWriter = toolBuilder().name("file-writer").description("Write content to a file. Creates the file if it doesn't exist, or overwrites it if it does.").category(ToolCategory.FILE_SYSTEM).tags(["file", "write", "io", "filesystem"]).schema(z.object({
1118
1067
  path: z.string().describe("Path to the file to write"),
1119
1068
  content: z.string().describe("Content to write to the file"),
1120
1069
  encoding: z.enum(["utf8", "utf-8", "ascii", "base64", "hex"]).default("utf8").describe("File encoding"),
1121
1070
  createDirs: z.boolean().default(false).describe("Create parent directories if they don't exist")
1122
- })).implement(async (input) => {
1123
- try {
1124
- if (input.createDirs) {
1125
- const dir = path3.dirname(input.path);
1126
- await promises.mkdir(dir, { recursive: true });
1127
- }
1128
- await promises.writeFile(input.path, input.content, input.encoding);
1129
- const stats = await promises.stat(input.path);
1130
- return {
1131
- success: true,
1132
- path: input.path,
1133
- size: stats.size,
1134
- encoding: input.encoding
1135
- };
1136
- } catch (error) {
1137
- return {
1138
- success: false,
1139
- error: error instanceof Error ? error.message : "Failed to write file",
1140
- path: input.path
1141
- };
1071
+ })).implementSafe(async (input) => {
1072
+ if (input.createDirs) {
1073
+ const dir = path3.dirname(input.path);
1074
+ await promises.mkdir(dir, { recursive: true });
1142
1075
  }
1076
+ await promises.writeFile(input.path, input.content, input.encoding);
1077
+ const stats = await promises.stat(input.path);
1078
+ return {
1079
+ path: input.path,
1080
+ size: stats.size,
1081
+ encoding: input.encoding
1082
+ };
1143
1083
  }).build();
1144
1084
  var fileAppend = toolBuilder().name("file-append").description("Append content to the end of a file. Creates the file if it doesn't exist.").category(ToolCategory.FILE_SYSTEM).tags(["file", "append", "io", "filesystem"]).schema(z.object({
1145
1085
  path: z.string().describe("Path to the file to append to"),
1146
1086
  content: z.string().describe("Content to append to the file"),
1147
1087
  encoding: z.enum(["utf8", "utf-8", "ascii"]).default("utf8").describe("File encoding")
1148
- })).implement(async (input) => {
1149
- try {
1150
- await promises.appendFile(input.path, input.content, input.encoding);
1151
- const stats = await promises.stat(input.path);
1152
- return {
1153
- success: true,
1154
- path: input.path,
1155
- size: stats.size
1156
- };
1157
- } catch (error) {
1158
- return {
1159
- success: false,
1160
- error: error instanceof Error ? error.message : "Failed to append to file",
1161
- path: input.path
1162
- };
1163
- }
1088
+ })).implementSafe(async (input) => {
1089
+ await promises.appendFile(input.path, input.content, input.encoding);
1090
+ const stats = await promises.stat(input.path);
1091
+ return {
1092
+ path: input.path,
1093
+ size: stats.size
1094
+ };
1164
1095
  }).build();
1165
1096
  var fileDelete = toolBuilder().name("file-delete").description("Delete a file from the file system. Returns an error if the file doesn't exist.").category(ToolCategory.FILE_SYSTEM).tags(["file", "delete", "remove", "filesystem"]).schema(z.object({
1166
1097
  path: z.string().describe("Path to the file to delete")
1167
- })).implement(async (input) => {
1168
- try {
1169
- await promises.unlink(input.path);
1170
- return {
1171
- success: true,
1172
- path: input.path,
1173
- message: "File deleted successfully"
1174
- };
1175
- } catch (error) {
1176
- return {
1177
- success: false,
1178
- error: error instanceof Error ? error.message : "Failed to delete file",
1179
- path: input.path
1180
- };
1181
- }
1098
+ })).implementSafe(async (input) => {
1099
+ await promises.unlink(input.path);
1100
+ return {
1101
+ path: input.path,
1102
+ message: "File deleted successfully"
1103
+ };
1182
1104
  }).build();
1183
1105
  var fileExists = toolBuilder().name("file-exists").description("Check if a file or directory exists at the specified path.").category(ToolCategory.FILE_SYSTEM).tags(["file", "exists", "check", "filesystem"]).schema(z.object({
1184
1106
  path: z.string().describe("Path to check")
@@ -1206,137 +1128,101 @@ var directoryList = toolBuilder().name("directory-list").description("List all f
1206
1128
  recursive: z.boolean().default(false).describe("List files recursively in subdirectories"),
1207
1129
  includeDetails: z.boolean().default(false).describe("Include file size, type, and modification date"),
1208
1130
  extension: z.string().optional().describe('Optional file extension filter (e.g., ".txt", ".js")')
1209
- })).implement(async (input) => {
1210
- try {
1211
- const listFiles = async (dir, recursive) => {
1212
- const entries = await promises.readdir(dir, { withFileTypes: true });
1213
- const files2 = [];
1214
- for (const entry of entries) {
1215
- const fullPath = path3.join(dir, entry.name);
1216
- const relativePath = path3.relative(input.path, fullPath);
1217
- if (input.extension && !entry.name.endsWith(input.extension)) {
1218
- if (!entry.isDirectory() || !recursive) {
1219
- continue;
1220
- }
1221
- }
1222
- if (input.includeDetails) {
1223
- const stats = await promises.stat(fullPath);
1224
- files2.push({
1225
- name: entry.name,
1226
- path: relativePath,
1227
- fullPath,
1228
- isFile: entry.isFile(),
1229
- isDirectory: entry.isDirectory(),
1230
- size: stats.size,
1231
- modified: stats.mtime.toISOString()
1232
- });
1233
- } else {
1234
- files2.push({
1235
- name: entry.name,
1236
- path: relativePath,
1237
- isFile: entry.isFile(),
1238
- isDirectory: entry.isDirectory()
1239
- });
1240
- }
1241
- if (recursive && entry.isDirectory()) {
1242
- const subFiles = await listFiles(fullPath, true);
1243
- files2.push(...subFiles);
1131
+ })).implementSafe(async (input) => {
1132
+ const listFiles = async (dir, recursive) => {
1133
+ const entries = await promises.readdir(dir, { withFileTypes: true });
1134
+ const files2 = [];
1135
+ for (const entry of entries) {
1136
+ const fullPath = path3.join(dir, entry.name);
1137
+ const relativePath = path3.relative(input.path, fullPath);
1138
+ if (input.extension && !entry.name.endsWith(input.extension)) {
1139
+ if (!entry.isDirectory() || !recursive) {
1140
+ continue;
1244
1141
  }
1245
1142
  }
1246
- return files2;
1247
- };
1248
- const files = await listFiles(input.path, input.recursive ?? false);
1249
- return {
1250
- success: true,
1251
- path: input.path,
1252
- files,
1253
- count: files.length
1254
- };
1255
- } catch (error) {
1256
- return {
1257
- success: false,
1258
- error: error instanceof Error ? error.message : "Failed to list directory",
1259
- path: input.path
1260
- };
1261
- }
1143
+ if (input.includeDetails) {
1144
+ const stats = await promises.stat(fullPath);
1145
+ files2.push({
1146
+ name: entry.name,
1147
+ path: relativePath,
1148
+ fullPath,
1149
+ isFile: entry.isFile(),
1150
+ isDirectory: entry.isDirectory(),
1151
+ size: stats.size,
1152
+ modified: stats.mtime.toISOString()
1153
+ });
1154
+ } else {
1155
+ files2.push({
1156
+ name: entry.name,
1157
+ path: relativePath,
1158
+ isFile: entry.isFile(),
1159
+ isDirectory: entry.isDirectory()
1160
+ });
1161
+ }
1162
+ if (recursive && entry.isDirectory()) {
1163
+ const subFiles = await listFiles(fullPath, true);
1164
+ files2.push(...subFiles);
1165
+ }
1166
+ }
1167
+ return files2;
1168
+ };
1169
+ const files = await listFiles(input.path, input.recursive ?? false);
1170
+ return {
1171
+ path: input.path,
1172
+ files,
1173
+ count: files.length
1174
+ };
1262
1175
  }).build();
1263
1176
  var directoryCreate = toolBuilder().name("directory-create").description("Create a new directory. Can optionally create parent directories if they don't exist.").category(ToolCategory.FILE_SYSTEM).tags(["directory", "create", "mkdir", "filesystem"]).schema(z.object({
1264
1177
  path: z.string().describe("Path to the directory to create"),
1265
1178
  recursive: z.boolean().default(true).describe("Create parent directories if they don't exist")
1266
- })).implement(async (input) => {
1267
- try {
1268
- await promises.mkdir(input.path, { recursive: input.recursive });
1269
- return {
1270
- success: true,
1271
- path: input.path,
1272
- message: "Directory created successfully"
1273
- };
1274
- } catch (error) {
1275
- return {
1276
- success: false,
1277
- error: error instanceof Error ? error.message : "Failed to create directory",
1278
- path: input.path
1279
- };
1280
- }
1179
+ })).implementSafe(async (input) => {
1180
+ await promises.mkdir(input.path, { recursive: input.recursive });
1181
+ return {
1182
+ path: input.path,
1183
+ message: "Directory created successfully"
1184
+ };
1281
1185
  }).build();
1282
1186
  var directoryDelete = toolBuilder().name("directory-delete").description("Delete a directory. Can optionally delete non-empty directories recursively.").category(ToolCategory.FILE_SYSTEM).tags(["directory", "delete", "remove", "filesystem"]).schema(z.object({
1283
1187
  path: z.string().describe("Path to the directory to delete"),
1284
1188
  recursive: z.boolean().default(false).describe("Delete directory and all its contents")
1285
- })).implement(async (input) => {
1286
- try {
1287
- await promises.rm(input.path, { recursive: input.recursive, force: false });
1288
- return {
1289
- success: true,
1290
- path: input.path,
1291
- message: "Directory deleted successfully"
1292
- };
1293
- } catch (error) {
1294
- return {
1295
- success: false,
1296
- error: error instanceof Error ? error.message : "Failed to delete directory",
1297
- path: input.path
1298
- };
1299
- }
1189
+ })).implementSafe(async (input) => {
1190
+ await promises.rm(input.path, { recursive: input.recursive, force: false });
1191
+ return {
1192
+ path: input.path,
1193
+ message: "Directory deleted successfully"
1194
+ };
1300
1195
  }).build();
1301
1196
  var fileSearch = toolBuilder().name("file-search").description("Search for files by name pattern in a directory. Supports wildcards and recursive search.").category(ToolCategory.FILE_SYSTEM).tags(["file", "search", "find", "filesystem"]).schema(z.object({
1302
1197
  directory: z.string().describe("Directory to search in"),
1303
1198
  pattern: z.string().describe("File name pattern to search for (supports * wildcard)"),
1304
1199
  recursive: z.boolean().default(true).describe("Search in subdirectories"),
1305
1200
  caseSensitive: z.boolean().default(false).describe("Case-sensitive pattern matching")
1306
- })).implement(async (input) => {
1307
- try {
1308
- const searchFiles = async (dir) => {
1309
- const entries = await promises.readdir(dir, { withFileTypes: true });
1310
- const matches2 = [];
1311
- const regexPattern = input.pattern.replace(/\./g, "\\.").replace(/\*/g, ".*");
1312
- const regex = new RegExp(`^${regexPattern}$`, input.caseSensitive ? "" : "i");
1313
- for (const entry of entries) {
1314
- const fullPath = path3.join(dir, entry.name);
1315
- if (entry.isFile() && regex.test(entry.name)) {
1316
- matches2.push(fullPath);
1317
- }
1318
- if (input.recursive && entry.isDirectory()) {
1319
- const subMatches = await searchFiles(fullPath);
1320
- matches2.push(...subMatches);
1321
- }
1201
+ })).implementSafe(async (input) => {
1202
+ const searchFiles = async (dir) => {
1203
+ const entries = await promises.readdir(dir, { withFileTypes: true });
1204
+ const matches2 = [];
1205
+ const regexPattern = input.pattern.replace(/\./g, "\\.").replace(/\*/g, ".*");
1206
+ const regex = new RegExp(`^${regexPattern}$`, input.caseSensitive ? "" : "i");
1207
+ for (const entry of entries) {
1208
+ const fullPath = path3.join(dir, entry.name);
1209
+ if (entry.isFile() && regex.test(entry.name)) {
1210
+ matches2.push(fullPath);
1322
1211
  }
1323
- return matches2;
1324
- };
1325
- const matches = await searchFiles(input.directory);
1326
- return {
1327
- success: true,
1328
- directory: input.directory,
1329
- pattern: input.pattern,
1330
- matches,
1331
- count: matches.length
1332
- };
1333
- } catch (error) {
1334
- return {
1335
- success: false,
1336
- error: error instanceof Error ? error.message : "Failed to search files",
1337
- directory: input.directory
1338
- };
1339
- }
1212
+ if (input.recursive && entry.isDirectory()) {
1213
+ const subMatches = await searchFiles(fullPath);
1214
+ matches2.push(...subMatches);
1215
+ }
1216
+ }
1217
+ return matches2;
1218
+ };
1219
+ const matches = await searchFiles(input.directory);
1220
+ return {
1221
+ directory: input.directory,
1222
+ pattern: input.pattern,
1223
+ matches,
1224
+ count: matches.length
1225
+ };
1340
1226
  }).build();
1341
1227
  var pathJoin = toolBuilder().name("path-join").description("Join multiple path segments into a single path. Handles platform-specific separators.").category(ToolCategory.FILE_SYSTEM).tags(["path", "join", "filesystem"]).schema(z.object({
1342
1228
  segments: z.array(z.string().describe("String value")).describe("Path segments to join")