@agentforge/tools 0.9.1 → 0.10.1

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
@@ -1,17 +1,17 @@
1
1
  import { toolBuilder, ToolCategory, LogLevel, createLogger } from '@agentforge/core';
2
+ import axios12 from 'axios';
2
3
  import { z } from 'zod';
3
- import axios from 'axios';
4
- import * as cheerio2 from 'cheerio';
4
+ import * as cheerio from 'cheerio';
5
5
  import { WebClient } from '@slack/web-api';
6
6
  import { parse } from 'csv-parse/sync';
7
7
  import { stringify } from 'csv-stringify/sync';
8
8
  import { XMLParser, XMLBuilder } from 'fast-xml-parser';
9
9
  import { promises } from 'fs';
10
- import * as path3 from 'path';
10
+ import * as path7 from 'path';
11
11
  import { format, parse as parse$1, isValid, add, sub, differenceInDays, differenceInHours, differenceInMinutes, isAfter, isBefore } from 'date-fns';
12
12
  import { randomUUID } from 'crypto';
13
13
 
14
- // src/web/http-client.ts
14
+ // src/web/http/tools/http-client.ts
15
15
  var HttpMethod = z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]);
16
16
  var httpRequestSchema = z.object({
17
17
  url: z.string().url().describe("The URL to make the request to"),
@@ -21,54 +21,79 @@ var httpRequestSchema = z.object({
21
21
  timeout: z.number().default(3e4).describe("Request timeout in milliseconds"),
22
22
  params: z.record(z.string()).optional().describe("Optional URL query parameters")
23
23
  });
24
- var httpClient = toolBuilder().name("http-client").description("Make HTTP requests to web APIs and services. Supports GET, POST, PUT, DELETE, PATCH methods with custom headers and body.").category(ToolCategory.WEB).tags(["http", "api", "request", "web"]).schema(httpRequestSchema).implement(async (input) => {
25
- const config = {
26
- method: input.method,
27
- url: input.url,
28
- headers: input.headers,
29
- data: input.body,
30
- timeout: input.timeout,
31
- params: input.params,
32
- validateStatus: () => true
33
- // Don't throw on any status code
34
- };
35
- const response = await axios(config);
36
- return {
37
- status: response.status,
38
- statusText: response.statusText,
39
- headers: response.headers,
40
- data: response.data,
41
- url: input.url,
42
- method: input.method ?? "GET"
43
- };
44
- }).build();
45
- var httpGet = toolBuilder().name("http-get").description("Make a simple HTTP GET request to a URL and return the response data.").category(ToolCategory.WEB).tags(["http", "get", "fetch", "web"]).schema(z.object({
24
+ var httpGetSchema = z.object({
46
25
  url: z.string().url().describe("The URL to fetch"),
47
26
  headers: z.record(z.string()).optional().describe("Optional HTTP headers"),
48
27
  params: z.record(z.string()).optional().describe("Optional URL query parameters")
49
- })).implement(async (input) => {
50
- const response = await axios.get(input.url, {
51
- headers: input.headers,
52
- params: input.params,
53
- timeout: 3e4
54
- });
55
- return response.data;
56
- }).build();
57
- var httpPost = toolBuilder().name("http-post").description("Make a simple HTTP POST request with JSON body and return the response data.").category(ToolCategory.WEB).tags(["http", "post", "api", "web"]).schema(z.object({
28
+ });
29
+ var httpPostSchema = z.object({
58
30
  url: z.string().url().describe("The URL to post to"),
59
31
  body: z.any().describe("The request body (will be sent as JSON)"),
60
32
  headers: z.record(z.string()).optional().describe("Optional HTTP headers")
61
- })).implement(async (input) => {
62
- const response = await axios.post(input.url, input.body, {
63
- headers: {
64
- "Content-Type": "application/json",
65
- ...input.headers
66
- },
67
- timeout: 3e4
68
- });
69
- return response.data;
70
- }).build();
71
- var webScraper = toolBuilder().name("web-scraper").description("Scrape and extract data from web pages. Can extract text, HTML, links, images, and use CSS selectors to target specific elements.").category(ToolCategory.WEB).tags(["scraper", "web", "html", "extract", "parse"]).schema(z.object({
33
+ });
34
+
35
+ // src/web/http/tools/http-client.ts
36
+ function createHttpClientTool(defaultTimeout = 3e4, defaultHeaders = {}) {
37
+ return toolBuilder().name("http-client").description("Make HTTP requests to web APIs and services. Supports GET, POST, PUT, DELETE, PATCH methods with custom headers and body.").category(ToolCategory.WEB).tags(["http", "api", "request", "web"]).schema(httpRequestSchema).implement(async (input) => {
38
+ const config = {
39
+ method: input.method,
40
+ url: input.url,
41
+ headers: { ...defaultHeaders, ...input.headers },
42
+ data: input.body,
43
+ timeout: input.timeout ?? defaultTimeout,
44
+ params: input.params,
45
+ validateStatus: () => true
46
+ // Don't throw on any status code
47
+ };
48
+ const response = await axios12(config);
49
+ return {
50
+ status: response.status,
51
+ statusText: response.statusText,
52
+ headers: response.headers,
53
+ data: response.data,
54
+ url: input.url,
55
+ method: input.method ?? "GET"
56
+ };
57
+ }).build();
58
+ }
59
+ function createHttpGetTool(defaultTimeout = 3e4, defaultHeaders = {}) {
60
+ return toolBuilder().name("http-get").description("Make a simple HTTP GET request to a URL and return the response data.").category(ToolCategory.WEB).tags(["http", "get", "fetch", "web"]).schema(httpGetSchema).implement(async (input) => {
61
+ const response = await axios12.get(input.url, {
62
+ headers: { ...defaultHeaders, ...input.headers },
63
+ params: input.params,
64
+ timeout: defaultTimeout
65
+ });
66
+ return response.data;
67
+ }).build();
68
+ }
69
+ function createHttpPostTool(defaultTimeout = 3e4, defaultHeaders = {}) {
70
+ return toolBuilder().name("http-post").description("Make a simple HTTP POST request with JSON body and return the response data.").category(ToolCategory.WEB).tags(["http", "post", "api", "web"]).schema(httpPostSchema).implement(async (input) => {
71
+ const response = await axios12.post(input.url, input.body, {
72
+ headers: {
73
+ "Content-Type": "application/json",
74
+ ...defaultHeaders,
75
+ ...input.headers
76
+ },
77
+ timeout: defaultTimeout
78
+ });
79
+ return response.data;
80
+ }).build();
81
+ }
82
+
83
+ // src/web/http/index.ts
84
+ var httpClient = createHttpClientTool();
85
+ var httpGet = createHttpGetTool();
86
+ var httpPost = createHttpPostTool();
87
+ var httpTools = [httpClient, httpGet, httpPost];
88
+ function createHttpTools(config = {}) {
89
+ const { defaultTimeout = 3e4, defaultHeaders = {} } = config;
90
+ return [
91
+ createHttpClientTool(defaultTimeout, defaultHeaders),
92
+ createHttpGetTool(defaultTimeout, defaultHeaders),
93
+ createHttpPostTool(defaultTimeout, defaultHeaders)
94
+ ];
95
+ }
96
+ var webScraperSchema = z.object({
72
97
  url: z.string().url().describe("The URL of the web page to scrape"),
73
98
  selector: z.string().optional().describe("Optional CSS selector to extract specific elements"),
74
99
  extractText: z.boolean().default(true).describe("Extract text content from the page"),
@@ -77,240 +102,295 @@ var webScraper = toolBuilder().name("web-scraper").description("Scrape and extra
77
102
  extractImages: z.boolean().default(false).describe("Extract all image URLs from the page"),
78
103
  extractMetadata: z.boolean().default(false).describe("Extract meta tags (title, description, etc.)"),
79
104
  timeout: z.number().default(3e4).describe("Request timeout in milliseconds")
80
- })).implement(async (input) => {
81
- const response = await axios.get(input.url, {
82
- timeout: input.timeout,
83
- headers: {
84
- "User-Agent": "Mozilla/5.0 (compatible; AgentForge/1.0; +https://agentforge.dev)"
85
- }
86
- });
87
- const html = response.data;
88
- const $ = cheerio2.load(html);
89
- const result = {
90
- url: input.url
91
- };
92
- const $selected = input.selector ? $(input.selector) : $("body");
93
- if (input.extractText) {
94
- result.text = $selected.text().trim();
95
- }
96
- if (input.extractHtml) {
97
- result.html = $selected.html() || "";
98
- }
99
- if (input.extractLinks) {
100
- result.links = [];
101
- $("a[href]").each((_, el) => {
102
- const href = $(el).attr("href");
103
- if (href) {
104
- try {
105
- const absoluteUrl = new URL(href, input.url).href;
106
- result.links.push(absoluteUrl);
107
- } catch {
108
- result.links.push(href);
109
- }
105
+ });
106
+ function createWebScraperTool(defaultTimeout = 3e4, userAgent = "Mozilla/5.0 (compatible; AgentForge/1.0; +https://agentforge.dev)") {
107
+ return toolBuilder().name("web-scraper").description("Scrape and extract data from web pages. Can extract text, HTML, links, images, and use CSS selectors to target specific elements.").category(ToolCategory.WEB).tags(["scraper", "web", "html", "extract", "parse"]).schema(webScraperSchema).implement(async (input) => {
108
+ const response = await axios12.get(input.url, {
109
+ timeout: input.timeout || defaultTimeout,
110
+ headers: {
111
+ "User-Agent": userAgent
110
112
  }
111
113
  });
112
- }
113
- if (input.extractImages) {
114
- result.images = [];
115
- $("img[src]").each((_, el) => {
116
- const src = $(el).attr("src");
117
- if (src) {
118
- try {
119
- const absoluteUrl = new URL(src, input.url).href;
120
- result.images.push(absoluteUrl);
121
- } catch {
122
- result.images.push(src);
114
+ const html = response.data;
115
+ const $ = cheerio.load(html);
116
+ const result = {
117
+ url: input.url
118
+ };
119
+ const $selected = input.selector ? $(input.selector) : $("body");
120
+ if (input.extractText) {
121
+ result.text = $selected.text().trim();
122
+ }
123
+ if (input.extractHtml) {
124
+ result.html = $selected.html() || "";
125
+ }
126
+ if (input.extractLinks) {
127
+ result.links = [];
128
+ $("a[href]").each((_, el) => {
129
+ const href = $(el).attr("href");
130
+ if (href) {
131
+ try {
132
+ const absoluteUrl = new URL(href, input.url).href;
133
+ result.links.push(absoluteUrl);
134
+ } catch {
135
+ result.links.push(href);
136
+ }
123
137
  }
124
- }
125
- });
126
- }
127
- if (input.extractMetadata) {
128
- result.metadata = {};
129
- const title = $("title").text() || $('meta[property="og:title"]').attr("content");
130
- if (title) result.metadata.title = title;
131
- const description = $('meta[name="description"]').attr("content") || $('meta[property="og:description"]').attr("content");
132
- if (description) result.metadata.description = description;
133
- $("meta[name], meta[property]").each((_, el) => {
134
- const name = $(el).attr("name") || $(el).attr("property");
135
- const content = $(el).attr("content");
136
- if (name && content) {
137
- result.metadata[name] = content;
138
- }
139
- });
140
- }
141
- if (input.selector) {
142
- result.selected = $selected.map((_, el) => ({
143
- text: $(el).text().trim(),
144
- html: $(el).html()
145
- })).get();
146
- }
147
- return result;
148
- }).build();
149
- var htmlParser = toolBuilder().name("html-parser").description("Parse HTML content and extract data using CSS selectors. Returns text, attributes, and structure of selected elements.").category(ToolCategory.WEB).tags(["html", "parser", "css", "selector", "extract"]).schema(z.object({
138
+ });
139
+ }
140
+ if (input.extractImages) {
141
+ result.images = [];
142
+ $("img[src]").each((_, el) => {
143
+ const src = $(el).attr("src");
144
+ if (src) {
145
+ try {
146
+ const absoluteUrl = new URL(src, input.url).href;
147
+ result.images.push(absoluteUrl);
148
+ } catch {
149
+ result.images.push(src);
150
+ }
151
+ }
152
+ });
153
+ }
154
+ if (input.extractMetadata) {
155
+ result.metadata = {};
156
+ const title = $("title").text() || $('meta[property="og:title"]').attr("content");
157
+ if (title) result.metadata.title = title;
158
+ const description = $('meta[name="description"]').attr("content") || $('meta[property="og:description"]').attr("content");
159
+ if (description) result.metadata.description = description;
160
+ $("meta[name], meta[property]").each((_, el) => {
161
+ const name = $(el).attr("name") || $(el).attr("property");
162
+ const content = $(el).attr("content");
163
+ if (name && content) {
164
+ result.metadata[name] = content;
165
+ }
166
+ });
167
+ }
168
+ if (input.selector) {
169
+ result.selected = $selected.map((_, el) => ({
170
+ text: $(el).text().trim(),
171
+ html: $(el).html()
172
+ })).get();
173
+ }
174
+ return result;
175
+ }).build();
176
+ }
177
+
178
+ // src/web/scraper/index.ts
179
+ var webScraper = createWebScraperTool();
180
+ var scraperTools = [webScraper];
181
+ function createScraperTools(config = {}) {
182
+ const { defaultTimeout = 3e4, userAgent = "Mozilla/5.0 (compatible; AgentForge/1.0; +https://agentforge.dev)" } = config;
183
+ return [createWebScraperTool(defaultTimeout, userAgent)];
184
+ }
185
+ var htmlParserSchema = z.object({
150
186
  html: z.string().describe("The HTML content to parse"),
151
187
  selector: z.string().describe("CSS selector to find elements"),
152
188
  extractText: z.boolean().default(true).describe("Extract text content from selected elements"),
153
189
  extractHtml: z.boolean().default(false).describe("Extract inner HTML of selected elements"),
154
190
  extractAttributes: z.array(z.string().describe("String value")).optional().describe('List of attributes to extract (e.g., ["href", "src", "class"])')
155
- })).implement(async (input) => {
156
- const $ = cheerio2.load(input.html);
157
- const $selected = $(input.selector);
158
- const results = $selected.map((_, el) => {
159
- const $el = $(el);
160
- const item = {};
161
- if (input.extractText) {
162
- item.text = $el.text().trim();
163
- }
164
- if (input.extractHtml) {
165
- item.html = $el.html();
166
- }
167
- if (input.extractAttributes && input.extractAttributes.length > 0) {
168
- item.attributes = {};
169
- for (const attr of input.extractAttributes) {
170
- const value = $el.attr(attr);
171
- if (value !== void 0) {
172
- item.attributes[attr] = value;
173
- }
174
- }
175
- }
176
- return item;
177
- }).get();
178
- return {
179
- count: results.length,
180
- results
181
- };
182
- }).build();
183
- var extractLinks = toolBuilder().name("extract-links").description("Extract all links (anchor tags) from HTML content with their text and href attributes.").category(ToolCategory.WEB).tags(["html", "links", "extract", "anchor"]).schema(z.object({
191
+ });
192
+ var extractLinksSchema = z.object({
184
193
  html: z.string().describe("The HTML content to extract links from"),
185
194
  baseUrl: z.string().url().optional().describe("Optional base URL to resolve relative links")
186
- })).implement(async (input) => {
187
- const $ = cheerio2.load(input.html);
188
- const links = [];
189
- $("a[href]").each((_, el) => {
190
- const $el = $(el);
191
- let href = $el.attr("href") || "";
192
- if (input.baseUrl && href) {
193
- try {
194
- href = new URL(href, input.baseUrl).href;
195
- } catch {
196
- }
197
- }
198
- links.push({
199
- text: $el.text().trim(),
200
- href,
201
- title: $el.attr("title")
202
- });
203
- });
204
- return {
205
- count: links.length,
206
- links
207
- };
208
- }).build();
209
- var extractImages = toolBuilder().name("extract-images").description("Extract all images from HTML content with their src, alt, and other attributes.").category(ToolCategory.WEB).tags(["html", "images", "extract", "img"]).schema(z.object({
195
+ });
196
+ var extractImagesSchema = z.object({
210
197
  html: z.string().describe("The HTML content to extract images from"),
211
198
  baseUrl: z.string().url().optional().describe("Optional base URL to resolve relative image URLs")
212
- })).implement(async (input) => {
213
- const $ = cheerio2.load(input.html);
214
- const images = [];
215
- $("img[src]").each((_, el) => {
216
- const $el = $(el);
217
- let src = $el.attr("src") || "";
218
- if (input.baseUrl && src) {
219
- try {
220
- src = new URL(src, input.baseUrl).href;
221
- } catch {
199
+ });
200
+ function createHtmlParserTool() {
201
+ return toolBuilder().name("html-parser").description("Parse HTML content and extract data using CSS selectors. Returns text, attributes, and structure of selected elements.").category(ToolCategory.WEB).tags(["html", "parser", "css", "selector", "extract"]).schema(htmlParserSchema).implement(async (input) => {
202
+ const $ = cheerio.load(input.html);
203
+ const $selected = $(input.selector);
204
+ const results = $selected.map((_, el) => {
205
+ const $el = $(el);
206
+ const item = {};
207
+ if (input.extractText) {
208
+ item.text = $el.text().trim();
222
209
  }
223
- }
224
- images.push({
225
- src,
226
- alt: $el.attr("alt"),
227
- title: $el.attr("title"),
228
- width: $el.attr("width"),
229
- height: $el.attr("height")
210
+ if (input.extractHtml) {
211
+ item.html = $el.html();
212
+ }
213
+ if (input.extractAttributes && input.extractAttributes.length > 0) {
214
+ item.attributes = {};
215
+ for (const attr of input.extractAttributes) {
216
+ const value = $el.attr(attr);
217
+ if (value !== void 0) {
218
+ item.attributes[attr] = value;
219
+ }
220
+ }
221
+ }
222
+ return item;
223
+ }).get();
224
+ return {
225
+ count: results.length,
226
+ results
227
+ };
228
+ }).build();
229
+ }
230
+ function createExtractLinksTool() {
231
+ return toolBuilder().name("extract-links").description("Extract all links (anchor tags) from HTML content with their text and href attributes.").category(ToolCategory.WEB).tags(["html", "links", "extract", "anchor"]).schema(extractLinksSchema).implement(async (input) => {
232
+ const $ = cheerio.load(input.html);
233
+ const links = [];
234
+ $("a[href]").each((_, el) => {
235
+ const $el = $(el);
236
+ let href = $el.attr("href") || "";
237
+ if (input.baseUrl && href) {
238
+ try {
239
+ href = new URL(href, input.baseUrl).href;
240
+ } catch {
241
+ }
242
+ }
243
+ links.push({
244
+ text: $el.text().trim(),
245
+ href,
246
+ title: $el.attr("title")
247
+ });
230
248
  });
231
- });
232
- return {
233
- count: images.length,
234
- images
235
- };
236
- }).build();
237
- 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({
249
+ return {
250
+ count: links.length,
251
+ links
252
+ };
253
+ }).build();
254
+ }
255
+ function createExtractImagesTool() {
256
+ return toolBuilder().name("extract-images").description("Extract all images from HTML content with their src, alt, and other attributes.").category(ToolCategory.WEB).tags(["html", "images", "extract", "img"]).schema(extractImagesSchema).implement(async (input) => {
257
+ const $ = cheerio.load(input.html);
258
+ const images = [];
259
+ $("img[src]").each((_, el) => {
260
+ const $el = $(el);
261
+ let src = $el.attr("src") || "";
262
+ if (input.baseUrl && src) {
263
+ try {
264
+ src = new URL(src, input.baseUrl).href;
265
+ } catch {
266
+ }
267
+ }
268
+ images.push({
269
+ src,
270
+ alt: $el.attr("alt"),
271
+ title: $el.attr("title"),
272
+ width: $el.attr("width"),
273
+ height: $el.attr("height")
274
+ });
275
+ });
276
+ return {
277
+ count: images.length,
278
+ images
279
+ };
280
+ }).build();
281
+ }
282
+
283
+ // src/web/html-parser/index.ts
284
+ var htmlParser = createHtmlParserTool();
285
+ var extractLinks = createExtractLinksTool();
286
+ var extractImages = createExtractImagesTool();
287
+ var htmlParserTools = [htmlParser, extractLinks, extractImages];
288
+ function createHtmlParserTools(config = {}) {
289
+ return [
290
+ createHtmlParserTool(),
291
+ createExtractLinksTool(),
292
+ createExtractImagesTool()
293
+ ];
294
+ }
295
+ var urlValidatorSchema = z.object({
238
296
  url: z.string().describe("The URL to validate and parse")
239
- })).implementSafe(async (input) => {
240
- const parsed = new URL(input.url);
241
- return {
242
- url: parsed.href,
243
- protocol: parsed.protocol,
244
- hostname: parsed.hostname,
245
- port: parsed.port,
246
- pathname: parsed.pathname,
247
- search: parsed.search,
248
- hash: parsed.hash,
249
- origin: parsed.origin
250
- };
251
- }).build();
252
- 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({
297
+ });
298
+ var urlBuilderSchema = z.object({
253
299
  protocol: z.string().default("https").describe("Protocol (http, https, etc.)"),
254
300
  hostname: z.string().describe("Hostname or domain name"),
255
301
  port: z.string().optional().describe("Optional port number"),
256
302
  pathname: z.string().default("/").describe("URL path"),
257
303
  query: z.record(z.string()).optional().describe("Query parameters as key-value pairs"),
258
304
  hash: z.string().optional().describe("URL hash/fragment")
259
- })).implement(async (input) => {
260
- const url = new URL(`${input.protocol}://${input.hostname}`);
261
- if (input.port) {
262
- url.port = input.port;
263
- }
264
- url.pathname = input.pathname ?? "/";
265
- if (input.query) {
266
- Object.entries(input.query).forEach(([key, value]) => {
267
- url.searchParams.append(key, value);
268
- });
269
- }
270
- if (input.hash) {
271
- url.hash = input.hash;
272
- }
273
- return {
274
- url: url.href,
275
- components: {
276
- protocol: url.protocol,
277
- hostname: url.hostname,
278
- port: url.port,
279
- pathname: url.pathname,
280
- search: url.search,
281
- hash: url.hash,
282
- origin: url.origin
283
- }
284
- };
285
- }).build();
286
- var urlQueryParser = toolBuilder().name("url-query-parser").description("Parse query parameters from a URL or query string into a key-value object.").category(ToolCategory.WEB).tags(["url", "query", "parse", "params"]).schema(z.object({
305
+ });
306
+ var urlQueryParserSchema = z.object({
287
307
  input: z.string().describe('URL or query string to parse (e.g., "?foo=bar&baz=qux" or full URL)')
288
- })).implement(async (input) => {
289
- let searchParams;
290
- try {
291
- const url = new URL(input.input);
292
- searchParams = url.searchParams;
293
- } catch {
294
- const queryString = input.input.startsWith("?") ? input.input.slice(1) : input.input;
295
- searchParams = new URLSearchParams(queryString);
296
- }
297
- const params = {};
298
- searchParams.forEach((value, key) => {
299
- if (params[key]) {
300
- if (Array.isArray(params[key])) {
301
- params[key].push(value);
302
- } else {
303
- params[key] = [params[key], value];
308
+ });
309
+ function createUrlValidatorTool() {
310
+ return 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(urlValidatorSchema).implementSafe(async (input) => {
311
+ const parsed = new URL(input.url);
312
+ return {
313
+ url: parsed.href,
314
+ protocol: parsed.protocol,
315
+ hostname: parsed.hostname,
316
+ port: parsed.port,
317
+ pathname: parsed.pathname,
318
+ search: parsed.search,
319
+ hash: parsed.hash,
320
+ origin: parsed.origin
321
+ };
322
+ }).build();
323
+ }
324
+ function createUrlBuilderTool() {
325
+ return toolBuilder().name("url-builder").description("Build a URL from components (protocol, hostname, path, query parameters, hash).").category(ToolCategory.WEB).tags(["url", "builder", "construct"]).schema(urlBuilderSchema).implement(async (input) => {
326
+ const url = new URL(`${input.protocol}://${input.hostname}`);
327
+ if (input.port) {
328
+ url.port = input.port;
329
+ }
330
+ url.pathname = input.pathname ?? "/";
331
+ if (input.query) {
332
+ Object.entries(input.query).forEach(([key, value]) => {
333
+ url.searchParams.append(key, value);
334
+ });
335
+ }
336
+ if (input.hash) {
337
+ url.hash = input.hash;
338
+ }
339
+ return {
340
+ url: url.href,
341
+ components: {
342
+ protocol: url.protocol,
343
+ hostname: url.hostname,
344
+ port: url.port,
345
+ pathname: url.pathname,
346
+ search: url.search,
347
+ hash: url.hash,
348
+ origin: url.origin
304
349
  }
305
- } else {
306
- params[key] = value;
350
+ };
351
+ }).build();
352
+ }
353
+ function createUrlQueryParserTool() {
354
+ return toolBuilder().name("url-query-parser").description("Parse query parameters from a URL or query string into a key-value object.").category(ToolCategory.WEB).tags(["url", "query", "parse", "params"]).schema(urlQueryParserSchema).implement(async (input) => {
355
+ let searchParams;
356
+ try {
357
+ const url = new URL(input.input);
358
+ searchParams = url.searchParams;
359
+ } catch {
360
+ const queryString = input.input.startsWith("?") ? input.input.slice(1) : input.input;
361
+ searchParams = new URLSearchParams(queryString);
307
362
  }
308
- });
309
- return {
310
- params,
311
- count: Object.keys(params).length
312
- };
313
- }).build();
363
+ const params = {};
364
+ searchParams.forEach((value, key) => {
365
+ if (params[key]) {
366
+ if (Array.isArray(params[key])) {
367
+ params[key].push(value);
368
+ } else {
369
+ params[key] = [params[key], value];
370
+ }
371
+ } else {
372
+ params[key] = value;
373
+ }
374
+ });
375
+ return {
376
+ params,
377
+ count: Object.keys(params).length
378
+ };
379
+ }).build();
380
+ }
381
+
382
+ // src/web/url-validator/index.ts
383
+ var urlValidator = createUrlValidatorTool();
384
+ var urlBuilder = createUrlBuilderTool();
385
+ var urlQueryParser = createUrlQueryParserTool();
386
+ var urlValidatorTools = [urlValidator, urlBuilder, urlQueryParser];
387
+ function createUrlValidatorTools(config = {}) {
388
+ return [
389
+ createUrlValidatorTool(),
390
+ createUrlBuilderTool(),
391
+ createUrlQueryParserTool()
392
+ ];
393
+ }
314
394
  var webSearchSchema = z.object({
315
395
  query: z.string().min(1).describe("The search query"),
316
396
  maxResults: z.number().min(1).max(50).default(10).describe("Maximum number of results to return (1-50)"),
@@ -415,7 +495,7 @@ var DuckDuckGoProvider = class {
415
495
  async search(query, maxResults, timeout = DEFAULT_TIMEOUT) {
416
496
  return retryWithBackoff(async () => {
417
497
  try {
418
- const response = await axios.get(
498
+ const response = await axios12.get(
419
499
  "https://api.duckduckgo.com/",
420
500
  {
421
501
  params: {
@@ -519,7 +599,7 @@ var SerperProvider = class {
519
599
  }
520
600
  return retryWithBackoff(async () => {
521
601
  try {
522
- const response = await axios.post(
602
+ const response = await axios12.post(
523
603
  "https://google.serper.dev/search",
524
604
  {
525
605
  q: query,
@@ -657,8 +737,28 @@ var webSearch = toolBuilder().name("web-search").description(
657
737
  };
658
738
  }
659
739
  }).build();
660
- var logLevel = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
661
- var logger = createLogger("tools:slack", { level: logLevel });
740
+ function createGetConfiguredSlackClient(token, botName = "AgentForge Bot", botIcon = ":robot_face:") {
741
+ let configuredClient = null;
742
+ return function getConfiguredSlackClient() {
743
+ if (!configuredClient) {
744
+ const slackToken = token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN;
745
+ if (!slackToken) {
746
+ throw new Error(
747
+ "Slack token not configured. Please provide a token in config or set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
748
+ );
749
+ }
750
+ configuredClient = new WebClient(slackToken);
751
+ }
752
+ return {
753
+ client: configuredClient,
754
+ config: {
755
+ token: token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN || "",
756
+ botName,
757
+ botIcon
758
+ }
759
+ };
760
+ };
761
+ }
662
762
  var defaultSlackClient = null;
663
763
  function getDefaultSlackClient() {
664
764
  if (!defaultSlackClient) {
@@ -670,196 +770,17 @@ function getDefaultSlackClient() {
670
770
  }
671
771
  defaultSlackClient = new WebClient(token);
672
772
  }
673
- return defaultSlackClient;
674
- }
675
- var sendSlackMessage = toolBuilder().name("send-slack-message").description("Send a message to a Slack channel for team communication and notifications").category(ToolCategory.WEB).tags(["slack", "messaging", "communication"]).usageNotes(
676
- "Use this for general team communication. For notifications with @mentions, consider using notify-slack instead. Use get-slack-channels first if you need to find the right channel."
677
- ).suggests(["get-slack-channels"]).schema(
678
- z.object({
679
- channel: z.string().describe("Channel name (e.g., 'general') or ID (e.g., 'C123456')"),
680
- message: z.string().describe("Message content to send")
681
- })
682
- ).implementSafe(async ({ channel, message }) => {
683
- logger.info("send-slack-message called", { channel, messageLength: message.length });
684
- try {
685
- const slack = getDefaultSlackClient();
686
- const result = await slack.chat.postMessage({
687
- channel,
688
- text: message,
689
- username: "AgentForge Bot",
690
- icon_emoji: ":robot_face:"
691
- });
692
- logger.info("send-slack-message result", {
693
- channel: result.channel,
694
- timestamp: result.ts,
695
- messageLength: message.length,
696
- success: true
697
- });
698
- return {
699
- channel: result.channel,
700
- message,
701
- timestamp: result.ts,
702
- message_id: result.ts
703
- };
704
- } catch (error) {
705
- logger.error("send-slack-message failed", {
706
- channel,
707
- error: error.message,
708
- data: error.data
709
- });
710
- throw error;
711
- }
712
- }).build();
713
- var notifySlack = toolBuilder().name("notify-slack").description("Send a notification to a Slack channel with optional @mentions for urgent alerts").category(ToolCategory.WEB).tags(["slack", "notification", "alert"]).usageNotes(
714
- "Use this for urgent notifications that require @mentions. For general messages without mentions, use send-slack-message instead."
715
- ).suggests(["get-slack-channels"]).schema(
716
- z.object({
717
- channel: z.string().describe("Channel name or ID"),
718
- message: z.string().describe("Notification message"),
719
- mentions: z.array(z.string()).optional().describe("List of usernames to mention (without @)")
720
- })
721
- ).implementSafe(async ({ channel, message, mentions = [] }) => {
722
- logger.info("notify-slack called", {
723
- channel,
724
- messageLength: message.length,
725
- mentionCount: mentions.length
726
- });
727
- const slack = getDefaultSlackClient();
728
- const mentionText = mentions.length > 0 ? mentions.map((m) => `<@${m}>`).join(" ") + " " : "";
729
- const fullMessage = `${mentionText}${message}`;
730
- const result = await slack.chat.postMessage({
731
- channel,
732
- text: fullMessage,
733
- username: "AgentForge Bot",
734
- icon_emoji: ":robot_face:"
735
- });
736
- logger.info("notify-slack result", {
737
- channel: result.channel,
738
- timestamp: result.ts,
739
- mentions: mentions.length
740
- });
741
- return {
742
- channel: result.channel,
743
- message: fullMessage,
744
- mentions,
745
- timestamp: result.ts,
746
- notification_id: result.ts
747
- };
748
- }).build();
749
- var getSlackChannels = toolBuilder().name("get-slack-channels").description("Get a list of available Slack channels to find the right channel for messaging").category(ToolCategory.WEB).tags(["slack", "channels", "list"]).usageNotes(
750
- "Use this first to discover available channels before sending messages. Helps ensure you are sending to the correct channel."
751
- ).follows(["send-slack-message", "notify-slack"]).schema(
752
- z.object({
753
- include_private: z.boolean().optional().describe("Include private channels (default: false)")
754
- })
755
- ).implementSafe(async ({ include_private = false }) => {
756
- logger.info("get-slack-channels called", { include_private });
757
- const slack = getDefaultSlackClient();
758
- const publicChannels = await slack.conversations.list({
759
- types: "public_channel",
760
- exclude_archived: true
761
- });
762
- let allChannels = publicChannels.channels || [];
763
- if (include_private) {
764
- const privateChannels = await slack.conversations.list({
765
- types: "private_channel",
766
- exclude_archived: true
767
- });
768
- allChannels = [...allChannels, ...privateChannels.channels || []];
769
- }
770
- logger.info("get-slack-channels result", {
771
- channelCount: allChannels.length,
772
- includePrivate: include_private
773
- });
774
773
  return {
775
- count: allChannels.length,
776
- channels: allChannels.map((c) => ({
777
- id: c.id,
778
- name: c.name,
779
- is_private: c.is_private || false,
780
- num_members: c.num_members || 0
781
- }))
782
- };
783
- }).build();
784
- var getSlackMessages = toolBuilder().name("get-slack-messages").description("Retrieve message history from a Slack channel to read recent conversations").category(ToolCategory.WEB).tags(["slack", "messages", "history", "read"]).usageNotes(
785
- "Use this to read recent messages from a channel. Use get-slack-channels first if you need to find the channel ID. Returns messages in reverse chronological order (newest first)."
786
- ).suggests(["get-slack-channels"]).schema(
787
- z.object({
788
- channel: z.string().describe("Channel name (e.g., 'general') or ID (e.g., 'C123456')"),
789
- limit: z.number().int().min(1).max(100).optional().describe("Number of messages to retrieve (default: 20, max: 100)")
790
- })
791
- ).implementSafe(async ({ channel, limit = 20 }) => {
792
- logger.info("get-slack-messages called", { channel, limit });
793
- try {
794
- const slack = getDefaultSlackClient();
795
- let channelId = channel;
796
- if (!channel.startsWith("C") && !channel.startsWith("D")) {
797
- const channels = await slack.conversations.list({
798
- types: "public_channel,private_channel",
799
- exclude_archived: true
800
- });
801
- const found = channels.channels?.find((c) => c.name === channel);
802
- if (!found) {
803
- logger.error("get-slack-messages: channel not found", { channel });
804
- throw new Error(
805
- `Channel '${channel}' not found. Use get-slack-channels to see available channels.`
806
- );
807
- }
808
- channelId = found.id;
809
- }
810
- const result = await slack.conversations.history({
811
- channel: channelId,
812
- limit: Math.min(limit, 100)
813
- // Cap at 100 for performance
814
- });
815
- logger.info("get-slack-messages result", {
816
- channel: channelId,
817
- messageCount: result.messages?.length || 0,
818
- limit
819
- });
820
- return {
821
- channel: channelId,
822
- count: result.messages?.length || 0,
823
- messages: result.messages?.map((m) => ({
824
- user: m.user || "unknown",
825
- text: m.text || "",
826
- timestamp: m.ts,
827
- thread_ts: m.thread_ts,
828
- type: m.type,
829
- subtype: m.subtype
830
- })) || []
831
- };
832
- } catch (error) {
833
- logger.error("get-slack-messages failed", {
834
- channel,
835
- error: error.message,
836
- data: error.data
837
- });
838
- throw error;
839
- }
840
- }).build();
841
- function createSlackTools(config = {}) {
842
- const {
843
- token,
844
- botName = "AgentForge Bot",
845
- botIcon = ":robot_face:",
846
- logLevel: customLogLevel
847
- } = config;
848
- let configuredClient = null;
849
- function getConfiguredSlackClient() {
850
- if (!configuredClient) {
851
- const slackToken = token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN;
852
- if (!slackToken) {
853
- throw new Error(
854
- "Slack token not configured. Please provide a token in config or set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
855
- );
856
- }
857
- configuredClient = new WebClient(slackToken);
774
+ client: defaultSlackClient,
775
+ config: {
776
+ token: process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN || "",
777
+ botName: "AgentForge Bot",
778
+ botIcon: ":robot_face:"
858
779
  }
859
- return configuredClient;
860
- }
861
- const toolLogger = customLogLevel ? createLogger("tools:slack", { level: customLogLevel }) : logger;
862
- const sendMessage = toolBuilder().name("send-slack-message").description("Send a message to a Slack channel for team communication and notifications").category(ToolCategory.WEB).tags(["slack", "messaging", "communication"]).usageNotes(
780
+ };
781
+ }
782
+ function createSendSlackMessageTool(getSlackClient, logger4) {
783
+ return toolBuilder().name("send-slack-message").description("Send a message to a Slack channel for team communication and notifications").category(ToolCategory.WEB).tags(["slack", "messaging", "communication"]).usageNotes(
863
784
  "Use this for general team communication. For notifications with @mentions, consider using notify-slack instead. Use get-slack-channels first if you need to find the right channel."
864
785
  ).suggests(["get-slack-channels"]).schema(
865
786
  z.object({
@@ -867,16 +788,16 @@ function createSlackTools(config = {}) {
867
788
  message: z.string().describe("Message content to send")
868
789
  })
869
790
  ).implementSafe(async ({ channel, message }) => {
870
- toolLogger.info("send-slack-message called", { channel, messageLength: message.length });
791
+ logger4.info("send-slack-message called", { channel, messageLength: message.length });
871
792
  try {
872
- const slack = getConfiguredSlackClient();
793
+ const { client: slack, config } = getSlackClient();
873
794
  const result = await slack.chat.postMessage({
874
795
  channel,
875
796
  text: message,
876
- username: botName,
877
- icon_emoji: botIcon
797
+ username: config.botName,
798
+ icon_emoji: config.botIcon
878
799
  });
879
- toolLogger.info("send-slack-message result", {
800
+ logger4.info("send-slack-message result", {
880
801
  channel: result.channel,
881
802
  timestamp: result.ts,
882
803
  messageLength: message.length,
@@ -889,7 +810,7 @@ function createSlackTools(config = {}) {
889
810
  message_id: result.ts
890
811
  };
891
812
  } catch (error) {
892
- toolLogger.error("send-slack-message failed", {
813
+ logger4.error("send-slack-message failed", {
893
814
  channel,
894
815
  error: error.message,
895
816
  data: error.data
@@ -897,7 +818,9 @@ function createSlackTools(config = {}) {
897
818
  throw error;
898
819
  }
899
820
  }).build();
900
- const notify = toolBuilder().name("notify-slack").description("Send a notification to a Slack channel with optional @mentions for urgent alerts").category(ToolCategory.WEB).tags(["slack", "notification", "alert"]).usageNotes(
821
+ }
822
+ function createNotifySlackTool(getSlackClient, logger4) {
823
+ return toolBuilder().name("notify-slack").description("Send a notification to a Slack channel with optional @mentions for urgent alerts").category(ToolCategory.WEB).tags(["slack", "notification", "alert"]).usageNotes(
901
824
  "Use this for urgent notifications that require @mentions. For general messages without mentions, use send-slack-message instead."
902
825
  ).suggests(["get-slack-channels"]).schema(
903
826
  z.object({
@@ -906,21 +829,21 @@ function createSlackTools(config = {}) {
906
829
  mentions: z.array(z.string()).optional().describe("List of usernames to mention (without @)")
907
830
  })
908
831
  ).implementSafe(async ({ channel, message, mentions = [] }) => {
909
- toolLogger.info("notify-slack called", {
832
+ logger4.info("notify-slack called", {
910
833
  channel,
911
834
  messageLength: message.length,
912
835
  mentionCount: mentions.length
913
836
  });
914
- const slack = getConfiguredSlackClient();
837
+ const { client: slack, config } = getSlackClient();
915
838
  const mentionText = mentions.length > 0 ? mentions.map((m) => `<@${m}>`).join(" ") + " " : "";
916
839
  const fullMessage = `${mentionText}${message}`;
917
840
  const result = await slack.chat.postMessage({
918
841
  channel,
919
842
  text: fullMessage,
920
- username: botName,
921
- icon_emoji: botIcon
843
+ username: config.botName,
844
+ icon_emoji: config.botIcon
922
845
  });
923
- toolLogger.info("notify-slack result", {
846
+ logger4.info("notify-slack result", {
924
847
  channel: result.channel,
925
848
  timestamp: result.ts,
926
849
  mentions: mentions.length
@@ -933,15 +856,17 @@ function createSlackTools(config = {}) {
933
856
  notification_id: result.ts
934
857
  };
935
858
  }).build();
936
- const getChannels = toolBuilder().name("get-slack-channels").description("Get a list of available Slack channels to find the right channel for messaging").category(ToolCategory.WEB).tags(["slack", "channels", "list"]).usageNotes(
859
+ }
860
+ function createGetSlackChannelsTool(getSlackClient, logger4) {
861
+ return toolBuilder().name("get-slack-channels").description("Get a list of available Slack channels to find the right channel for messaging").category(ToolCategory.WEB).tags(["slack", "channels", "list"]).usageNotes(
937
862
  "Use this first to discover available channels before sending messages. Helps ensure you are sending to the correct channel."
938
863
  ).follows(["send-slack-message", "notify-slack"]).schema(
939
864
  z.object({
940
865
  include_private: z.boolean().optional().describe("Include private channels (default: false)")
941
866
  })
942
867
  ).implementSafe(async ({ include_private = false }) => {
943
- toolLogger.info("get-slack-channels called", { include_private });
944
- const slack = getConfiguredSlackClient();
868
+ logger4.info("get-slack-channels called", { include_private });
869
+ const { client: slack } = getSlackClient();
945
870
  const publicChannels = await slack.conversations.list({
946
871
  types: "public_channel",
947
872
  exclude_archived: true
@@ -954,7 +879,7 @@ function createSlackTools(config = {}) {
954
879
  });
955
880
  allChannels = [...allChannels, ...privateChannels.channels || []];
956
881
  }
957
- toolLogger.info("get-slack-channels result", {
882
+ logger4.info("get-slack-channels result", {
958
883
  channelCount: allChannels.length,
959
884
  includePrivate: include_private
960
885
  });
@@ -968,7 +893,9 @@ function createSlackTools(config = {}) {
968
893
  }))
969
894
  };
970
895
  }).build();
971
- const getMessages = toolBuilder().name("get-slack-messages").description("Retrieve message history from a Slack channel to read recent conversations").category(ToolCategory.WEB).tags(["slack", "messages", "history", "read"]).usageNotes(
896
+ }
897
+ function createGetSlackMessagesTool(getSlackClient, logger4) {
898
+ return toolBuilder().name("get-slack-messages").description("Retrieve message history from a Slack channel to read recent conversations").category(ToolCategory.WEB).tags(["slack", "messages", "history", "read"]).usageNotes(
972
899
  "Use this to read recent messages from a channel. Use get-slack-channels first if you need to find the channel ID. Returns messages in reverse chronological order (newest first)."
973
900
  ).suggests(["get-slack-channels"]).schema(
974
901
  z.object({
@@ -976,9 +903,9 @@ function createSlackTools(config = {}) {
976
903
  limit: z.number().int().min(1).max(100).optional().describe("Number of messages to retrieve (default: 20, max: 100)")
977
904
  })
978
905
  ).implementSafe(async ({ channel, limit = 20 }) => {
979
- toolLogger.info("get-slack-messages called", { channel, limit });
906
+ logger4.info("get-slack-messages called", { channel, limit });
980
907
  try {
981
- const slack = getConfiguredSlackClient();
908
+ const { client: slack } = getSlackClient();
982
909
  let channelId = channel;
983
910
  if (!channel.startsWith("C") && !channel.startsWith("D")) {
984
911
  const channels = await slack.conversations.list({
@@ -987,7 +914,7 @@ function createSlackTools(config = {}) {
987
914
  });
988
915
  const found = channels.channels?.find((c) => c.name === channel);
989
916
  if (!found) {
990
- toolLogger.error("get-slack-messages: channel not found", { channel });
917
+ logger4.error("get-slack-messages: channel not found", { channel });
991
918
  throw new Error(
992
919
  `Channel '${channel}' not found. Use get-slack-channels to see available channels.`
993
920
  );
@@ -997,8 +924,9 @@ function createSlackTools(config = {}) {
997
924
  const result = await slack.conversations.history({
998
925
  channel: channelId,
999
926
  limit: Math.min(limit, 100)
927
+ // Cap at 100 for performance
1000
928
  });
1001
- toolLogger.info("get-slack-messages result", {
929
+ logger4.info("get-slack-messages result", {
1002
930
  channel: channelId,
1003
931
  messageCount: result.messages?.length || 0,
1004
932
  limit
@@ -1016,7 +944,7 @@ function createSlackTools(config = {}) {
1016
944
  })) || []
1017
945
  };
1018
946
  } catch (error) {
1019
- toolLogger.error("get-slack-messages failed", {
947
+ logger4.error("get-slack-messages failed", {
1020
948
  channel,
1021
949
  error: error.message,
1022
950
  data: error.data
@@ -1024,6 +952,36 @@ function createSlackTools(config = {}) {
1024
952
  throw error;
1025
953
  }
1026
954
  }).build();
955
+ }
956
+
957
+ // src/web/slack/index.ts
958
+ var logLevel = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
959
+ var logger = createLogger("[tools:slack]", { level: logLevel });
960
+ var sendSlackMessage = createSendSlackMessageTool(getDefaultSlackClient, logger);
961
+ var notifySlack = createNotifySlackTool(getDefaultSlackClient, logger);
962
+ var getSlackChannels = createGetSlackChannelsTool(getDefaultSlackClient, logger);
963
+ var getSlackMessages = createGetSlackMessagesTool(getDefaultSlackClient, logger);
964
+ var slackTools = [
965
+ // Write tools
966
+ sendSlackMessage,
967
+ notifySlack,
968
+ // Read tools
969
+ getSlackChannels,
970
+ getSlackMessages
971
+ ];
972
+ function createSlackTools(config = {}) {
973
+ const {
974
+ token,
975
+ botName = "AgentForge Bot",
976
+ botIcon = ":robot_face:",
977
+ logLevel: customLogLevel
978
+ } = config;
979
+ const getConfiguredSlackClient = createGetConfiguredSlackClient(token, botName, botIcon);
980
+ const toolLogger = customLogLevel ? createLogger("[tools:slack]", { level: customLogLevel }) : logger;
981
+ const sendMessage = createSendSlackMessageTool(getConfiguredSlackClient, toolLogger);
982
+ const notify = createNotifySlackTool(getConfiguredSlackClient, toolLogger);
983
+ const getChannels = createGetSlackChannelsTool(getConfiguredSlackClient, toolLogger);
984
+ const getMessages = createGetSlackMessagesTool(getConfiguredSlackClient, toolLogger);
1027
985
  return {
1028
986
  sendMessage,
1029
987
  notify,
@@ -1031,1205 +989,2164 @@ function createSlackTools(config = {}) {
1031
989
  getMessages
1032
990
  };
1033
991
  }
1034
- var slackTools = [sendSlackMessage, notifySlack, getSlackChannels, getSlackMessages];
1035
- 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({
1036
- json: z.string().describe("JSON string to parse"),
1037
- strict: z.boolean().default(true).describe("Use strict JSON parsing (no trailing commas, etc.)")
1038
- })).implementSafe(async (input) => {
1039
- const parsed = JSON.parse(input.json);
1040
- return {
1041
- data: parsed,
1042
- type: Array.isArray(parsed) ? "array" : typeof parsed
992
+
993
+ // src/web/confluence/auth.ts
994
+ function createGetConfiguredAuth(apiKey, email, siteUrl) {
995
+ return function getConfiguredAuth() {
996
+ const ATLASSIAN_API_KEY = apiKey || process.env.ATLASSIAN_API_KEY || "";
997
+ const ATLASSIAN_EMAIL = email || process.env.ATLASSIAN_EMAIL || "";
998
+ const ATLASSIAN_SITE_URL = (siteUrl || process.env.ATLASSIAN_SITE_URL || "").replace(/\/$/, "");
999
+ if (!ATLASSIAN_API_KEY || !ATLASSIAN_EMAIL || !ATLASSIAN_SITE_URL) {
1000
+ throw new Error(
1001
+ "Confluence credentials not configured. Set ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, and ATLASSIAN_SITE_URL in config or environment variables."
1002
+ );
1003
+ }
1004
+ return { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, ATLASSIAN_SITE_URL };
1043
1005
  };
1044
- }).build();
1045
- 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({
1046
- data: z.any().describe("Data to convert to JSON string"),
1047
- pretty: z.boolean().default(false).describe("Format with indentation for readability"),
1048
- indent: z.number().default(2).describe("Number of spaces for indentation (when pretty is true)")
1049
- })).implementSafe(async (input) => {
1050
- const json = input.pretty ? JSON.stringify(input.data, null, input.indent) : JSON.stringify(input.data);
1051
- return {
1052
- json,
1053
- length: json.length
1006
+ }
1007
+ function createGetConfiguredAuthHeader(getConfiguredAuth) {
1008
+ return function getConfiguredAuthHeader() {
1009
+ const { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL } = getConfiguredAuth();
1010
+ const auth = Buffer.from(`${ATLASSIAN_EMAIL}:${ATLASSIAN_API_KEY}`).toString("base64");
1011
+ return `Basic ${auth}`;
1054
1012
  };
1055
- }).build();
1056
- 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({
1057
- data: z.any().describe("JSON data to query"),
1058
- path: z.string().describe('Dot notation path to query (e.g., "user.name" or "items[0].id")')
1059
- })).implementSafe(async (input) => {
1060
- const parts = input.path.split(".");
1061
- let current = input.data;
1062
- for (const part of parts) {
1063
- const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
1064
- if (arrayMatch) {
1065
- const [, key, index] = arrayMatch;
1066
- current = current[key][parseInt(index, 10)];
1067
- } else {
1068
- current = current[part];
1013
+ }
1014
+ function getConfig() {
1015
+ const ATLASSIAN_API_KEY = process.env.ATLASSIAN_API_KEY || "";
1016
+ const ATLASSIAN_EMAIL = process.env.ATLASSIAN_EMAIL || "";
1017
+ const ATLASSIAN_SITE_URL = (process.env.ATLASSIAN_SITE_URL || "").replace(/\/$/, "");
1018
+ if (!ATLASSIAN_API_KEY || !ATLASSIAN_EMAIL || !ATLASSIAN_SITE_URL) {
1019
+ throw new Error("Confluence credentials not configured. Set ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, and ATLASSIAN_SITE_URL in .env");
1020
+ }
1021
+ return { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, ATLASSIAN_SITE_URL };
1022
+ }
1023
+ function getAuthHeader() {
1024
+ const { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL } = getConfig();
1025
+ const auth = Buffer.from(`${ATLASSIAN_EMAIL}:${ATLASSIAN_API_KEY}`).toString("base64");
1026
+ return `Basic ${auth}`;
1027
+ }
1028
+ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger4) {
1029
+ return toolBuilder().name("search-confluence").description("Search for pages in Confluence using keywords or CQL (Confluence Query Language). Returns matching pages with titles, IDs, and excerpts.").category(ToolCategory.WEB).tag("confluence").tag("search").tag("knowledge-base").usageNotes("Use this to find relevant documentation, policies, or information in Confluence. You can search by keywords or use CQL for advanced queries (e.g., 'space=AI AND type=page'). Use get-confluence-page to retrieve full content of specific pages.").suggests(["get-confluence-page"]).schema(z.object({
1030
+ query: z.string().describe("Search query or CQL expression (e.g., 'payment processing' or 'space=BL3 AND title~payment')"),
1031
+ limit: z.number().optional().describe("Maximum number of results to return (default: 10, max: 25)")
1032
+ })).implement(async ({ query, limit = 10 }) => {
1033
+ logger4.info("search-confluence called", { query, limit });
1034
+ try {
1035
+ const { ATLASSIAN_SITE_URL } = getAuth();
1036
+ const response = await axios12.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/search`, {
1037
+ headers: {
1038
+ Authorization: getAuthHeader2(),
1039
+ Accept: "application/json"
1040
+ },
1041
+ params: {
1042
+ cql: query,
1043
+ limit: Math.min(limit, 25),
1044
+ expand: "space,version"
1045
+ }
1046
+ });
1047
+ const { ATLASSIAN_SITE_URL: siteUrl } = getAuth();
1048
+ const results = response.data.results.map((page) => ({
1049
+ id: page.id,
1050
+ title: page.title,
1051
+ type: page.type,
1052
+ space: page.space?.name || "Unknown",
1053
+ spaceKey: page.space?.key || "",
1054
+ url: `${siteUrl}/wiki${page._links.webui}`,
1055
+ lastModified: page.version?.when || ""
1056
+ }));
1057
+ if (results.length === 0) {
1058
+ logger4.warn("search-confluence returned NO RESULTS - this is a valid outcome, agent should not retry", {
1059
+ query,
1060
+ limit,
1061
+ totalSize: response.data.totalSize
1062
+ });
1063
+ } else {
1064
+ logger4.info("search-confluence result", {
1065
+ query,
1066
+ resultCount: results.length,
1067
+ totalSize: response.data.totalSize,
1068
+ titles: results.map((r) => r.title).slice(0, 3)
1069
+ // Log first 3 titles
1070
+ });
1071
+ }
1072
+ return JSON.stringify({
1073
+ success: true,
1074
+ count: results.length,
1075
+ total: response.data.totalSize,
1076
+ results
1077
+ });
1078
+ } catch (error) {
1079
+ logger4.error("search-confluence error", {
1080
+ query,
1081
+ error: error.response?.data?.message || error.message,
1082
+ status: error.response?.status
1083
+ });
1084
+ return JSON.stringify({
1085
+ success: false,
1086
+ error: error.response?.data?.message || error.message
1087
+ });
1069
1088
  }
1070
- if (current === void 0) {
1071
- throw new Error(`Path not found: ${input.path}`);
1089
+ }).build();
1090
+ }
1091
+ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger4) {
1092
+ return toolBuilder().name("get-confluence-page").description("Get the full content of a specific Confluence page by its ID. Returns the page title, content (in storage format), space, and metadata.").category(ToolCategory.WEB).tag("confluence").tag("page").tag("content").usageNotes("Use this after search-confluence to retrieve the full content of a specific page. The page ID can be found in search results.").requires(["search-confluence"]).schema(z.object({
1093
+ page_id: z.string().describe("The Confluence page ID (from search results)")
1094
+ })).implement(async ({ page_id }) => {
1095
+ logger4.info("get-confluence-page called", { page_id });
1096
+ try {
1097
+ const { ATLASSIAN_SITE_URL } = getAuth();
1098
+ const response = await axios12.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`, {
1099
+ headers: {
1100
+ Authorization: getAuthHeader2(),
1101
+ Accept: "application/json"
1102
+ },
1103
+ params: {
1104
+ expand: "body.storage,space,version,history"
1105
+ }
1106
+ });
1107
+ const page = response.data;
1108
+ logger4.info("get-confluence-page result", {
1109
+ page_id,
1110
+ title: page.title,
1111
+ space: page.space?.name,
1112
+ contentLength: page.body?.storage?.value?.length || 0
1113
+ });
1114
+ return JSON.stringify({
1115
+ success: true,
1116
+ page: {
1117
+ id: page.id,
1118
+ title: page.title,
1119
+ type: page.type,
1120
+ space: page.space?.name || "Unknown",
1121
+ spaceKey: page.space?.key || "",
1122
+ content: page.body?.storage?.value || "",
1123
+ url: `${ATLASSIAN_SITE_URL}/wiki${page._links.webui}`,
1124
+ created: page.history?.createdDate || "",
1125
+ lastModified: page.version?.when || "",
1126
+ version: page.version?.number || 1
1127
+ }
1128
+ });
1129
+ } catch (error) {
1130
+ logger4.error("get-confluence-page error", {
1131
+ page_id,
1132
+ error: error.response?.data?.message || error.message,
1133
+ status: error.response?.status
1134
+ });
1135
+ return JSON.stringify({
1136
+ success: false,
1137
+ error: error.response?.data?.message || error.message
1138
+ });
1072
1139
  }
1073
- }
1074
- return {
1075
- value: current,
1076
- type: Array.isArray(current) ? "array" : typeof current
1077
- };
1078
- }).build();
1079
- 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({
1080
- json: z.string().describe("JSON string to validate")
1081
- })).implementSafe(async (input) => {
1082
- JSON.parse(input.json);
1083
- return {
1084
- valid: true,
1085
- message: "Valid JSON"
1086
- };
1087
- }).build();
1088
- 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({
1089
- objects: z.array(z.any().describe("Object to merge")).describe("Array of objects to merge"),
1090
- deep: z.boolean().default(false).describe("Perform deep merge (nested objects)")
1091
- })).implement(async (input) => {
1092
- if (input.deep) {
1093
- const deepMerge = (target, source) => {
1094
- const output = { ...target };
1095
- for (const key in source) {
1096
- if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
1097
- output[key] = deepMerge(output[key] || {}, source[key]);
1098
- } else {
1099
- output[key] = source[key];
1140
+ }).build();
1141
+ }
1142
+ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger4) {
1143
+ return toolBuilder().name("list-confluence-spaces").description("List all available Confluence spaces. Returns space names, keys, types, and descriptions to help identify where to search for information.").category(ToolCategory.WEB).tag("confluence").tag("spaces").tag("list").usageNotes("Use this first to discover available spaces before searching. Helps narrow down searches to specific areas (e.g., 'AI', 'BL3', 'Finance').").follows(["search-confluence"]).schema(z.object({
1144
+ limit: z.number().optional().describe("Maximum number of spaces to return (default: 25)")
1145
+ })).implement(async ({ limit = 25 }) => {
1146
+ logger4.info("list-confluence-spaces called", { limit });
1147
+ try {
1148
+ const { ATLASSIAN_SITE_URL } = getAuth();
1149
+ const response = await axios12.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/space`, {
1150
+ headers: {
1151
+ Authorization: getAuthHeader2(),
1152
+ Accept: "application/json"
1153
+ },
1154
+ params: {
1155
+ limit
1156
+ }
1157
+ });
1158
+ const spaces = response.data.results.map((space) => ({
1159
+ key: space.key,
1160
+ name: space.name,
1161
+ type: space.type,
1162
+ description: space.description?.plain?.value || "",
1163
+ url: `${ATLASSIAN_SITE_URL}/wiki${space._links.webui}`
1164
+ }));
1165
+ logger4.info("list-confluence-spaces result", {
1166
+ spaceCount: spaces.length,
1167
+ spaceKeys: spaces.map((s) => s.key).slice(0, 5)
1168
+ // Log first 5 space keys
1169
+ });
1170
+ return JSON.stringify({
1171
+ success: true,
1172
+ count: spaces.length,
1173
+ spaces
1174
+ });
1175
+ } catch (error) {
1176
+ logger4.error("list-confluence-spaces error", {
1177
+ error: error.response?.data?.message || error.message,
1178
+ status: error.response?.status
1179
+ });
1180
+ return JSON.stringify({
1181
+ success: false,
1182
+ error: error.response?.data?.message || error.message
1183
+ });
1184
+ }
1185
+ }).build();
1186
+ }
1187
+ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger4) {
1188
+ return toolBuilder().name("get-space-pages").description("Get all pages from a specific Confluence space by space key. Useful for browsing content in a particular area.").category(ToolCategory.WEB).tag("confluence").tag("space").tag("pages").usageNotes("Use this to explore all pages in a specific space. Get the space key from list-confluence-spaces first.").requires(["list-confluence-spaces"]).schema(z.object({
1189
+ space_key: z.string().describe("The space key (e.g., 'AI', 'BL3', 'FIN')"),
1190
+ limit: z.number().optional().describe("Maximum number of pages to return (default: 25)")
1191
+ })).implement(async ({ space_key, limit = 25 }) => {
1192
+ logger4.info("get-space-pages called", { space_key, limit });
1193
+ try {
1194
+ const { ATLASSIAN_SITE_URL } = getAuth();
1195
+ const response = await axios12.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content`, {
1196
+ headers: {
1197
+ Authorization: getAuthHeader2(),
1198
+ Accept: "application/json"
1199
+ },
1200
+ params: {
1201
+ spaceKey: space_key,
1202
+ type: "page",
1203
+ limit,
1204
+ expand: "version"
1100
1205
  }
1206
+ });
1207
+ const pages = response.data.results.map((page) => ({
1208
+ id: page.id,
1209
+ title: page.title,
1210
+ url: `${ATLASSIAN_SITE_URL}/wiki${page._links.webui}`,
1211
+ lastModified: page.version?.when || ""
1212
+ }));
1213
+ if (pages.length === 0) {
1214
+ logger4.warn("get-space-pages returned NO PAGES - this is a valid outcome, agent should not retry", {
1215
+ space_key,
1216
+ limit
1217
+ });
1218
+ } else {
1219
+ logger4.info("get-space-pages result", {
1220
+ space_key,
1221
+ pageCount: pages.length,
1222
+ titles: pages.map((p) => p.title).slice(0, 3)
1223
+ // Log first 3 titles
1224
+ });
1101
1225
  }
1102
- return output;
1103
- };
1104
- return input.objects.reduce((acc, obj) => deepMerge(acc, obj), {});
1105
- } else {
1106
- return Object.assign({}, ...input.objects);
1107
- }
1108
- }).build();
1109
- var csvParser = toolBuilder().name("csv-parser").description("Parse CSV string into an array of objects. Supports custom delimiters, headers, and options.").category(ToolCategory.UTILITY).tags(["csv", "parse", "data", "table"]).schema(z.object({
1226
+ return JSON.stringify({
1227
+ success: true,
1228
+ space: space_key,
1229
+ count: pages.length,
1230
+ pages
1231
+ });
1232
+ } catch (error) {
1233
+ logger4.error("get-space-pages error", {
1234
+ space_key,
1235
+ error: error.response?.data?.message || error.message,
1236
+ status: error.response?.status
1237
+ });
1238
+ return JSON.stringify({
1239
+ success: false,
1240
+ error: error.response?.data?.message || error.message
1241
+ });
1242
+ }
1243
+ }).build();
1244
+ }
1245
+ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger4) {
1246
+ return toolBuilder().name("create-confluence-page").description("Create a new page in a Confluence space. Requires space key, page title, and content (in HTML storage format).").category(ToolCategory.WEB).tag("confluence").tag("create").tag("write").usageNotes("Use this to create new documentation pages. Content should be in Confluence storage format (HTML). Get the space key from list-confluence-spaces first. Be mindful of creating duplicate pages.").requires(["list-confluence-spaces"]).schema(z.object({
1247
+ space_key: z.string().describe("The space key where the page will be created (e.g., 'AI', 'BL3')"),
1248
+ title: z.string().describe("The title of the new page"),
1249
+ content: z.string().describe("The page content in HTML format (Confluence storage format)"),
1250
+ parent_page_id: z.string().optional().describe("Optional parent page ID to create this as a child page")
1251
+ })).implement(async ({ space_key, title, content, parent_page_id }) => {
1252
+ logger4.info("create-confluence-page called", { space_key, title, hasParent: !!parent_page_id });
1253
+ try {
1254
+ const { ATLASSIAN_SITE_URL } = getAuth();
1255
+ const pageData = {
1256
+ type: "page",
1257
+ title,
1258
+ space: { key: space_key },
1259
+ body: {
1260
+ storage: {
1261
+ value: content,
1262
+ representation: "storage"
1263
+ }
1264
+ }
1265
+ };
1266
+ if (parent_page_id) {
1267
+ pageData.ancestors = [{ id: parent_page_id }];
1268
+ }
1269
+ const response = await axios12.post(
1270
+ `${ATLASSIAN_SITE_URL}/wiki/rest/api/content`,
1271
+ pageData,
1272
+ {
1273
+ headers: {
1274
+ Authorization: getAuthHeader2(),
1275
+ "Content-Type": "application/json"
1276
+ }
1277
+ }
1278
+ );
1279
+ logger4.info("create-confluence-page result", {
1280
+ page_id: response.data.id,
1281
+ title: response.data.title,
1282
+ space: space_key
1283
+ });
1284
+ return JSON.stringify({
1285
+ success: true,
1286
+ page: {
1287
+ id: response.data.id,
1288
+ title: response.data.title,
1289
+ space: space_key,
1290
+ url: `${ATLASSIAN_SITE_URL}/wiki${response.data._links.webui}`,
1291
+ version: response.data.version?.number || 1
1292
+ }
1293
+ });
1294
+ } catch (error) {
1295
+ logger4.error("create-confluence-page error", {
1296
+ space_key,
1297
+ title,
1298
+ error: error.response?.data?.message || error.message,
1299
+ status: error.response?.status
1300
+ });
1301
+ return JSON.stringify({
1302
+ success: false,
1303
+ error: error.response?.data?.message || error.message
1304
+ });
1305
+ }
1306
+ }).build();
1307
+ }
1308
+ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger4) {
1309
+ return toolBuilder().name("update-confluence-page").description("Update an existing Confluence page's content. Requires page ID, new title, and new content.").category(ToolCategory.WEB).tag("confluence").tag("update").tag("write").usageNotes("Use this to update existing documentation. You must provide the page ID (from search results). The tool will automatically handle version incrementing. Always get the current page content first to avoid overwriting important information.").requires(["get-confluence-page"]).schema(z.object({
1310
+ page_id: z.string().describe("The ID of the page to update"),
1311
+ title: z.string().describe("The new title for the page"),
1312
+ content: z.string().describe("The new content in HTML format (Confluence storage format)")
1313
+ })).implement(async ({ page_id, title, content }) => {
1314
+ logger4.info("update-confluence-page called", { page_id, title });
1315
+ try {
1316
+ const { ATLASSIAN_SITE_URL } = getAuth();
1317
+ const getResponse = await axios12.get(
1318
+ `${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`,
1319
+ {
1320
+ headers: {
1321
+ Authorization: getAuthHeader2()
1322
+ },
1323
+ params: { expand: "version" }
1324
+ }
1325
+ );
1326
+ const currentVersion = getResponse.data.version.number;
1327
+ const updateResponse = await axios12.put(
1328
+ `${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`,
1329
+ {
1330
+ type: "page",
1331
+ title,
1332
+ version: { number: currentVersion + 1 },
1333
+ body: {
1334
+ storage: {
1335
+ value: content,
1336
+ representation: "storage"
1337
+ }
1338
+ }
1339
+ },
1340
+ {
1341
+ headers: {
1342
+ Authorization: getAuthHeader2(),
1343
+ "Content-Type": "application/json"
1344
+ }
1345
+ }
1346
+ );
1347
+ logger4.info("update-confluence-page result", {
1348
+ page_id,
1349
+ title: updateResponse.data.title,
1350
+ previousVersion: currentVersion,
1351
+ newVersion: updateResponse.data.version.number
1352
+ });
1353
+ return JSON.stringify({
1354
+ success: true,
1355
+ page: {
1356
+ id: updateResponse.data.id,
1357
+ title: updateResponse.data.title,
1358
+ url: `${ATLASSIAN_SITE_URL}/wiki${updateResponse.data._links.webui}`,
1359
+ version: updateResponse.data.version.number,
1360
+ previousVersion: currentVersion
1361
+ }
1362
+ });
1363
+ } catch (error) {
1364
+ logger4.error("update-confluence-page error", {
1365
+ page_id,
1366
+ title,
1367
+ error: error.response?.data?.message || error.message,
1368
+ status: error.response?.status
1369
+ });
1370
+ return JSON.stringify({
1371
+ success: false,
1372
+ error: error.response?.data?.message || error.message
1373
+ });
1374
+ }
1375
+ }).build();
1376
+ }
1377
+ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger4) {
1378
+ return toolBuilder().name("archive-confluence-page").description("Archive a Confluence page by moving it to trash. The page can be restored by space admins. Note: UI may require a note explaining why the page was archived.").category(ToolCategory.WEB).tag("confluence").tag("archive").tag("delete").usageNotes("Use this to archive outdated or obsolete documentation. The page is moved to trash, not permanently deleted. Space admins can restore it if needed. Be very careful - only archive pages that are truly obsolete.").conflicts(["create-confluence-page"]).schema(z.object({
1379
+ page_id: z.string().describe("The ID of the page to archive"),
1380
+ reason: z.string().optional().describe("Optional reason for archiving (for audit trail)")
1381
+ })).implement(async ({ page_id, reason }) => {
1382
+ logger4.info("archive-confluence-page called", { page_id, reason });
1383
+ try {
1384
+ const { ATLASSIAN_SITE_URL } = getAuth();
1385
+ const getResponse = await axios12.get(
1386
+ `${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`,
1387
+ {
1388
+ headers: {
1389
+ Authorization: getAuthHeader2()
1390
+ },
1391
+ params: { expand: "version,body.storage,space" }
1392
+ }
1393
+ );
1394
+ const currentVersion = getResponse.data.version.number;
1395
+ const pageData = getResponse.data;
1396
+ await axios12.put(
1397
+ `${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`,
1398
+ {
1399
+ version: { number: currentVersion + 1 },
1400
+ title: pageData.title,
1401
+ type: "page",
1402
+ status: "trashed",
1403
+ body: pageData.body,
1404
+ space: { key: pageData.space.key }
1405
+ },
1406
+ {
1407
+ headers: {
1408
+ Authorization: getAuthHeader2(),
1409
+ "Content-Type": "application/json"
1410
+ }
1411
+ }
1412
+ );
1413
+ logger4.info("archive-confluence-page result", {
1414
+ page_id,
1415
+ title: pageData.title,
1416
+ previousVersion: currentVersion,
1417
+ newVersion: currentVersion + 1
1418
+ });
1419
+ return JSON.stringify({
1420
+ success: true,
1421
+ archived: {
1422
+ id: page_id,
1423
+ title: pageData.title,
1424
+ previousVersion: currentVersion,
1425
+ newVersion: currentVersion + 1,
1426
+ reason: reason || "Archived via API",
1427
+ note: "Page moved to trash. Space admins can restore it from the Confluence UI."
1428
+ }
1429
+ });
1430
+ } catch (error) {
1431
+ logger4.error("archive-confluence-page error", {
1432
+ page_id,
1433
+ error: error.response?.data?.message || error.message,
1434
+ status: error.response?.status
1435
+ });
1436
+ return JSON.stringify({
1437
+ success: false,
1438
+ error: error.response?.data?.message || error.message
1439
+ });
1440
+ }
1441
+ }).build();
1442
+ }
1443
+
1444
+ // src/web/confluence/index.ts
1445
+ var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
1446
+ var logger2 = createLogger("[tools:confluence]", { level: logLevel2 });
1447
+ var searchConfluence = createSearchConfluenceTool(getConfig, getAuthHeader, logger2);
1448
+ var getConfluencePage = createGetConfluencePageTool(getConfig, getAuthHeader, logger2);
1449
+ var listConfluenceSpaces = createListConfluenceSpacesTool(getConfig, getAuthHeader, logger2);
1450
+ var getSpacePages = createGetSpacePagesTool(getConfig, getAuthHeader, logger2);
1451
+ var createConfluencePage = createCreateConfluencePageTool(getConfig, getAuthHeader, logger2);
1452
+ var updateConfluencePage = createUpdateConfluencePageTool(getConfig, getAuthHeader, logger2);
1453
+ var archiveConfluencePage = createArchiveConfluencePageTool(getConfig, getAuthHeader, logger2);
1454
+ var confluenceTools = [
1455
+ // Read tools
1456
+ searchConfluence,
1457
+ getConfluencePage,
1458
+ listConfluenceSpaces,
1459
+ getSpacePages,
1460
+ // Write tools
1461
+ createConfluencePage,
1462
+ updateConfluencePage,
1463
+ archiveConfluencePage
1464
+ ];
1465
+ function createConfluenceTools(config = {}) {
1466
+ const {
1467
+ apiKey,
1468
+ email,
1469
+ siteUrl,
1470
+ logLevel: customLogLevel
1471
+ } = config;
1472
+ const getConfiguredAuth = createGetConfiguredAuth(apiKey, email, siteUrl);
1473
+ const getConfiguredAuthHeader = createGetConfiguredAuthHeader(getConfiguredAuth);
1474
+ const toolLogger = customLogLevel ? createLogger("tools:confluence", { level: customLogLevel }) : logger2;
1475
+ const searchConfluence2 = createSearchConfluenceTool(getConfiguredAuth, getConfiguredAuthHeader, toolLogger);
1476
+ const getConfluencePage2 = createGetConfluencePageTool(getConfiguredAuth, getConfiguredAuthHeader, toolLogger);
1477
+ const listConfluenceSpaces2 = createListConfluenceSpacesTool(getConfiguredAuth, getConfiguredAuthHeader, toolLogger);
1478
+ const getSpacePages2 = createGetSpacePagesTool(getConfiguredAuth, getConfiguredAuthHeader, toolLogger);
1479
+ const createConfluencePage2 = createCreateConfluencePageTool(getConfiguredAuth, getConfiguredAuthHeader, toolLogger);
1480
+ const updateConfluencePage2 = createUpdateConfluencePageTool(getConfiguredAuth, getConfiguredAuthHeader, toolLogger);
1481
+ const archiveConfluencePage2 = createArchiveConfluencePageTool(getConfiguredAuth, getConfiguredAuthHeader, toolLogger);
1482
+ return {
1483
+ searchConfluence: searchConfluence2,
1484
+ getConfluencePage: getConfluencePage2,
1485
+ listConfluenceSpaces: listConfluenceSpaces2,
1486
+ getSpacePages: getSpacePages2,
1487
+ createConfluencePage: createConfluencePage2,
1488
+ updateConfluencePage: updateConfluencePage2,
1489
+ archiveConfluencePage: archiveConfluencePage2
1490
+ };
1491
+ }
1492
+ var csvParserSchema = z.object({
1110
1493
  csv: z.string().describe("CSV string to parse"),
1111
1494
  delimiter: z.string().default(",").describe("Column delimiter character"),
1112
1495
  hasHeaders: z.boolean().default(true).describe("First row contains column headers"),
1113
1496
  skipEmptyLines: z.boolean().default(true).describe("Skip empty lines in the CSV"),
1114
1497
  trim: z.boolean().default(true).describe("Trim whitespace from values")
1115
- })).implement(async (input) => {
1116
- try {
1117
- const records = parse(input.csv, {
1118
- delimiter: input.delimiter,
1119
- columns: input.hasHeaders,
1120
- skip_empty_lines: input.skipEmptyLines,
1121
- trim: input.trim,
1122
- relax_column_count: true
1123
- });
1124
- return {
1125
- success: true,
1126
- data: records,
1127
- rowCount: records.length,
1128
- columnCount: records.length > 0 ? Object.keys(records[0]).length : 0
1129
- };
1130
- } catch (error) {
1131
- return {
1132
- success: false,
1133
- error: error instanceof Error ? error.message : "Failed to parse CSV"
1134
- };
1135
- }
1136
- }).build();
1137
- var csvGenerator = toolBuilder().name("csv-generator").description("Convert an array of objects to CSV string. Automatically extracts headers from object keys.").category(ToolCategory.UTILITY).tags(["csv", "generate", "stringify", "data"]).schema(z.object({
1498
+ });
1499
+ var csvGeneratorSchema = z.object({
1138
1500
  data: z.array(z.record(z.any().describe("Column value"))).describe("Array of objects to convert to CSV"),
1139
1501
  delimiter: z.string().default(",").describe("Column delimiter character"),
1140
1502
  includeHeaders: z.boolean().default(true).describe("Include header row with column names"),
1141
1503
  columns: z.array(z.string().describe("String value")).optional().describe("Optional list of columns to include (in order)")
1142
- })).implement(async (input) => {
1143
- try {
1144
- const csv = stringify(input.data, {
1145
- delimiter: input.delimiter,
1146
- header: input.includeHeaders,
1147
- columns: input.columns
1148
- });
1149
- return {
1150
- success: true,
1151
- csv,
1152
- rowCount: input.data.length
1153
- };
1154
- } catch (error) {
1155
- return {
1156
- success: false,
1157
- error: error instanceof Error ? error.message : "Failed to generate CSV"
1158
- };
1159
- }
1160
- }).build();
1161
- var csvToJson = toolBuilder().name("csv-to-json").description("Convert CSV string to JSON array. Each row becomes an object with column headers as keys.").category(ToolCategory.UTILITY).tags(["csv", "json", "convert", "data"]).schema(z.object({
1504
+ });
1505
+ var csvToJsonSchema = z.object({
1162
1506
  csv: z.string().describe("CSV string to convert"),
1163
1507
  delimiter: z.string().default(",").describe("Column delimiter character"),
1164
1508
  pretty: z.boolean().default(false).describe("Format JSON with indentation")
1165
- })).implement(async (input) => {
1166
- try {
1167
- const records = parse(input.csv, {
1168
- delimiter: input.delimiter,
1169
- columns: true,
1170
- skip_empty_lines: true,
1171
- trim: true
1172
- });
1173
- const json = input.pretty ? JSON.stringify(records, null, 2) : JSON.stringify(records);
1174
- return {
1175
- success: true,
1176
- json,
1177
- recordCount: records.length
1178
- };
1179
- } catch (error) {
1180
- return {
1181
- success: false,
1182
- error: error instanceof Error ? error.message : "Failed to convert CSV to JSON"
1183
- };
1184
- }
1185
- }).build();
1186
- var jsonToCsv = toolBuilder().name("json-to-csv").description("Convert JSON array to CSV string. Each object becomes a row with keys as column headers.").category(ToolCategory.UTILITY).tags(["json", "csv", "convert", "data"]).schema(z.object({
1509
+ });
1510
+ var jsonToCsvSchema = z.object({
1187
1511
  json: z.string().describe("JSON array string to convert"),
1188
1512
  delimiter: z.string().default(",").describe("Column delimiter character")
1189
- })).implement(async (input) => {
1190
- try {
1191
- const data = JSON.parse(input.json);
1192
- if (!Array.isArray(data)) {
1513
+ });
1514
+ function createCsvParserTool(defaultDelimiter = ",", defaultHasHeaders = true, defaultSkipEmptyLines = true, defaultTrim = true) {
1515
+ return toolBuilder().name("csv-parser").description("Parse CSV string into an array of objects. Supports custom delimiters, headers, and options.").category(ToolCategory.UTILITY).tags(["csv", "parse", "data", "table"]).schema(csvParserSchema).implement(async (input) => {
1516
+ try {
1517
+ const records = parse(input.csv, {
1518
+ delimiter: input.delimiter ?? defaultDelimiter,
1519
+ columns: input.hasHeaders ?? defaultHasHeaders,
1520
+ skip_empty_lines: input.skipEmptyLines ?? defaultSkipEmptyLines,
1521
+ trim: input.trim ?? defaultTrim,
1522
+ relax_column_count: true
1523
+ });
1524
+ return {
1525
+ success: true,
1526
+ data: records,
1527
+ rowCount: records.length,
1528
+ columnCount: records.length > 0 ? Object.keys(records[0]).length : 0
1529
+ };
1530
+ } catch (error) {
1193
1531
  return {
1194
1532
  success: false,
1195
- error: "Input must be a JSON array"
1533
+ error: error instanceof Error ? error.message : "Failed to parse CSV"
1196
1534
  };
1197
1535
  }
1198
- const csv = stringify(data, {
1199
- delimiter: input.delimiter,
1200
- header: true
1201
- });
1536
+ }).build();
1537
+ }
1538
+ function createCsvGeneratorTool(defaultDelimiter = ",") {
1539
+ return toolBuilder().name("csv-generator").description("Convert an array of objects to CSV string. Automatically extracts headers from object keys.").category(ToolCategory.UTILITY).tags(["csv", "generate", "stringify", "data"]).schema(csvGeneratorSchema).implement(async (input) => {
1540
+ try {
1541
+ const csv = stringify(input.data, {
1542
+ delimiter: input.delimiter ?? defaultDelimiter,
1543
+ header: input.includeHeaders,
1544
+ columns: input.columns
1545
+ });
1546
+ return {
1547
+ success: true,
1548
+ csv,
1549
+ rowCount: input.data.length
1550
+ };
1551
+ } catch (error) {
1552
+ return {
1553
+ success: false,
1554
+ error: error instanceof Error ? error.message : "Failed to generate CSV"
1555
+ };
1556
+ }
1557
+ }).build();
1558
+ }
1559
+ function createCsvToJsonTool(defaultDelimiter = ",") {
1560
+ return toolBuilder().name("csv-to-json").description("Convert CSV string to JSON array. Each row becomes an object with column headers as keys.").category(ToolCategory.UTILITY).tags(["csv", "json", "convert", "data"]).schema(csvToJsonSchema).implement(async (input) => {
1561
+ try {
1562
+ const records = parse(input.csv, {
1563
+ delimiter: input.delimiter ?? defaultDelimiter,
1564
+ columns: true,
1565
+ skip_empty_lines: true,
1566
+ trim: true
1567
+ });
1568
+ const json = input.pretty ? JSON.stringify(records, null, 2) : JSON.stringify(records);
1569
+ return {
1570
+ success: true,
1571
+ json,
1572
+ recordCount: records.length
1573
+ };
1574
+ } catch (error) {
1575
+ return {
1576
+ success: false,
1577
+ error: error instanceof Error ? error.message : "Failed to convert CSV to JSON"
1578
+ };
1579
+ }
1580
+ }).build();
1581
+ }
1582
+ function createJsonToCsvTool(defaultDelimiter = ",") {
1583
+ return toolBuilder().name("json-to-csv").description("Convert JSON array to CSV string. Each object becomes a row with keys as column headers.").category(ToolCategory.UTILITY).tags(["json", "csv", "convert", "data"]).schema(jsonToCsvSchema).implement(async (input) => {
1584
+ try {
1585
+ const data = JSON.parse(input.json);
1586
+ if (!Array.isArray(data)) {
1587
+ return {
1588
+ success: false,
1589
+ error: "Input must be a JSON array"
1590
+ };
1591
+ }
1592
+ const csv = stringify(data, {
1593
+ delimiter: input.delimiter ?? defaultDelimiter,
1594
+ header: true
1595
+ });
1596
+ return {
1597
+ success: true,
1598
+ csv,
1599
+ rowCount: data.length
1600
+ };
1601
+ } catch (error) {
1602
+ return {
1603
+ success: false,
1604
+ error: error instanceof Error ? error.message : "Failed to convert JSON to CSV"
1605
+ };
1606
+ }
1607
+ }).build();
1608
+ }
1609
+
1610
+ // src/data/csv/index.ts
1611
+ var csvParser = createCsvParserTool();
1612
+ var csvGenerator = createCsvGeneratorTool();
1613
+ var csvToJson = createCsvToJsonTool();
1614
+ var jsonToCsv = createJsonToCsvTool();
1615
+ var csvTools = [csvParser, csvGenerator, csvToJson, jsonToCsv];
1616
+ function createCsvTools(config = {}) {
1617
+ const {
1618
+ defaultDelimiter = ",",
1619
+ defaultHasHeaders = true,
1620
+ defaultSkipEmptyLines = true,
1621
+ defaultTrim = true
1622
+ } = config;
1623
+ return [
1624
+ createCsvParserTool(defaultDelimiter, defaultHasHeaders, defaultSkipEmptyLines, defaultTrim),
1625
+ createCsvGeneratorTool(defaultDelimiter),
1626
+ createCsvToJsonTool(defaultDelimiter),
1627
+ createJsonToCsvTool(defaultDelimiter)
1628
+ ];
1629
+ }
1630
+ var jsonParserSchema = z.object({
1631
+ json: z.string().describe("JSON string to parse"),
1632
+ strict: z.boolean().default(true).describe("Use strict JSON parsing (no trailing commas, etc.)")
1633
+ });
1634
+ var jsonStringifySchema = z.object({
1635
+ data: z.any().describe("Data to convert to JSON string"),
1636
+ pretty: z.boolean().default(false).describe("Format with indentation for readability"),
1637
+ indent: z.number().default(2).describe("Number of spaces for indentation (when pretty is true)")
1638
+ });
1639
+ var jsonQuerySchema = z.object({
1640
+ data: z.any().describe("JSON data to query"),
1641
+ path: z.string().describe('Dot notation path to query (e.g., "user.name" or "items[0].id")')
1642
+ });
1643
+ var jsonValidatorSchema = z.object({
1644
+ json: z.string().describe("JSON string to validate")
1645
+ });
1646
+ var jsonMergeSchema = z.object({
1647
+ objects: z.array(z.any().describe("Object to merge")).describe("Array of objects to merge"),
1648
+ deep: z.boolean().default(false).describe("Perform deep merge (nested objects)")
1649
+ });
1650
+ function createJsonParserTool() {
1651
+ return 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(jsonParserSchema).implementSafe(async (input) => {
1652
+ const parsed = JSON.parse(input.json);
1202
1653
  return {
1203
- success: true,
1204
- csv,
1205
- rowCount: data.length
1654
+ data: parsed,
1655
+ type: Array.isArray(parsed) ? "array" : typeof parsed
1206
1656
  };
1207
- } catch (error) {
1657
+ }).build();
1658
+ }
1659
+ function createJsonStringifyTool(defaultIndent = 2, defaultPretty = false) {
1660
+ return 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(jsonStringifySchema).implementSafe(async (input) => {
1661
+ const pretty = input.pretty ?? defaultPretty;
1662
+ const indent = input.indent ?? defaultIndent;
1663
+ const json = pretty ? JSON.stringify(input.data, null, indent) : JSON.stringify(input.data);
1208
1664
  return {
1209
- success: false,
1210
- error: error instanceof Error ? error.message : "Failed to convert JSON to CSV"
1665
+ json,
1666
+ length: json.length
1211
1667
  };
1212
- }
1213
- }).build();
1214
- var xmlParser = toolBuilder().name("xml-parser").description("Parse XML string into a JavaScript object. Supports attributes, CDATA, and nested elements.").category(ToolCategory.UTILITY).tags(["xml", "parse", "data"]).schema(z.object({
1215
- xml: z.string().describe("XML string to parse"),
1216
- ignoreAttributes: z.boolean().default(false).describe("Ignore XML attributes"),
1217
- parseAttributeValue: z.boolean().default(true).describe("Parse attribute values (numbers, booleans)"),
1218
- trimValues: z.boolean().default(true).describe("Trim whitespace from text values")
1219
- })).implement(async (input) => {
1220
- try {
1221
- const parser = new XMLParser({
1222
- ignoreAttributes: input.ignoreAttributes,
1223
- parseAttributeValue: input.parseAttributeValue,
1224
- trimValues: input.trimValues,
1225
- parseTagValue: true
1226
- });
1227
- const result = parser.parse(input.xml);
1668
+ }).build();
1669
+ }
1670
+ function createJsonQueryTool() {
1671
+ return 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(jsonQuerySchema).implementSafe(async (input) => {
1672
+ const parts = input.path.split(".");
1673
+ let current = input.data;
1674
+ for (const part of parts) {
1675
+ const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
1676
+ if (arrayMatch) {
1677
+ const [, key, index] = arrayMatch;
1678
+ current = current[key][parseInt(index, 10)];
1679
+ } else {
1680
+ current = current[part];
1681
+ }
1682
+ if (current === void 0) {
1683
+ throw new Error(`Path not found: ${input.path}`);
1684
+ }
1685
+ }
1228
1686
  return {
1229
- success: true,
1230
- data: result
1687
+ value: current,
1688
+ type: Array.isArray(current) ? "array" : typeof current
1231
1689
  };
1232
- } catch (error) {
1690
+ }).build();
1691
+ }
1692
+ function createJsonValidatorTool() {
1693
+ return 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(jsonValidatorSchema).implementSafe(async (input) => {
1694
+ JSON.parse(input.json);
1233
1695
  return {
1234
- success: false,
1235
- error: error instanceof Error ? error.message : "Failed to parse XML"
1696
+ valid: true,
1697
+ message: "Valid JSON"
1236
1698
  };
1237
- }
1238
- }).build();
1239
- var xmlGenerator = toolBuilder().name("xml-generator").description("Convert a JavaScript object to XML string. Supports attributes, CDATA, and nested elements.").category(ToolCategory.UTILITY).tags(["xml", "generate", "stringify", "data"]).schema(z.object({
1699
+ }).build();
1700
+ }
1701
+ function createJsonMergeTool() {
1702
+ return 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(jsonMergeSchema).implement(async (input) => {
1703
+ if (input.deep) {
1704
+ const deepMerge = (target, source) => {
1705
+ const output = { ...target };
1706
+ for (const key in source) {
1707
+ if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
1708
+ output[key] = deepMerge(output[key] || {}, source[key]);
1709
+ } else {
1710
+ output[key] = source[key];
1711
+ }
1712
+ }
1713
+ return output;
1714
+ };
1715
+ return input.objects.reduce((acc, obj) => deepMerge(acc, obj), {});
1716
+ } else {
1717
+ return Object.assign({}, ...input.objects);
1718
+ }
1719
+ }).build();
1720
+ }
1721
+
1722
+ // src/data/json/index.ts
1723
+ var jsonParser = createJsonParserTool();
1724
+ var jsonStringify = createJsonStringifyTool();
1725
+ var jsonQuery = createJsonQueryTool();
1726
+ var jsonValidator = createJsonValidatorTool();
1727
+ var jsonMerge = createJsonMergeTool();
1728
+ var jsonTools = [jsonParser, jsonStringify, jsonQuery, jsonValidator, jsonMerge];
1729
+ function createJsonTools(config = {}) {
1730
+ const {
1731
+ defaultIndent = 2,
1732
+ defaultPretty = false
1733
+ } = config;
1734
+ return [
1735
+ createJsonParserTool(),
1736
+ createJsonStringifyTool(defaultIndent, defaultPretty),
1737
+ createJsonQueryTool(),
1738
+ createJsonValidatorTool(),
1739
+ createJsonMergeTool()
1740
+ ];
1741
+ }
1742
+ var xmlParserSchema = z.object({
1743
+ xml: z.string().describe("XML string to parse"),
1744
+ ignoreAttributes: z.boolean().default(false).describe("Ignore XML attributes"),
1745
+ parseAttributeValue: z.boolean().default(true).describe("Parse attribute values (numbers, booleans)"),
1746
+ trimValues: z.boolean().default(true).describe("Trim whitespace from text values")
1747
+ });
1748
+ var xmlGeneratorSchema = z.object({
1240
1749
  data: z.any().describe("Object to convert to XML"),
1241
1750
  rootName: z.string().default("root").describe("Name of the root XML element"),
1242
1751
  format: z.boolean().default(false).describe("Format XML with indentation"),
1243
1752
  indentSize: z.number().default(2).describe("Number of spaces for indentation (when format is true)")
1244
- })).implement(async (input) => {
1245
- try {
1246
- const indentSize = input.indentSize ?? 2;
1247
- const rootName = input.rootName ?? "root";
1248
- const builder = new XMLBuilder({
1249
- format: input.format ?? false,
1250
- indentBy: " ".repeat(indentSize),
1251
- ignoreAttributes: false
1252
- });
1253
- const dataToConvert = input.data[rootName] ? input.data : { [rootName]: input.data };
1254
- const xml = builder.build(dataToConvert);
1255
- return {
1256
- success: true,
1257
- xml
1258
- };
1259
- } catch (error) {
1260
- return {
1261
- success: false,
1262
- error: error instanceof Error ? error.message : "Failed to generate XML"
1263
- };
1264
- }
1265
- }).build();
1266
- var xmlToJson = toolBuilder().name("xml-to-json").description("Convert XML string to JSON. Preserves structure and can include or exclude attributes.").category(ToolCategory.UTILITY).tags(["xml", "json", "convert", "data"]).schema(z.object({
1753
+ });
1754
+ var xmlToJsonSchema = z.object({
1267
1755
  xml: z.string().describe("XML string to convert"),
1268
1756
  ignoreAttributes: z.boolean().default(false).describe("Ignore XML attributes in conversion"),
1269
1757
  pretty: z.boolean().default(false).describe("Format JSON with indentation")
1270
- })).implement(async (input) => {
1271
- try {
1272
- const parser = new XMLParser({
1273
- ignoreAttributes: input.ignoreAttributes,
1274
- parseAttributeValue: true,
1275
- trimValues: true
1276
- });
1277
- const result = parser.parse(input.xml);
1278
- const json = input.pretty ? JSON.stringify(result, null, 2) : JSON.stringify(result);
1279
- return {
1280
- success: true,
1281
- json
1282
- };
1283
- } catch (error) {
1284
- return {
1285
- success: false,
1286
- error: error instanceof Error ? error.message : "Failed to convert XML to JSON"
1287
- };
1288
- }
1289
- }).build();
1290
- var jsonToXml = toolBuilder().name("json-to-xml").description("Convert JSON string to XML. Each object key becomes an XML element.").category(ToolCategory.UTILITY).tags(["json", "xml", "convert", "data"]).schema(z.object({
1758
+ });
1759
+ var jsonToXmlSchema = z.object({
1291
1760
  json: z.string().describe("JSON string to convert"),
1292
1761
  rootName: z.string().default("root").describe("Name of the root XML element"),
1293
1762
  format: z.boolean().default(false).describe("Format XML with indentation")
1294
- })).implement(async (input) => {
1295
- try {
1296
- const data = JSON.parse(input.json);
1297
- const rootName = input.rootName ?? "root";
1298
- const builder = new XMLBuilder({
1299
- format: input.format ?? false,
1300
- indentBy: " ",
1301
- ignoreAttributes: false
1302
- });
1303
- const dataToConvert = data[rootName] ? data : { [rootName]: data };
1304
- const xml = builder.build(dataToConvert);
1305
- return {
1306
- success: true,
1307
- xml
1308
- };
1309
- } catch (error) {
1310
- return {
1311
- success: false,
1312
- error: error instanceof Error ? error.message : "Failed to convert JSON to XML"
1313
- };
1314
- }
1315
- }).build();
1316
- var arrayFilter = toolBuilder().name("array-filter").description("Filter an array based on a property value. Supports equality, comparison, and contains operations.").category(ToolCategory.UTILITY).tags(["array", "filter", "data", "transform"]).schema(z.object({
1763
+ });
1764
+ function createXmlParserTool() {
1765
+ return toolBuilder().name("xml-parser").description("Parse XML string into a JavaScript object. Supports attributes, CDATA, and nested elements.").category(ToolCategory.UTILITY).tags(["xml", "parse", "data"]).schema(xmlParserSchema).implement(async (input) => {
1766
+ try {
1767
+ const parser = new XMLParser({
1768
+ ignoreAttributes: input.ignoreAttributes,
1769
+ parseAttributeValue: input.parseAttributeValue,
1770
+ trimValues: input.trimValues,
1771
+ parseTagValue: true
1772
+ });
1773
+ const result = parser.parse(input.xml);
1774
+ return {
1775
+ success: true,
1776
+ data: result
1777
+ };
1778
+ } catch (error) {
1779
+ return {
1780
+ success: false,
1781
+ error: error instanceof Error ? error.message : "Failed to parse XML"
1782
+ };
1783
+ }
1784
+ }).build();
1785
+ }
1786
+ function createXmlGeneratorTool(defaultRootName = "root", defaultFormat = false, defaultIndentSize = 2) {
1787
+ return toolBuilder().name("xml-generator").description("Convert a JavaScript object to XML string. Supports attributes, CDATA, and nested elements.").category(ToolCategory.UTILITY).tags(["xml", "generate", "stringify", "data"]).schema(xmlGeneratorSchema).implement(async (input) => {
1788
+ try {
1789
+ const indentSize = input.indentSize ?? defaultIndentSize;
1790
+ const rootName = input.rootName ?? defaultRootName;
1791
+ const format3 = input.format ?? defaultFormat;
1792
+ const builder = new XMLBuilder({
1793
+ format: format3,
1794
+ indentBy: " ".repeat(indentSize),
1795
+ ignoreAttributes: false
1796
+ });
1797
+ const dataToConvert = input.data[rootName] ? input.data : { [rootName]: input.data };
1798
+ const xml = builder.build(dataToConvert);
1799
+ return {
1800
+ success: true,
1801
+ xml
1802
+ };
1803
+ } catch (error) {
1804
+ return {
1805
+ success: false,
1806
+ error: error instanceof Error ? error.message : "Failed to generate XML"
1807
+ };
1808
+ }
1809
+ }).build();
1810
+ }
1811
+ function createXmlToJsonTool() {
1812
+ return toolBuilder().name("xml-to-json").description("Convert XML string to JSON. Preserves structure and can include or exclude attributes.").category(ToolCategory.UTILITY).tags(["xml", "json", "convert", "data"]).schema(xmlToJsonSchema).implement(async (input) => {
1813
+ try {
1814
+ const parser = new XMLParser({
1815
+ ignoreAttributes: input.ignoreAttributes,
1816
+ parseAttributeValue: true,
1817
+ trimValues: true
1818
+ });
1819
+ const result = parser.parse(input.xml);
1820
+ const json = input.pretty ? JSON.stringify(result, null, 2) : JSON.stringify(result);
1821
+ return {
1822
+ success: true,
1823
+ json
1824
+ };
1825
+ } catch (error) {
1826
+ return {
1827
+ success: false,
1828
+ error: error instanceof Error ? error.message : "Failed to convert XML to JSON"
1829
+ };
1830
+ }
1831
+ }).build();
1832
+ }
1833
+ function createJsonToXmlTool(defaultRootName = "root", defaultFormat = false) {
1834
+ return toolBuilder().name("json-to-xml").description("Convert JSON string to XML. Each object key becomes an XML element.").category(ToolCategory.UTILITY).tags(["json", "xml", "convert", "data"]).schema(jsonToXmlSchema).implement(async (input) => {
1835
+ try {
1836
+ const data = JSON.parse(input.json);
1837
+ const rootName = input.rootName ?? defaultRootName;
1838
+ const format3 = input.format ?? defaultFormat;
1839
+ const builder = new XMLBuilder({
1840
+ format: format3,
1841
+ indentBy: " ",
1842
+ ignoreAttributes: false
1843
+ });
1844
+ const dataToConvert = data[rootName] ? data : { [rootName]: data };
1845
+ const xml = builder.build(dataToConvert);
1846
+ return {
1847
+ success: true,
1848
+ xml
1849
+ };
1850
+ } catch (error) {
1851
+ return {
1852
+ success: false,
1853
+ error: error instanceof Error ? error.message : "Failed to convert JSON to XML"
1854
+ };
1855
+ }
1856
+ }).build();
1857
+ }
1858
+
1859
+ // src/data/xml/index.ts
1860
+ var xmlParser = createXmlParserTool();
1861
+ var xmlGenerator = createXmlGeneratorTool();
1862
+ var xmlToJson = createXmlToJsonTool();
1863
+ var jsonToXml = createJsonToXmlTool();
1864
+ var xmlTools = [xmlParser, xmlGenerator, xmlToJson, jsonToXml];
1865
+ function createXmlTools(config = {}) {
1866
+ const {
1867
+ defaultRootName = "root",
1868
+ defaultFormat = false,
1869
+ defaultIndentSize = 2
1870
+ } = config;
1871
+ return [
1872
+ createXmlParserTool(),
1873
+ createXmlGeneratorTool(defaultRootName, defaultFormat, defaultIndentSize),
1874
+ createXmlToJsonTool(),
1875
+ createJsonToXmlTool(defaultRootName, defaultFormat)
1876
+ ];
1877
+ }
1878
+ var arrayFilterSchema = z.object({
1317
1879
  array: z.array(z.any().describe("Array element")).describe("Array to filter"),
1318
1880
  property: z.string().describe("Property name to filter by (use dot notation for nested properties)"),
1319
1881
  operator: z.enum(["equals", "not-equals", "greater-than", "less-than", "contains", "starts-with", "ends-with"]).describe("Comparison operator"),
1320
1882
  value: z.any().describe("Value to compare against")
1321
- })).implement(async (input) => {
1322
- const getNestedValue = (obj, path4) => {
1323
- return path4.split(".").reduce((current, key) => current?.[key], obj);
1324
- };
1325
- const filtered = input.array.filter((item) => {
1326
- const itemValue = getNestedValue(item, input.property);
1327
- switch (input.operator) {
1328
- case "equals":
1329
- return itemValue === input.value;
1330
- case "not-equals":
1331
- return itemValue !== input.value;
1332
- case "greater-than":
1333
- return itemValue > input.value;
1334
- case "less-than":
1335
- return itemValue < input.value;
1336
- case "contains":
1337
- return String(itemValue).includes(String(input.value));
1338
- case "starts-with":
1339
- return String(itemValue).startsWith(String(input.value));
1340
- case "ends-with":
1341
- return String(itemValue).endsWith(String(input.value));
1342
- default:
1343
- return false;
1344
- }
1345
- });
1346
- return {
1347
- filtered,
1348
- originalCount: input.array.length,
1349
- filteredCount: filtered.length
1350
- };
1351
- }).build();
1352
- var arrayMap = toolBuilder().name("array-map").description("Extract specific properties from each object in an array. Creates a new array with only the selected properties.").category(ToolCategory.UTILITY).tags(["array", "map", "data", "transform"]).schema(z.object({
1883
+ });
1884
+ var arrayMapSchema = z.object({
1353
1885
  array: z.array(z.any().describe("Array element")).describe("Array to map"),
1354
1886
  properties: z.array(z.string().describe("String value")).describe("List of property names to extract from each object")
1355
- })).implement(async (input) => {
1356
- const mapped = input.array.map((item) => {
1357
- const result = {};
1358
- for (const prop of input.properties) {
1359
- const value = prop.split(".").reduce((current, key) => current?.[key], item);
1360
- result[prop] = value;
1361
- }
1362
- return result;
1363
- });
1364
- return {
1365
- mapped,
1366
- count: mapped.length
1367
- };
1368
- }).build();
1369
- var arraySort = toolBuilder().name("array-sort").description("Sort an array by a property value. Supports ascending and descending order.").category(ToolCategory.UTILITY).tags(["array", "sort", "data", "transform"]).schema(z.object({
1887
+ });
1888
+ var arraySortSchema = z.object({
1370
1889
  array: z.array(z.any().describe("Array element")).describe("Array to sort"),
1371
1890
  property: z.string().describe("Property name to sort by (use dot notation for nested properties)"),
1372
1891
  order: z.enum(["asc", "desc"]).default("asc").describe("Sort order: ascending or descending")
1373
- })).implement(async (input) => {
1374
- const getNestedValue = (obj, path4) => {
1375
- return path4.split(".").reduce((current, key) => current?.[key], obj);
1376
- };
1377
- const sorted = [...input.array].sort((a, b) => {
1378
- const aValue = getNestedValue(a, input.property);
1379
- const bValue = getNestedValue(b, input.property);
1380
- if (aValue < bValue) return input.order === "asc" ? -1 : 1;
1381
- if (aValue > bValue) return input.order === "asc" ? 1 : -1;
1382
- return 0;
1383
- });
1384
- return {
1385
- sorted,
1386
- count: sorted.length
1387
- };
1388
- }).build();
1389
- var arrayGroupBy = toolBuilder().name("array-group-by").description("Group an array of objects by a property value. Returns an object with groups as keys.").category(ToolCategory.UTILITY).tags(["array", "group", "data", "transform"]).schema(z.object({
1892
+ });
1893
+ var arrayGroupBySchema = z.object({
1390
1894
  array: z.array(z.any().describe("Array element")).describe("Array to group"),
1391
1895
  property: z.string().describe("Property name to group by")
1392
- })).implement(async (input) => {
1393
- const groups = {};
1394
- for (const item of input.array) {
1395
- const key = String(item[input.property]);
1396
- if (!groups[key]) {
1397
- groups[key] = [];
1398
- }
1399
- groups[key].push(item);
1400
- }
1401
- return {
1402
- groups,
1403
- groupCount: Object.keys(groups).length,
1404
- totalItems: input.array.length
1405
- };
1406
- }).build();
1407
- var objectPick = toolBuilder().name("object-pick").description("Create a new object with only the specified properties from the source object.").category(ToolCategory.UTILITY).tags(["object", "pick", "data", "transform"]).schema(z.object({
1896
+ });
1897
+ var objectPickSchema = z.object({
1408
1898
  object: z.record(z.any().describe("Property value")).describe("Source object"),
1409
1899
  properties: z.array(z.string().describe("String value")).describe("List of property names to pick")
1410
- })).implement(async (input) => {
1411
- const picked = {};
1412
- for (const prop of input.properties) {
1413
- if (prop in input.object) {
1414
- picked[prop] = input.object[prop];
1415
- }
1416
- }
1417
- return picked;
1418
- }).build();
1419
- var objectOmit = toolBuilder().name("object-omit").description("Create a new object excluding the specified properties from the source object.").category(ToolCategory.UTILITY).tags(["object", "omit", "data", "transform"]).schema(z.object({
1900
+ });
1901
+ var objectOmitSchema = z.object({
1420
1902
  object: z.record(z.any().describe("Property value")).describe("Source object"),
1421
1903
  properties: z.array(z.string().describe("String value")).describe("List of property names to omit")
1422
- })).implement(async (input) => {
1423
- const omitted = { ...input.object };
1424
- for (const prop of input.properties) {
1425
- delete omitted[prop];
1426
- }
1427
- return omitted;
1428
- }).build();
1429
- 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({
1904
+ });
1905
+ function createArrayFilterTool() {
1906
+ return toolBuilder().name("array-filter").description("Filter an array based on a property value. Supports equality, comparison, and contains operations.").category(ToolCategory.UTILITY).tags(["array", "filter", "data", "transform"]).schema(arrayFilterSchema).implement(async (input) => {
1907
+ const getNestedValue = (obj, path12) => {
1908
+ return path12.split(".").reduce((current, key) => current?.[key], obj);
1909
+ };
1910
+ const filtered = input.array.filter((item) => {
1911
+ const itemValue = getNestedValue(item, input.property);
1912
+ switch (input.operator) {
1913
+ case "equals":
1914
+ return itemValue === input.value;
1915
+ case "not-equals":
1916
+ return itemValue !== input.value;
1917
+ case "greater-than":
1918
+ return itemValue > input.value;
1919
+ case "less-than":
1920
+ return itemValue < input.value;
1921
+ case "contains":
1922
+ return String(itemValue).includes(String(input.value));
1923
+ case "starts-with":
1924
+ return String(itemValue).startsWith(String(input.value));
1925
+ case "ends-with":
1926
+ return String(itemValue).endsWith(String(input.value));
1927
+ default:
1928
+ return false;
1929
+ }
1930
+ });
1931
+ return {
1932
+ filtered,
1933
+ originalCount: input.array.length,
1934
+ filteredCount: filtered.length
1935
+ };
1936
+ }).build();
1937
+ }
1938
+ function createArrayMapTool() {
1939
+ return toolBuilder().name("array-map").description("Extract specific properties from each object in an array. Creates a new array with only the selected properties.").category(ToolCategory.UTILITY).tags(["array", "map", "data", "transform"]).schema(arrayMapSchema).implement(async (input) => {
1940
+ const mapped = input.array.map((item) => {
1941
+ const result = {};
1942
+ for (const prop of input.properties) {
1943
+ const value = prop.split(".").reduce((current, key) => current?.[key], item);
1944
+ result[prop] = value;
1945
+ }
1946
+ return result;
1947
+ });
1948
+ return {
1949
+ mapped,
1950
+ count: mapped.length
1951
+ };
1952
+ }).build();
1953
+ }
1954
+ function createArraySortTool() {
1955
+ return toolBuilder().name("array-sort").description("Sort an array by a property value. Supports ascending and descending order.").category(ToolCategory.UTILITY).tags(["array", "sort", "data", "transform"]).schema(arraySortSchema).implement(async (input) => {
1956
+ const getNestedValue = (obj, path12) => {
1957
+ return path12.split(".").reduce((current, key) => current?.[key], obj);
1958
+ };
1959
+ const sorted = [...input.array].sort((a, b) => {
1960
+ const aValue = getNestedValue(a, input.property);
1961
+ const bValue = getNestedValue(b, input.property);
1962
+ if (aValue < bValue) return input.order === "asc" ? -1 : 1;
1963
+ if (aValue > bValue) return input.order === "asc" ? 1 : -1;
1964
+ return 0;
1965
+ });
1966
+ return {
1967
+ sorted,
1968
+ count: sorted.length
1969
+ };
1970
+ }).build();
1971
+ }
1972
+ function createArrayGroupByTool() {
1973
+ return toolBuilder().name("array-group-by").description("Group an array of objects by a property value. Returns an object with groups as keys.").category(ToolCategory.UTILITY).tags(["array", "group", "data", "transform"]).schema(arrayGroupBySchema).implement(async (input) => {
1974
+ const groups = {};
1975
+ for (const item of input.array) {
1976
+ const key = String(item[input.property]);
1977
+ if (!groups[key]) {
1978
+ groups[key] = [];
1979
+ }
1980
+ groups[key].push(item);
1981
+ }
1982
+ return {
1983
+ groups,
1984
+ groupCount: Object.keys(groups).length,
1985
+ totalItems: input.array.length
1986
+ };
1987
+ }).build();
1988
+ }
1989
+ function createObjectPickTool() {
1990
+ return toolBuilder().name("object-pick").description("Create a new object with only the specified properties from the source object.").category(ToolCategory.UTILITY).tags(["object", "pick", "data", "transform"]).schema(objectPickSchema).implement(async (input) => {
1991
+ const picked = {};
1992
+ for (const prop of input.properties) {
1993
+ if (prop in input.object) {
1994
+ picked[prop] = input.object[prop];
1995
+ }
1996
+ }
1997
+ return picked;
1998
+ }).build();
1999
+ }
2000
+ function createObjectOmitTool() {
2001
+ return toolBuilder().name("object-omit").description("Create a new object excluding the specified properties from the source object.").category(ToolCategory.UTILITY).tags(["object", "omit", "data", "transform"]).schema(objectOmitSchema).implement(async (input) => {
2002
+ const omitted = { ...input.object };
2003
+ for (const prop of input.properties) {
2004
+ delete omitted[prop];
2005
+ }
2006
+ return omitted;
2007
+ }).build();
2008
+ }
2009
+
2010
+ // src/data/transformer/index.ts
2011
+ var arrayFilter = createArrayFilterTool();
2012
+ var arrayMap = createArrayMapTool();
2013
+ var arraySort = createArraySortTool();
2014
+ var arrayGroupBy = createArrayGroupByTool();
2015
+ var objectPick = createObjectPickTool();
2016
+ var objectOmit = createObjectOmitTool();
2017
+ var transformerTools = [arrayFilter, arrayMap, arraySort, arrayGroupBy, objectPick, objectOmit];
2018
+ function createTransformerTools(config = {}) {
2019
+ return [
2020
+ createArrayFilterTool(),
2021
+ createArrayMapTool(),
2022
+ createArraySortTool(),
2023
+ createArrayGroupByTool(),
2024
+ createObjectPickTool(),
2025
+ createObjectOmitTool()
2026
+ ];
2027
+ }
2028
+ var fileReaderSchema = z.object({
1430
2029
  path: z.string().describe("Path to the file to read"),
1431
2030
  encoding: z.enum(["utf8", "utf-8", "ascii", "base64", "hex", "binary"]).default("utf8").describe("File encoding")
1432
- })).implementSafe(async (input) => {
1433
- const content = await promises.readFile(input.path, input.encoding);
1434
- const stats = await promises.stat(input.path);
1435
- return {
1436
- content,
1437
- size: stats.size,
1438
- path: input.path,
1439
- encoding: input.encoding
1440
- };
1441
- }).build();
1442
- 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({
2031
+ });
2032
+ var fileWriterSchema = z.object({
1443
2033
  path: z.string().describe("Path to the file to write"),
1444
2034
  content: z.string().describe("Content to write to the file"),
1445
2035
  encoding: z.enum(["utf8", "utf-8", "ascii", "base64", "hex"]).default("utf8").describe("File encoding"),
1446
2036
  createDirs: z.boolean().default(false).describe("Create parent directories if they don't exist")
1447
- })).implementSafe(async (input) => {
1448
- if (input.createDirs) {
1449
- const dir = path3.dirname(input.path);
1450
- await promises.mkdir(dir, { recursive: true });
1451
- }
1452
- await promises.writeFile(input.path, input.content, input.encoding);
1453
- const stats = await promises.stat(input.path);
1454
- return {
1455
- path: input.path,
1456
- size: stats.size,
1457
- encoding: input.encoding
1458
- };
1459
- }).build();
1460
- 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({
2037
+ });
2038
+ var fileAppendSchema = z.object({
1461
2039
  path: z.string().describe("Path to the file to append to"),
1462
2040
  content: z.string().describe("Content to append to the file"),
1463
2041
  encoding: z.enum(["utf8", "utf-8", "ascii"]).default("utf8").describe("File encoding")
1464
- })).implementSafe(async (input) => {
1465
- await promises.appendFile(input.path, input.content, input.encoding);
1466
- const stats = await promises.stat(input.path);
1467
- return {
1468
- path: input.path,
1469
- size: stats.size
1470
- };
1471
- }).build();
1472
- 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({
2042
+ });
2043
+ var fileDeleteSchema = z.object({
1473
2044
  path: z.string().describe("Path to the file to delete")
1474
- })).implementSafe(async (input) => {
1475
- await promises.unlink(input.path);
1476
- return {
1477
- path: input.path,
1478
- message: "File deleted successfully"
1479
- };
1480
- }).build();
1481
- 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({
2045
+ });
2046
+ var fileExistsSchema = z.object({
1482
2047
  path: z.string().describe("Path to check")
1483
- })).implement(async (input) => {
1484
- try {
1485
- await promises.access(input.path);
2048
+ });
2049
+ function createFileReaderTool(defaultEncoding = "utf8") {
2050
+ return 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(fileReaderSchema).implementSafe(async (input) => {
2051
+ const encoding = input.encoding || defaultEncoding;
2052
+ const content = await promises.readFile(input.path, encoding);
2053
+ const stats = await promises.stat(input.path);
2054
+ return {
2055
+ content,
2056
+ size: stats.size,
2057
+ path: input.path,
2058
+ encoding
2059
+ };
2060
+ }).build();
2061
+ }
2062
+ function createFileWriterTool(defaultEncoding = "utf8", createDirsDefault = false) {
2063
+ return 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(fileWriterSchema).implementSafe(async (input) => {
2064
+ const encoding = input.encoding || defaultEncoding;
2065
+ const createDirs = input.createDirs ?? createDirsDefault;
2066
+ if (createDirs) {
2067
+ const dir = path7.dirname(input.path);
2068
+ await promises.mkdir(dir, { recursive: true });
2069
+ }
2070
+ await promises.writeFile(input.path, input.content, encoding);
1486
2071
  const stats = await promises.stat(input.path);
1487
2072
  return {
1488
- exists: true,
1489
2073
  path: input.path,
1490
- isFile: stats.isFile(),
1491
- isDirectory: stats.isDirectory(),
1492
2074
  size: stats.size,
1493
- modified: stats.mtime.toISOString()
2075
+ encoding
1494
2076
  };
1495
- } catch {
2077
+ }).build();
2078
+ }
2079
+ function createFileAppendTool(defaultEncoding = "utf8") {
2080
+ return 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(fileAppendSchema).implementSafe(async (input) => {
2081
+ const encoding = input.encoding || defaultEncoding;
2082
+ await promises.appendFile(input.path, input.content, encoding);
2083
+ const stats = await promises.stat(input.path);
1496
2084
  return {
1497
- exists: false,
1498
- path: input.path
2085
+ path: input.path,
2086
+ size: stats.size
1499
2087
  };
1500
- }
1501
- }).build();
1502
- var directoryList = toolBuilder().name("directory-list").description("List all files and directories in a directory. Can optionally include file details and filter by extension.").category(ToolCategory.FILE_SYSTEM).tags(["directory", "list", "files", "filesystem"]).schema(z.object({
2088
+ }).build();
2089
+ }
2090
+ function createFileDeleteTool() {
2091
+ return 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(fileDeleteSchema).implementSafe(async (input) => {
2092
+ await promises.unlink(input.path);
2093
+ return {
2094
+ path: input.path,
2095
+ message: "File deleted successfully"
2096
+ };
2097
+ }).build();
2098
+ }
2099
+ function createFileExistsTool() {
2100
+ return 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(fileExistsSchema).implement(async (input) => {
2101
+ try {
2102
+ await promises.access(input.path);
2103
+ const stats = await promises.stat(input.path);
2104
+ return {
2105
+ exists: true,
2106
+ path: input.path,
2107
+ isFile: stats.isFile(),
2108
+ isDirectory: stats.isDirectory(),
2109
+ size: stats.size,
2110
+ modified: stats.mtime.toISOString()
2111
+ };
2112
+ } catch {
2113
+ return {
2114
+ exists: false,
2115
+ path: input.path
2116
+ };
2117
+ }
2118
+ }).build();
2119
+ }
2120
+
2121
+ // src/file/operations/index.ts
2122
+ var fileReader = createFileReaderTool();
2123
+ var fileWriter = createFileWriterTool();
2124
+ var fileAppend = createFileAppendTool();
2125
+ var fileDelete = createFileDeleteTool();
2126
+ var fileExists = createFileExistsTool();
2127
+ var fileOperationTools = [
2128
+ fileReader,
2129
+ fileWriter,
2130
+ fileAppend,
2131
+ fileDelete,
2132
+ fileExists
2133
+ ];
2134
+ function createFileOperationTools(config = {}) {
2135
+ const {
2136
+ defaultEncoding = "utf8",
2137
+ createDirsDefault = false
2138
+ } = config;
2139
+ return [
2140
+ createFileReaderTool(defaultEncoding),
2141
+ createFileWriterTool(defaultEncoding, createDirsDefault),
2142
+ createFileAppendTool(defaultEncoding),
2143
+ createFileDeleteTool(),
2144
+ createFileExistsTool()
2145
+ ];
2146
+ }
2147
+ var directoryListSchema = z.object({
1503
2148
  path: z.string().describe("Path to the directory to list"),
1504
2149
  recursive: z.boolean().default(false).describe("List files recursively in subdirectories"),
1505
2150
  includeDetails: z.boolean().default(false).describe("Include file size, type, and modification date"),
1506
2151
  extension: z.string().optional().describe('Optional file extension filter (e.g., ".txt", ".js")')
1507
- })).implementSafe(async (input) => {
1508
- const listFiles = async (dir, recursive) => {
1509
- const entries = await promises.readdir(dir, { withFileTypes: true });
1510
- const files2 = [];
1511
- for (const entry of entries) {
1512
- const fullPath = path3.join(dir, entry.name);
1513
- const relativePath = path3.relative(input.path, fullPath);
1514
- if (input.extension && !entry.name.endsWith(input.extension)) {
1515
- if (!entry.isDirectory() || !recursive) {
1516
- continue;
1517
- }
1518
- }
1519
- if (input.includeDetails) {
1520
- const stats = await promises.stat(fullPath);
1521
- files2.push({
1522
- name: entry.name,
1523
- path: relativePath,
1524
- fullPath,
1525
- isFile: entry.isFile(),
1526
- isDirectory: entry.isDirectory(),
1527
- size: stats.size,
1528
- modified: stats.mtime.toISOString()
1529
- });
1530
- } else {
1531
- files2.push({
1532
- name: entry.name,
1533
- path: relativePath,
1534
- isFile: entry.isFile(),
1535
- isDirectory: entry.isDirectory()
1536
- });
1537
- }
1538
- if (recursive && entry.isDirectory()) {
1539
- const subFiles = await listFiles(fullPath, true);
1540
- files2.push(...subFiles);
1541
- }
1542
- }
1543
- return files2;
1544
- };
1545
- const files = await listFiles(input.path, input.recursive ?? false);
1546
- return {
1547
- path: input.path,
1548
- files,
1549
- count: files.length
1550
- };
1551
- }).build();
1552
- 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({
2152
+ });
2153
+ var directoryCreateSchema = z.object({
1553
2154
  path: z.string().describe("Path to the directory to create"),
1554
2155
  recursive: z.boolean().default(true).describe("Create parent directories if they don't exist")
1555
- })).implementSafe(async (input) => {
1556
- await promises.mkdir(input.path, { recursive: input.recursive });
1557
- return {
1558
- path: input.path,
1559
- message: "Directory created successfully"
1560
- };
1561
- }).build();
1562
- 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({
2156
+ });
2157
+ var directoryDeleteSchema = z.object({
1563
2158
  path: z.string().describe("Path to the directory to delete"),
1564
2159
  recursive: z.boolean().default(false).describe("Delete directory and all its contents")
1565
- })).implementSafe(async (input) => {
1566
- await promises.rm(input.path, { recursive: input.recursive, force: false });
1567
- return {
1568
- path: input.path,
1569
- message: "Directory deleted successfully"
1570
- };
1571
- }).build();
1572
- 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({
2160
+ });
2161
+ var fileSearchSchema = z.object({
1573
2162
  directory: z.string().describe("Directory to search in"),
1574
2163
  pattern: z.string().describe("File name pattern to search for (supports * wildcard)"),
1575
2164
  recursive: z.boolean().default(true).describe("Search in subdirectories"),
1576
2165
  caseSensitive: z.boolean().default(false).describe("Case-sensitive pattern matching")
1577
- })).implementSafe(async (input) => {
1578
- const searchFiles = async (dir) => {
1579
- const entries = await promises.readdir(dir, { withFileTypes: true });
1580
- const matches2 = [];
1581
- const regexPattern = input.pattern.replace(/\./g, "\\.").replace(/\*/g, ".*");
1582
- const regex = new RegExp(`^${regexPattern}$`, input.caseSensitive ? "" : "i");
1583
- for (const entry of entries) {
1584
- const fullPath = path3.join(dir, entry.name);
1585
- if (entry.isFile() && regex.test(entry.name)) {
1586
- matches2.push(fullPath);
2166
+ });
2167
+ function createDirectoryListTool(defaultRecursive = false, defaultIncludeDetails = false) {
2168
+ return toolBuilder().name("directory-list").description("List all files and directories in a directory. Can optionally include file details and filter by extension.").category(ToolCategory.FILE_SYSTEM).tags(["directory", "list", "files", "filesystem"]).schema(directoryListSchema).implementSafe(async (input) => {
2169
+ const listFiles = async (dir, recursive2) => {
2170
+ const entries = await promises.readdir(dir, { withFileTypes: true });
2171
+ const files2 = [];
2172
+ for (const entry of entries) {
2173
+ const fullPath = path7.join(dir, entry.name);
2174
+ const relativePath = path7.relative(input.path, fullPath);
2175
+ if (input.extension && !entry.name.endsWith(input.extension)) {
2176
+ if (!entry.isDirectory() || !recursive2) {
2177
+ continue;
2178
+ }
2179
+ }
2180
+ if (input.includeDetails) {
2181
+ const stats = await promises.stat(fullPath);
2182
+ files2.push({
2183
+ name: entry.name,
2184
+ path: relativePath,
2185
+ fullPath,
2186
+ isFile: entry.isFile(),
2187
+ isDirectory: entry.isDirectory(),
2188
+ size: stats.size,
2189
+ modified: stats.mtime.toISOString()
2190
+ });
2191
+ } else {
2192
+ files2.push({
2193
+ name: entry.name,
2194
+ path: relativePath,
2195
+ isFile: entry.isFile(),
2196
+ isDirectory: entry.isDirectory()
2197
+ });
2198
+ }
2199
+ if (recursive2 && entry.isDirectory()) {
2200
+ const subFiles = await listFiles(fullPath, true);
2201
+ files2.push(...subFiles);
2202
+ }
1587
2203
  }
1588
- if (input.recursive && entry.isDirectory()) {
1589
- const subMatches = await searchFiles(fullPath);
1590
- matches2.push(...subMatches);
2204
+ return files2;
2205
+ };
2206
+ const recursive = input.recursive ?? defaultRecursive;
2207
+ const files = await listFiles(input.path, recursive);
2208
+ return {
2209
+ path: input.path,
2210
+ files,
2211
+ count: files.length
2212
+ };
2213
+ }).build();
2214
+ }
2215
+ function createDirectoryCreateTool(defaultRecursive = true) {
2216
+ return 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(directoryCreateSchema).implementSafe(async (input) => {
2217
+ const recursive = input.recursive ?? defaultRecursive;
2218
+ await promises.mkdir(input.path, { recursive });
2219
+ return {
2220
+ path: input.path,
2221
+ message: "Directory created successfully"
2222
+ };
2223
+ }).build();
2224
+ }
2225
+ function createDirectoryDeleteTool(defaultRecursive = false) {
2226
+ return 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(directoryDeleteSchema).implementSafe(async (input) => {
2227
+ const recursive = input.recursive ?? defaultRecursive;
2228
+ await promises.rm(input.path, { recursive, force: false });
2229
+ return {
2230
+ path: input.path,
2231
+ message: "Directory deleted successfully"
2232
+ };
2233
+ }).build();
2234
+ }
2235
+ function createFileSearchTool(defaultRecursive = true, defaultCaseSensitive = false) {
2236
+ return 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(fileSearchSchema).implementSafe(async (input) => {
2237
+ const recursive = input.recursive ?? defaultRecursive;
2238
+ const caseSensitive = input.caseSensitive ?? defaultCaseSensitive;
2239
+ const searchFiles = async (dir) => {
2240
+ const entries = await promises.readdir(dir, { withFileTypes: true });
2241
+ const matches2 = [];
2242
+ const regexPattern = input.pattern.replace(/\./g, "\\.").replace(/\*/g, ".*");
2243
+ const regex = new RegExp(`^${regexPattern}$`, caseSensitive ? "" : "i");
2244
+ for (const entry of entries) {
2245
+ const fullPath = path7.join(dir, entry.name);
2246
+ if (entry.isFile() && regex.test(entry.name)) {
2247
+ matches2.push(fullPath);
2248
+ }
2249
+ if (recursive && entry.isDirectory()) {
2250
+ const subMatches = await searchFiles(fullPath);
2251
+ matches2.push(...subMatches);
2252
+ }
1591
2253
  }
1592
- }
1593
- return matches2;
1594
- };
1595
- const matches = await searchFiles(input.directory);
1596
- return {
1597
- directory: input.directory,
1598
- pattern: input.pattern,
1599
- matches,
1600
- count: matches.length
1601
- };
1602
- }).build();
1603
- 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({
2254
+ return matches2;
2255
+ };
2256
+ const matches = await searchFiles(input.directory);
2257
+ return {
2258
+ directory: input.directory,
2259
+ pattern: input.pattern,
2260
+ matches,
2261
+ count: matches.length
2262
+ };
2263
+ }).build();
2264
+ }
2265
+
2266
+ // src/file/directory/index.ts
2267
+ var directoryList = createDirectoryListTool();
2268
+ var directoryCreate = createDirectoryCreateTool();
2269
+ var directoryDelete = createDirectoryDeleteTool();
2270
+ var fileSearch = createFileSearchTool();
2271
+ var directoryOperationTools = [
2272
+ directoryList,
2273
+ directoryCreate,
2274
+ directoryDelete,
2275
+ fileSearch
2276
+ ];
2277
+ function createDirectoryOperationTools(config = {}) {
2278
+ const {
2279
+ defaultRecursive = false,
2280
+ defaultIncludeDetails = false,
2281
+ defaultCaseSensitive = false
2282
+ } = config;
2283
+ return [
2284
+ createDirectoryListTool(defaultRecursive, defaultIncludeDetails),
2285
+ createDirectoryCreateTool(true),
2286
+ // Always default to true for create
2287
+ createDirectoryDeleteTool(false),
2288
+ // Always default to false for delete (safety)
2289
+ createFileSearchTool(defaultRecursive, defaultCaseSensitive)
2290
+ ];
2291
+ }
2292
+ var pathJoinSchema = z.object({
1604
2293
  segments: z.array(z.string().describe("String value")).describe("Path segments to join")
1605
- })).implement(async (input) => {
1606
- const joined = path3.join(...input.segments);
1607
- return {
1608
- path: joined,
1609
- segments: input.segments
1610
- };
1611
- }).build();
1612
- var pathResolve = toolBuilder().name("path-resolve").description("Resolve a sequence of paths into an absolute path. Resolves relative paths from the current working directory.").category(ToolCategory.FILE_SYSTEM).tags(["path", "resolve", "absolute", "filesystem"]).schema(z.object({
2294
+ });
2295
+ var pathResolveSchema = z.object({
1613
2296
  paths: z.array(z.string().describe("String value")).describe("Paths to resolve")
1614
- })).implement(async (input) => {
1615
- const resolved = path3.resolve(...input.paths);
1616
- return {
1617
- path: resolved,
1618
- isAbsolute: path3.isAbsolute(resolved)
1619
- };
1620
- }).build();
1621
- var pathParse = toolBuilder().name("path-parse").description("Parse a file path into its components (directory, filename, extension, etc.).").category(ToolCategory.FILE_SYSTEM).tags(["path", "parse", "filesystem"]).schema(z.object({
2297
+ });
2298
+ var pathParseSchema = z.object({
1622
2299
  path: z.string().describe("File path to parse")
1623
- })).implement(async (input) => {
1624
- const parsed = path3.parse(input.path);
1625
- return {
1626
- root: parsed.root,
1627
- dir: parsed.dir,
1628
- base: parsed.base,
1629
- name: parsed.name,
1630
- ext: parsed.ext,
1631
- isAbsolute: path3.isAbsolute(input.path)
1632
- };
1633
- }).build();
1634
- var pathBasename = toolBuilder().name("path-basename").description("Get the last portion of a path (filename with extension). Optionally remove the extension.").category(ToolCategory.FILE_SYSTEM).tags(["path", "basename", "filename", "filesystem"]).schema(z.object({
2300
+ });
2301
+ var pathBasenameSchema = z.object({
1635
2302
  path: z.string().describe("File path"),
1636
2303
  removeExtension: z.boolean().default(false).describe("Remove the file extension")
1637
- })).implement(async (input) => {
1638
- const basename2 = input.removeExtension ? path3.basename(input.path, path3.extname(input.path)) : path3.basename(input.path);
1639
- return {
1640
- basename: basename2,
1641
- extension: path3.extname(input.path)
1642
- };
1643
- }).build();
1644
- var pathDirname = toolBuilder().name("path-dirname").description("Get the directory name of a path (everything except the last portion).").category(ToolCategory.FILE_SYSTEM).tags(["path", "dirname", "directory", "filesystem"]).schema(z.object({
2304
+ });
2305
+ var pathDirnameSchema = z.object({
1645
2306
  path: z.string().describe("File path")
1646
- })).implement(async (input) => {
1647
- const dirname3 = path3.dirname(input.path);
1648
- return {
1649
- dirname: dirname3,
1650
- basename: path3.basename(input.path)
1651
- };
1652
- }).build();
1653
- var pathExtension = toolBuilder().name("path-extension").description('Get the file extension from a path (including the dot, e.g., ".txt").').category(ToolCategory.FILE_SYSTEM).tags(["path", "extension", "ext", "filesystem"]).schema(z.object({
2307
+ });
2308
+ var pathExtensionSchema = z.object({
1654
2309
  path: z.string().describe("File path")
1655
- })).implement(async (input) => {
1656
- const ext = path3.extname(input.path);
1657
- return {
1658
- extension: ext,
1659
- hasExtension: ext.length > 0,
1660
- filename: path3.basename(input.path, ext)
1661
- };
1662
- }).build();
1663
- var pathRelative = toolBuilder().name("path-relative").description("Get the relative path from one path to another.").category(ToolCategory.FILE_SYSTEM).tags(["path", "relative", "filesystem"]).schema(z.object({
2310
+ });
2311
+ var pathRelativeSchema = z.object({
1664
2312
  from: z.string().describe("Source path"),
1665
2313
  to: z.string().describe("Destination path")
1666
- })).implement(async (input) => {
1667
- const relative3 = path3.relative(input.from, input.to);
1668
- return {
1669
- relativePath: relative3,
1670
- from: input.from,
1671
- to: input.to
1672
- };
1673
- }).build();
1674
- var pathNormalize = toolBuilder().name("path-normalize").description('Normalize a path by resolving ".." and "." segments and removing duplicate separators.').category(ToolCategory.FILE_SYSTEM).tags(["path", "normalize", "filesystem"]).schema(z.object({
2314
+ });
2315
+ var pathNormalizeSchema = z.object({
1675
2316
  path: z.string().describe("Path to normalize")
1676
- })).implement(async (input) => {
1677
- const normalized = path3.normalize(input.path);
1678
- return {
1679
- normalized,
1680
- original: input.path
1681
- };
1682
- }).build();
1683
- var currentDateTime = toolBuilder().name("current-date-time").description("Get the current date and time in various formats (ISO, Unix timestamp, formatted string).").category(ToolCategory.UTILITY).tags(["date", "time", "now", "current"]).schema(z.object({
2317
+ });
2318
+ function createPathJoinTool() {
2319
+ return 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(pathJoinSchema).implement(async (input) => {
2320
+ const joined = path7.join(...input.segments);
2321
+ return {
2322
+ path: joined,
2323
+ segments: input.segments
2324
+ };
2325
+ }).build();
2326
+ }
2327
+ function createPathResolveTool() {
2328
+ return toolBuilder().name("path-resolve").description("Resolve a sequence of paths into an absolute path. Resolves relative paths from the current working directory.").category(ToolCategory.FILE_SYSTEM).tags(["path", "resolve", "absolute", "filesystem"]).schema(pathResolveSchema).implement(async (input) => {
2329
+ const resolved = path7.resolve(...input.paths);
2330
+ return {
2331
+ path: resolved,
2332
+ isAbsolute: path7.isAbsolute(resolved)
2333
+ };
2334
+ }).build();
2335
+ }
2336
+ function createPathParseTool() {
2337
+ return toolBuilder().name("path-parse").description("Parse a file path into its components (directory, filename, extension, etc.).").category(ToolCategory.FILE_SYSTEM).tags(["path", "parse", "filesystem"]).schema(pathParseSchema).implement(async (input) => {
2338
+ const parsed = path7.parse(input.path);
2339
+ return {
2340
+ root: parsed.root,
2341
+ dir: parsed.dir,
2342
+ base: parsed.base,
2343
+ name: parsed.name,
2344
+ ext: parsed.ext,
2345
+ isAbsolute: path7.isAbsolute(input.path)
2346
+ };
2347
+ }).build();
2348
+ }
2349
+ function createPathBasenameTool() {
2350
+ return toolBuilder().name("path-basename").description("Get the last portion of a path (filename with extension). Optionally remove the extension.").category(ToolCategory.FILE_SYSTEM).tags(["path", "basename", "filename", "filesystem"]).schema(pathBasenameSchema).implement(async (input) => {
2351
+ const basename4 = input.removeExtension ? path7.basename(input.path, path7.extname(input.path)) : path7.basename(input.path);
2352
+ return {
2353
+ basename: basename4,
2354
+ extension: path7.extname(input.path)
2355
+ };
2356
+ }).build();
2357
+ }
2358
+ function createPathDirnameTool() {
2359
+ return toolBuilder().name("path-dirname").description("Get the directory name of a path (everything except the last portion).").category(ToolCategory.FILE_SYSTEM).tags(["path", "dirname", "directory", "filesystem"]).schema(pathDirnameSchema).implement(async (input) => {
2360
+ const dirname3 = path7.dirname(input.path);
2361
+ return {
2362
+ dirname: dirname3,
2363
+ basename: path7.basename(input.path)
2364
+ };
2365
+ }).build();
2366
+ }
2367
+ function createPathExtensionTool() {
2368
+ return toolBuilder().name("path-extension").description('Get the file extension from a path (including the dot, e.g., ".txt").').category(ToolCategory.FILE_SYSTEM).tags(["path", "extension", "ext", "filesystem"]).schema(pathExtensionSchema).implement(async (input) => {
2369
+ const ext = path7.extname(input.path);
2370
+ return {
2371
+ extension: ext,
2372
+ hasExtension: ext.length > 0,
2373
+ filename: path7.basename(input.path, ext)
2374
+ };
2375
+ }).build();
2376
+ }
2377
+ function createPathRelativeTool() {
2378
+ return toolBuilder().name("path-relative").description("Get the relative path from one path to another.").category(ToolCategory.FILE_SYSTEM).tags(["path", "relative", "filesystem"]).schema(pathRelativeSchema).implement(async (input) => {
2379
+ const relative3 = path7.relative(input.from, input.to);
2380
+ return {
2381
+ relativePath: relative3,
2382
+ from: input.from,
2383
+ to: input.to
2384
+ };
2385
+ }).build();
2386
+ }
2387
+ function createPathNormalizeTool() {
2388
+ return toolBuilder().name("path-normalize").description('Normalize a path by resolving ".." and "." segments and removing duplicate separators.').category(ToolCategory.FILE_SYSTEM).tags(["path", "normalize", "filesystem"]).schema(pathNormalizeSchema).implement(async (input) => {
2389
+ const normalized = path7.normalize(input.path);
2390
+ return {
2391
+ normalized,
2392
+ original: input.path
2393
+ };
2394
+ }).build();
2395
+ }
2396
+
2397
+ // src/file/path/index.ts
2398
+ var pathJoin = createPathJoinTool();
2399
+ var pathResolve = createPathResolveTool();
2400
+ var pathParse = createPathParseTool();
2401
+ var pathBasename = createPathBasenameTool();
2402
+ var pathDirname = createPathDirnameTool();
2403
+ var pathExtension = createPathExtensionTool();
2404
+ var pathRelative = createPathRelativeTool();
2405
+ var pathNormalize = createPathNormalizeTool();
2406
+ var pathUtilityTools = [
2407
+ pathJoin,
2408
+ pathResolve,
2409
+ pathParse,
2410
+ pathBasename,
2411
+ pathDirname,
2412
+ pathExtension,
2413
+ pathRelative,
2414
+ pathNormalize
2415
+ ];
2416
+ function createPathUtilityTools(config = {}) {
2417
+ return [
2418
+ createPathJoinTool(),
2419
+ createPathResolveTool(),
2420
+ createPathParseTool(),
2421
+ createPathBasenameTool(),
2422
+ createPathDirnameTool(),
2423
+ createPathExtensionTool(),
2424
+ createPathRelativeTool(),
2425
+ createPathNormalizeTool()
2426
+ ];
2427
+ }
2428
+ var CurrentDateTimeSchema = z.object({
1684
2429
  format: z.enum(["iso", "unix", "custom"]).default("iso").describe("Output format"),
1685
2430
  customFormat: z.string().optional().describe('Custom format string (e.g., "yyyy-MM-dd HH:mm:ss") when format is "custom"'),
1686
2431
  timezone: z.string().optional().describe('Timezone (e.g., "America/New_York")')
1687
- })).implement(async (input) => {
1688
- const now = /* @__PURE__ */ new Date();
1689
- let formatted;
1690
- if (input.format === "iso") {
1691
- formatted = now.toISOString();
1692
- } else if (input.format === "unix") {
1693
- formatted = Math.floor(now.getTime() / 1e3);
1694
- } else if (input.format === "custom" && input.customFormat) {
1695
- formatted = format(now, input.customFormat);
1696
- } else {
1697
- formatted = now.toISOString();
1698
- }
1699
- return {
1700
- formatted,
1701
- iso: now.toISOString(),
1702
- unix: Math.floor(now.getTime() / 1e3),
1703
- year: now.getFullYear(),
1704
- month: now.getMonth() + 1,
1705
- day: now.getDate(),
1706
- hour: now.getHours(),
1707
- minute: now.getMinutes(),
1708
- second: now.getSeconds()
1709
- };
1710
- }).build();
1711
- var dateFormatter = toolBuilder().name("date-formatter").description("Format a date string or timestamp into a different format. Supports ISO, Unix timestamps, and custom formats.").category(ToolCategory.UTILITY).tags(["date", "format", "time"]).schema(z.object({
2432
+ });
2433
+ var DateFormatterSchema = z.object({
1712
2434
  date: z.string().describe("Date string or Unix timestamp to format"),
1713
2435
  outputFormat: z.string().describe('Output format string (e.g., "yyyy-MM-dd", "MMM dd, yyyy")'),
1714
2436
  inputFormat: z.string().optional().describe("Input format string (optional, auto-detected if not provided)")
1715
- })).implement(async (input) => {
1716
- try {
1717
- let date;
1718
- if (input.inputFormat) {
1719
- date = parse$1(input.date, input.inputFormat, /* @__PURE__ */ new Date());
1720
- } else if (!isNaN(Number(input.date))) {
1721
- date = new Date(Number(input.date) * 1e3);
2437
+ });
2438
+ var DateArithmeticSchema = z.object({
2439
+ date: z.string().describe("Starting date (ISO string or Unix timestamp)"),
2440
+ operation: z.enum(["add", "subtract"]).describe("Operation to perform"),
2441
+ amount: z.number().describe("Amount to add or subtract"),
2442
+ unit: z.enum(["years", "months", "weeks", "days", "hours", "minutes", "seconds"]).describe("Time unit")
2443
+ });
2444
+ var DateDifferenceSchema = z.object({
2445
+ startDate: z.string().describe("Start date (ISO string or Unix timestamp)"),
2446
+ endDate: z.string().describe("End date (ISO string or Unix timestamp)"),
2447
+ unit: z.enum(["days", "hours", "minutes"]).default("days").describe("Unit for the difference")
2448
+ });
2449
+ var DateComparisonSchema = z.object({
2450
+ date1: z.string().describe("First date to compare"),
2451
+ date2: z.string().describe("Second date to compare")
2452
+ });
2453
+
2454
+ // src/utility/date-time/tools/current-date-time.ts
2455
+ function createCurrentDateTimeTool() {
2456
+ return toolBuilder().name("current-date-time").description("Get the current date and time in various formats (ISO, Unix timestamp, formatted string).").category(ToolCategory.UTILITY).tags(["date", "time", "now", "current"]).schema(CurrentDateTimeSchema).implement(async (input) => {
2457
+ const now = /* @__PURE__ */ new Date();
2458
+ let formatted;
2459
+ if (input.format === "iso") {
2460
+ formatted = now.toISOString();
2461
+ } else if (input.format === "unix") {
2462
+ formatted = Math.floor(now.getTime() / 1e3);
2463
+ } else if (input.format === "custom" && input.customFormat) {
2464
+ formatted = format(now, input.customFormat);
1722
2465
  } else {
1723
- date = new Date(input.date);
1724
- }
1725
- if (!isValid(date)) {
1726
- return {
1727
- success: false,
1728
- error: "Invalid date"
1729
- };
2466
+ formatted = now.toISOString();
1730
2467
  }
1731
- const formatted = format(date, input.outputFormat);
1732
2468
  return {
1733
- success: true,
1734
2469
  formatted,
1735
- iso: date.toISOString()
1736
- };
1737
- } catch (error) {
1738
- return {
1739
- success: false,
1740
- error: error instanceof Error ? error.message : "Failed to format date"
2470
+ iso: now.toISOString(),
2471
+ unix: Math.floor(now.getTime() / 1e3),
2472
+ year: now.getFullYear(),
2473
+ month: now.getMonth() + 1,
2474
+ day: now.getDate(),
2475
+ hour: now.getHours(),
2476
+ minute: now.getMinutes(),
2477
+ second: now.getSeconds()
1741
2478
  };
1742
- }
1743
- }).build();
1744
- var dateArithmetic = toolBuilder().name("date-arithmetic").description("Add or subtract time from a date. Supports years, months, weeks, days, hours, minutes, and seconds.").category(ToolCategory.UTILITY).tags(["date", "time", "add", "subtract", "arithmetic"]).schema(z.object({
1745
- date: z.string().describe("Starting date (ISO string or Unix timestamp)"),
1746
- operation: z.enum(["add", "subtract"]).describe("Operation to perform"),
1747
- amount: z.number().describe("Amount to add or subtract"),
1748
- unit: z.enum(["years", "months", "weeks", "days", "hours", "minutes", "seconds"]).describe("Time unit")
1749
- })).implement(async (input) => {
1750
- try {
1751
- const date = new Date(input.date);
1752
- if (!isValid(date)) {
2479
+ }).build();
2480
+ }
2481
+ function createDateFormatterTool() {
2482
+ return toolBuilder().name("date-formatter").description("Format a date string or timestamp into a different format. Supports ISO, Unix timestamps, and custom formats.").category(ToolCategory.UTILITY).tags(["date", "format", "time"]).schema(DateFormatterSchema).implement(async (input) => {
2483
+ try {
2484
+ let date;
2485
+ if (input.inputFormat) {
2486
+ date = parse$1(input.date, input.inputFormat, /* @__PURE__ */ new Date());
2487
+ } else if (!isNaN(Number(input.date))) {
2488
+ date = new Date(Number(input.date) * 1e3);
2489
+ } else {
2490
+ date = new Date(input.date);
2491
+ }
2492
+ if (!isValid(date)) {
2493
+ return {
2494
+ success: false,
2495
+ error: "Invalid date"
2496
+ };
2497
+ }
2498
+ const formatted = format(date, input.outputFormat);
2499
+ return {
2500
+ success: true,
2501
+ formatted,
2502
+ iso: date.toISOString()
2503
+ };
2504
+ } catch (error) {
1753
2505
  return {
1754
2506
  success: false,
1755
- error: "Invalid date"
2507
+ error: error instanceof Error ? error.message : "Failed to format date"
1756
2508
  };
1757
2509
  }
1758
- const duration = { [input.unit]: input.amount };
1759
- const result = input.operation === "add" ? add(date, duration) : sub(date, duration);
1760
- return {
1761
- success: true,
1762
- result: result.toISOString(),
1763
- unix: Math.floor(result.getTime() / 1e3)
1764
- };
1765
- } catch (error) {
1766
- return {
1767
- success: false,
1768
- error: error instanceof Error ? error.message : "Failed to perform date arithmetic"
1769
- };
1770
- }
1771
- }).build();
1772
- var dateDifference = toolBuilder().name("date-difference").description("Calculate the difference between two dates in various units (days, hours, minutes).").category(ToolCategory.UTILITY).tags(["date", "time", "difference", "duration"]).schema(z.object({
1773
- startDate: z.string().describe("Start date (ISO string or Unix timestamp)"),
1774
- endDate: z.string().describe("End date (ISO string or Unix timestamp)"),
1775
- unit: z.enum(["days", "hours", "minutes"]).default("days").describe("Unit for the difference")
1776
- })).implement(async (input) => {
1777
- try {
1778
- const start = new Date(input.startDate);
1779
- const end = new Date(input.endDate);
1780
- if (!isValid(start) || !isValid(end)) {
2510
+ }).build();
2511
+ }
2512
+ function createDateArithmeticTool() {
2513
+ return toolBuilder().name("date-arithmetic").description("Add or subtract time from a date. Supports years, months, weeks, days, hours, minutes, and seconds.").category(ToolCategory.UTILITY).tags(["date", "time", "add", "subtract", "arithmetic"]).schema(DateArithmeticSchema).implement(async (input) => {
2514
+ try {
2515
+ const date = new Date(input.date);
2516
+ if (!isValid(date)) {
2517
+ return {
2518
+ success: false,
2519
+ error: "Invalid date"
2520
+ };
2521
+ }
2522
+ const duration = { [input.unit]: input.amount };
2523
+ const result = input.operation === "add" ? add(date, duration) : sub(date, duration);
2524
+ return {
2525
+ success: true,
2526
+ result: result.toISOString(),
2527
+ unix: Math.floor(result.getTime() / 1e3)
2528
+ };
2529
+ } catch (error) {
1781
2530
  return {
1782
2531
  success: false,
1783
- error: "Invalid date(s)"
2532
+ error: error instanceof Error ? error.message : "Failed to perform date arithmetic"
1784
2533
  };
1785
2534
  }
1786
- let difference;
1787
- if (input.unit === "days") {
1788
- difference = differenceInDays(end, start);
1789
- } else if (input.unit === "hours") {
1790
- difference = differenceInHours(end, start);
1791
- } else {
1792
- difference = differenceInMinutes(end, start);
2535
+ }).build();
2536
+ }
2537
+ function createDateDifferenceTool() {
2538
+ return toolBuilder().name("date-difference").description("Calculate the difference between two dates in various units (days, hours, minutes).").category(ToolCategory.UTILITY).tags(["date", "time", "difference", "duration"]).schema(DateDifferenceSchema).implement(async (input) => {
2539
+ try {
2540
+ const start = new Date(input.startDate);
2541
+ const end = new Date(input.endDate);
2542
+ if (!isValid(start) || !isValid(end)) {
2543
+ return {
2544
+ success: false,
2545
+ error: "Invalid date(s)"
2546
+ };
2547
+ }
2548
+ let difference;
2549
+ if (input.unit === "days") {
2550
+ difference = differenceInDays(end, start);
2551
+ } else if (input.unit === "hours") {
2552
+ difference = differenceInHours(end, start);
2553
+ } else {
2554
+ difference = differenceInMinutes(end, start);
2555
+ }
2556
+ return {
2557
+ success: true,
2558
+ difference,
2559
+ unit: input.unit,
2560
+ startDate: start.toISOString(),
2561
+ endDate: end.toISOString()
2562
+ };
2563
+ } catch (error) {
2564
+ return {
2565
+ success: false,
2566
+ error: error instanceof Error ? error.message : "Failed to calculate date difference"
2567
+ };
1793
2568
  }
1794
- return {
1795
- success: true,
1796
- difference,
1797
- unit: input.unit,
1798
- startDate: start.toISOString(),
1799
- endDate: end.toISOString()
1800
- };
1801
- } catch (error) {
1802
- return {
1803
- success: false,
1804
- error: error instanceof Error ? error.message : "Failed to calculate date difference"
1805
- };
1806
- }
1807
- }).build();
1808
- var dateComparison = toolBuilder().name("date-comparison").description("Compare two dates to determine if one is before, after, or equal to the other.").category(ToolCategory.UTILITY).tags(["date", "time", "compare", "comparison"]).schema(z.object({
1809
- date1: z.string().describe("First date to compare"),
1810
- date2: z.string().describe("Second date to compare")
1811
- })).implement(async (input) => {
1812
- try {
1813
- const d1 = new Date(input.date1);
1814
- const d2 = new Date(input.date2);
1815
- if (!isValid(d1) || !isValid(d2)) {
2569
+ }).build();
2570
+ }
2571
+ function createDateComparisonTool() {
2572
+ return toolBuilder().name("date-comparison").description("Compare two dates to determine if one is before, after, or equal to the other.").category(ToolCategory.UTILITY).tags(["date", "time", "compare", "comparison"]).schema(DateComparisonSchema).implement(async (input) => {
2573
+ try {
2574
+ const d1 = new Date(input.date1);
2575
+ const d2 = new Date(input.date2);
2576
+ if (!isValid(d1) || !isValid(d2)) {
2577
+ return {
2578
+ success: false,
2579
+ error: "Invalid date(s)"
2580
+ };
2581
+ }
2582
+ return {
2583
+ success: true,
2584
+ date1IsBefore: isBefore(d1, d2),
2585
+ date1IsAfter: isAfter(d1, d2),
2586
+ datesAreEqual: d1.getTime() === d2.getTime(),
2587
+ date1: d1.toISOString(),
2588
+ date2: d2.toISOString()
2589
+ };
2590
+ } catch (error) {
1816
2591
  return {
1817
2592
  success: false,
1818
- error: "Invalid date(s)"
2593
+ error: error instanceof Error ? error.message : "Failed to compare dates"
1819
2594
  };
1820
2595
  }
1821
- return {
1822
- success: true,
1823
- date1IsBefore: isBefore(d1, d2),
1824
- date1IsAfter: isAfter(d1, d2),
1825
- datesAreEqual: d1.getTime() === d2.getTime(),
1826
- date1: d1.toISOString(),
1827
- date2: d2.toISOString()
1828
- };
1829
- } catch (error) {
1830
- return {
1831
- success: false,
1832
- error: error instanceof Error ? error.message : "Failed to compare dates"
1833
- };
1834
- }
1835
- }).build();
1836
- var stringCaseConverter = toolBuilder().name("string-case-converter").description("Convert string to different cases: lowercase, uppercase, title case, camel case, snake case, kebab case.").category(ToolCategory.UTILITY).tags(["string", "case", "convert", "transform"]).schema(z.object({
2596
+ }).build();
2597
+ }
2598
+
2599
+ // src/utility/date-time/index.ts
2600
+ var currentDateTime = createCurrentDateTimeTool();
2601
+ var dateFormatter = createDateFormatterTool();
2602
+ var dateArithmetic = createDateArithmeticTool();
2603
+ var dateDifference = createDateDifferenceTool();
2604
+ var dateComparison = createDateComparisonTool();
2605
+ var dateTimeTools = [
2606
+ currentDateTime,
2607
+ dateFormatter,
2608
+ dateArithmetic,
2609
+ dateDifference,
2610
+ dateComparison
2611
+ ];
2612
+ function createDateTimeTools(config = {}) {
2613
+ return [
2614
+ createCurrentDateTimeTool(),
2615
+ createDateFormatterTool(),
2616
+ createDateArithmeticTool(),
2617
+ createDateDifferenceTool(),
2618
+ createDateComparisonTool()
2619
+ ];
2620
+ }
2621
+ var StringCaseConverterSchema = z.object({
1837
2622
  text: z.string().describe("Text to convert"),
1838
2623
  targetCase: z.enum(["lowercase", "uppercase", "title", "camel", "snake", "kebab", "pascal"]).describe("Target case format")
1839
- })).implement(async (input) => {
1840
- let result;
1841
- switch (input.targetCase) {
1842
- case "lowercase":
1843
- result = input.text.toLowerCase();
1844
- break;
1845
- case "uppercase":
1846
- result = input.text.toUpperCase();
1847
- break;
1848
- case "title":
1849
- result = input.text.toLowerCase().replace(/\b\w/g, (char) => char.toUpperCase());
1850
- break;
1851
- case "camel":
1852
- result = input.text.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.toUpperCase());
1853
- break;
1854
- case "snake":
1855
- result = input.text.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
1856
- break;
1857
- case "kebab":
1858
- result = input.text.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
1859
- break;
1860
- case "pascal":
1861
- result = input.text.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.toUpperCase()).replace(/^./, (char) => char.toUpperCase());
1862
- break;
1863
- default:
1864
- result = input.text;
1865
- }
1866
- return {
1867
- original: input.text,
1868
- converted: result,
1869
- targetCase: input.targetCase
1870
- };
1871
- }).build();
1872
- var stringTrim = toolBuilder().name("string-trim").description("Remove whitespace from the beginning and/or end of a string. Supports trim, trim start, and trim end.").category(ToolCategory.UTILITY).tags(["string", "trim", "whitespace"]).schema(z.object({
2624
+ });
2625
+ var StringTrimSchema = z.object({
1873
2626
  text: z.string().describe("Text to trim"),
1874
2627
  mode: z.enum(["both", "start", "end"]).default("both").describe("Which side to trim"),
1875
2628
  characters: z.string().optional().describe("Optional custom characters to trim (default: whitespace)")
1876
- })).implement(async (input) => {
1877
- let result;
1878
- if (input.characters) {
1879
- const chars = input.characters.split("").map((c) => c.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
1880
- const regex = input.mode === "both" ? new RegExp(`^[${chars}]+|[${chars}]+$`, "g") : input.mode === "start" ? new RegExp(`^[${chars}]+`, "g") : new RegExp(`[${chars}]+$`, "g");
1881
- result = input.text.replace(regex, "");
1882
- } else {
1883
- result = input.mode === "both" ? input.text.trim() : input.mode === "start" ? input.text.trimStart() : input.text.trimEnd();
1884
- }
1885
- return {
1886
- original: input.text,
1887
- trimmed: result,
1888
- removed: input.text.length - result.length
1889
- };
1890
- }).build();
1891
- var stringReplace = toolBuilder().name("string-replace").description("Replace occurrences of a substring or pattern in a string. Supports regex patterns and global replacement.").category(ToolCategory.UTILITY).tags(["string", "replace", "substitute"]).schema(z.object({
2629
+ });
2630
+ var StringReplaceSchema = z.object({
1892
2631
  text: z.string().describe("Text to search in"),
1893
2632
  search: z.string().describe("String or regex pattern to search for"),
1894
2633
  replace: z.string().describe("Replacement string"),
1895
2634
  global: z.boolean().default(true).describe("Replace all occurrences (true) or just the first (false)"),
1896
2635
  caseInsensitive: z.boolean().default(false).describe("Case-insensitive search")
1897
- })).implement(async (input) => {
1898
- const flags = (input.global ? "g" : "") + (input.caseInsensitive ? "i" : "");
1899
- const regex = new RegExp(input.search, flags);
1900
- const result = input.text.replace(regex, input.replace);
1901
- const matches = input.text.match(regex);
1902
- const count = matches ? matches.length : 0;
1903
- return {
1904
- original: input.text,
1905
- result,
1906
- replacements: count
1907
- };
1908
- }).build();
1909
- var stringSplit = toolBuilder().name("string-split").description("Split a string into an array of substrings using a delimiter. Supports regex delimiters and limit.").category(ToolCategory.UTILITY).tags(["string", "split", "array"]).schema(z.object({
2636
+ });
2637
+ var StringSplitSchema = z.object({
1910
2638
  text: z.string().describe("Text to split"),
1911
2639
  delimiter: z.string().describe("Delimiter to split on (can be a regex pattern)"),
1912
2640
  limit: z.number().optional().describe("Maximum number of splits")
1913
- })).implement(async (input) => {
1914
- const parts = input.text.split(input.delimiter, input.limit);
1915
- return {
1916
- parts,
1917
- count: parts.length
1918
- };
1919
- }).build();
1920
- var stringJoin = toolBuilder().name("string-join").description("Join an array of strings into a single string with a separator.").category(ToolCategory.UTILITY).tags(["string", "join", "array"]).schema(z.object({
2641
+ });
2642
+ var StringJoinSchema = z.object({
1921
2643
  parts: z.array(z.string().describe("String value")).describe("Array of strings to join"),
1922
2644
  separator: z.string().default("").describe("Separator to use between parts")
1923
- })).implement(async (input) => {
1924
- const result = input.parts.join(input.separator);
1925
- return {
1926
- result,
1927
- partCount: input.parts.length,
1928
- length: result.length
1929
- };
1930
- }).build();
1931
- var stringSubstring = toolBuilder().name("string-substring").description("Extract a substring from a string using start and end positions.").category(ToolCategory.UTILITY).tags(["string", "substring", "slice"]).schema(z.object({
2645
+ });
2646
+ var StringSubstringSchema = z.object({
1932
2647
  text: z.string().describe("Source text"),
1933
2648
  start: z.number().describe("Start position (0-based)"),
1934
2649
  end: z.number().optional().describe("End position (optional, defaults to end of string)")
1935
- })).implement(async (input) => {
1936
- const result = input.text.substring(input.start, input.end);
1937
- return {
1938
- result,
1939
- length: result.length,
1940
- start: input.start,
1941
- end: input.end ?? input.text.length
1942
- };
1943
- }).build();
1944
- var stringLength = toolBuilder().name("string-length").description("Get the length of a string in characters, words, or lines.").category(ToolCategory.UTILITY).tags(["string", "length", "count"]).schema(z.object({
2650
+ });
2651
+ var StringLengthSchema = z.object({
1945
2652
  text: z.string().describe("Text to measure")
1946
- })).implement(async (input) => {
1947
- const words = input.text.trim().split(/\s+/).filter((w) => w.length > 0);
1948
- const lines = input.text.split("\n");
1949
- return {
1950
- characters: input.text.length,
1951
- words: words.length,
1952
- lines: lines.length
1953
- };
1954
- }).build();
1955
- var calculator = toolBuilder().name("calculator").description("Perform basic arithmetic operations: add, subtract, multiply, divide, power, modulo.").category(ToolCategory.UTILITY).tags(["math", "calculator", "arithmetic"]).schema(z.object({
2653
+ });
2654
+
2655
+ // src/utility/string/tools/string-case-converter.ts
2656
+ function createStringCaseConverterTool() {
2657
+ return toolBuilder().name("string-case-converter").description("Convert string to different cases: lowercase, uppercase, title case, camel case, snake case, kebab case.").category(ToolCategory.UTILITY).tags(["string", "case", "convert", "transform"]).schema(StringCaseConverterSchema).implement(async (input) => {
2658
+ let result;
2659
+ switch (input.targetCase) {
2660
+ case "lowercase":
2661
+ result = input.text.toLowerCase();
2662
+ break;
2663
+ case "uppercase":
2664
+ result = input.text.toUpperCase();
2665
+ break;
2666
+ case "title":
2667
+ result = input.text.toLowerCase().replace(/\b\w/g, (char) => char.toUpperCase());
2668
+ break;
2669
+ case "camel":
2670
+ result = input.text.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.toUpperCase());
2671
+ break;
2672
+ case "snake":
2673
+ result = input.text.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
2674
+ break;
2675
+ case "kebab":
2676
+ result = input.text.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
2677
+ break;
2678
+ case "pascal":
2679
+ result = input.text.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.toUpperCase()).replace(/^./, (char) => char.toUpperCase());
2680
+ break;
2681
+ default:
2682
+ result = input.text;
2683
+ }
2684
+ return {
2685
+ original: input.text,
2686
+ converted: result,
2687
+ targetCase: input.targetCase
2688
+ };
2689
+ }).build();
2690
+ }
2691
+ function createStringTrimTool() {
2692
+ return toolBuilder().name("string-trim").description("Remove whitespace from the beginning and/or end of a string. Supports trim, trim start, and trim end.").category(ToolCategory.UTILITY).tags(["string", "trim", "whitespace"]).schema(StringTrimSchema).implement(async (input) => {
2693
+ let result;
2694
+ if (input.characters) {
2695
+ const chars = input.characters.split("").map((c) => c.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
2696
+ const regex = input.mode === "both" ? new RegExp(`^[${chars}]+|[${chars}]+$`, "g") : input.mode === "start" ? new RegExp(`^[${chars}]+`, "g") : new RegExp(`[${chars}]+$`, "g");
2697
+ result = input.text.replace(regex, "");
2698
+ } else {
2699
+ result = input.mode === "both" ? input.text.trim() : input.mode === "start" ? input.text.trimStart() : input.text.trimEnd();
2700
+ }
2701
+ return {
2702
+ original: input.text,
2703
+ trimmed: result,
2704
+ removed: input.text.length - result.length
2705
+ };
2706
+ }).build();
2707
+ }
2708
+ function createStringReplaceTool() {
2709
+ return toolBuilder().name("string-replace").description("Replace occurrences of a substring or pattern in a string. Supports regex patterns and global replacement.").category(ToolCategory.UTILITY).tags(["string", "replace", "substitute"]).schema(StringReplaceSchema).implement(async (input) => {
2710
+ const flags = (input.global ? "g" : "") + (input.caseInsensitive ? "i" : "");
2711
+ const regex = new RegExp(input.search, flags);
2712
+ const result = input.text.replace(regex, input.replace);
2713
+ const matches = input.text.match(regex);
2714
+ const count = matches ? matches.length : 0;
2715
+ return {
2716
+ original: input.text,
2717
+ result,
2718
+ replacements: count
2719
+ };
2720
+ }).build();
2721
+ }
2722
+ function createStringSplitTool() {
2723
+ return toolBuilder().name("string-split").description("Split a string into an array of substrings using a delimiter. Supports regex delimiters and limit.").category(ToolCategory.UTILITY).tags(["string", "split", "array"]).schema(StringSplitSchema).implement(async (input) => {
2724
+ const parts = input.text.split(input.delimiter, input.limit);
2725
+ return {
2726
+ parts,
2727
+ count: parts.length
2728
+ };
2729
+ }).build();
2730
+ }
2731
+ function createStringJoinTool() {
2732
+ return toolBuilder().name("string-join").description("Join an array of strings into a single string with a separator.").category(ToolCategory.UTILITY).tags(["string", "join", "array"]).schema(StringJoinSchema).implement(async (input) => {
2733
+ const result = input.parts.join(input.separator);
2734
+ return {
2735
+ result,
2736
+ partCount: input.parts.length,
2737
+ length: result.length
2738
+ };
2739
+ }).build();
2740
+ }
2741
+ function createStringSubstringTool() {
2742
+ return toolBuilder().name("string-substring").description("Extract a substring from a string using start and end positions.").category(ToolCategory.UTILITY).tags(["string", "substring", "slice"]).schema(StringSubstringSchema).implement(async (input) => {
2743
+ const result = input.text.substring(input.start, input.end);
2744
+ return {
2745
+ result,
2746
+ length: result.length,
2747
+ start: input.start,
2748
+ end: input.end ?? input.text.length
2749
+ };
2750
+ }).build();
2751
+ }
2752
+ function createStringLengthTool() {
2753
+ return toolBuilder().name("string-length").description("Get the length of a string in characters, words, or lines.").category(ToolCategory.UTILITY).tags(["string", "length", "count"]).schema(StringLengthSchema).implement(async (input) => {
2754
+ const words = input.text.trim().split(/\s+/).filter((w) => w.length > 0);
2755
+ const lines = input.text.split("\n");
2756
+ return {
2757
+ characters: input.text.length,
2758
+ words: words.length,
2759
+ lines: lines.length
2760
+ };
2761
+ }).build();
2762
+ }
2763
+
2764
+ // src/utility/string/index.ts
2765
+ var stringCaseConverter = createStringCaseConverterTool();
2766
+ var stringTrim = createStringTrimTool();
2767
+ var stringReplace = createStringReplaceTool();
2768
+ var stringSplit = createStringSplitTool();
2769
+ var stringJoin = createStringJoinTool();
2770
+ var stringSubstring = createStringSubstringTool();
2771
+ var stringLength = createStringLengthTool();
2772
+ var stringUtilityTools = [
2773
+ stringCaseConverter,
2774
+ stringTrim,
2775
+ stringReplace,
2776
+ stringSplit,
2777
+ stringJoin,
2778
+ stringSubstring,
2779
+ stringLength
2780
+ ];
2781
+ function createStringUtilityTools(config = {}) {
2782
+ return [
2783
+ createStringCaseConverterTool(),
2784
+ createStringTrimTool(),
2785
+ createStringReplaceTool(),
2786
+ createStringSplitTool(),
2787
+ createStringJoinTool(),
2788
+ createStringSubstringTool(),
2789
+ createStringLengthTool()
2790
+ ];
2791
+ }
2792
+ var CalculatorSchema = z.object({
1956
2793
  operation: z.enum(["add", "subtract", "multiply", "divide", "power", "modulo"]).describe("Mathematical operation to perform"),
1957
2794
  a: z.number().describe("First number"),
1958
2795
  b: z.number().describe("Second number")
1959
- })).implement(async (input) => {
1960
- let result;
1961
- switch (input.operation) {
1962
- case "add":
1963
- result = input.a + input.b;
1964
- break;
1965
- case "subtract":
1966
- result = input.a - input.b;
1967
- break;
1968
- case "multiply":
1969
- result = input.a * input.b;
1970
- break;
1971
- case "divide":
1972
- if (input.b === 0) {
1973
- return {
1974
- success: false,
1975
- error: "Division by zero"
1976
- };
1977
- }
1978
- result = input.a / input.b;
1979
- break;
1980
- case "power":
1981
- result = Math.pow(input.a, input.b);
1982
- break;
1983
- case "modulo":
1984
- result = input.a % input.b;
1985
- break;
1986
- default:
1987
- return {
1988
- success: false,
1989
- error: "Unknown operation"
1990
- };
1991
- }
1992
- return {
1993
- success: true,
1994
- result,
1995
- operation: input.operation,
1996
- a: input.a,
1997
- b: input.b
1998
- };
1999
- }).build();
2000
- var mathFunctions = toolBuilder().name("math-functions").description("Apply mathematical functions: sqrt, abs, round, floor, ceil, sin, cos, tan, log, exp.").category(ToolCategory.UTILITY).tags(["math", "functions", "trigonometry"]).schema(z.object({
2796
+ });
2797
+ var MathFunctionsSchema = z.object({
2001
2798
  function: z.enum(["sqrt", "abs", "round", "floor", "ceil", "sin", "cos", "tan", "log", "exp"]).describe("Mathematical function to apply"),
2002
2799
  value: z.number().describe("Input value")
2003
- })).implement(async (input) => {
2004
- let result;
2005
- try {
2006
- switch (input.function) {
2007
- case "sqrt":
2008
- result = Math.sqrt(input.value);
2009
- break;
2010
- case "abs":
2011
- result = Math.abs(input.value);
2012
- break;
2013
- case "round":
2014
- result = Math.round(input.value);
2015
- break;
2016
- case "floor":
2017
- result = Math.floor(input.value);
2018
- break;
2019
- case "ceil":
2020
- result = Math.ceil(input.value);
2800
+ });
2801
+ var RandomNumberSchema = z.object({
2802
+ min: z.number().default(0).describe("Minimum value (inclusive)"),
2803
+ max: z.number().default(1).describe("Maximum value (exclusive for decimals, inclusive for integers)"),
2804
+ integer: z.boolean().default(false).describe("Generate an integer (true) or decimal (false)")
2805
+ });
2806
+ var StatisticsSchema = z.object({
2807
+ numbers: z.array(z.number().describe("Number value")).describe("Array of numbers to analyze")
2808
+ });
2809
+
2810
+ // src/utility/math/tools/calculator.ts
2811
+ function createCalculatorTool() {
2812
+ return toolBuilder().name("calculator").description("Perform basic arithmetic operations: add, subtract, multiply, divide, power, modulo.").category(ToolCategory.UTILITY).tags(["math", "calculator", "arithmetic"]).schema(CalculatorSchema).implement(async (input) => {
2813
+ let result;
2814
+ switch (input.operation) {
2815
+ case "add":
2816
+ result = input.a + input.b;
2021
2817
  break;
2022
- case "sin":
2023
- result = Math.sin(input.value);
2818
+ case "subtract":
2819
+ result = input.a - input.b;
2024
2820
  break;
2025
- case "cos":
2026
- result = Math.cos(input.value);
2821
+ case "multiply":
2822
+ result = input.a * input.b;
2027
2823
  break;
2028
- case "tan":
2029
- result = Math.tan(input.value);
2824
+ case "divide":
2825
+ if (input.b === 0) {
2826
+ return {
2827
+ success: false,
2828
+ error: "Division by zero"
2829
+ };
2830
+ }
2831
+ result = input.a / input.b;
2030
2832
  break;
2031
- case "log":
2032
- result = Math.log(input.value);
2833
+ case "power":
2834
+ result = Math.pow(input.a, input.b);
2033
2835
  break;
2034
- case "exp":
2035
- result = Math.exp(input.value);
2836
+ case "modulo":
2837
+ result = input.a % input.b;
2036
2838
  break;
2037
2839
  default:
2038
2840
  return {
2039
2841
  success: false,
2040
- error: "Unknown function"
2842
+ error: "Unknown operation"
2041
2843
  };
2042
2844
  }
2043
- if (isNaN(result) || !isFinite(result)) {
2845
+ return {
2846
+ success: true,
2847
+ result,
2848
+ operation: input.operation,
2849
+ a: input.a,
2850
+ b: input.b
2851
+ };
2852
+ }).build();
2853
+ }
2854
+ function createMathFunctionsTool() {
2855
+ return toolBuilder().name("math-functions").description("Apply mathematical functions: sqrt, abs, round, floor, ceil, sin, cos, tan, log, exp.").category(ToolCategory.UTILITY).tags(["math", "functions", "trigonometry"]).schema(MathFunctionsSchema).implement(async (input) => {
2856
+ let result;
2857
+ try {
2858
+ switch (input.function) {
2859
+ case "sqrt":
2860
+ result = Math.sqrt(input.value);
2861
+ break;
2862
+ case "abs":
2863
+ result = Math.abs(input.value);
2864
+ break;
2865
+ case "round":
2866
+ result = Math.round(input.value);
2867
+ break;
2868
+ case "floor":
2869
+ result = Math.floor(input.value);
2870
+ break;
2871
+ case "ceil":
2872
+ result = Math.ceil(input.value);
2873
+ break;
2874
+ case "sin":
2875
+ result = Math.sin(input.value);
2876
+ break;
2877
+ case "cos":
2878
+ result = Math.cos(input.value);
2879
+ break;
2880
+ case "tan":
2881
+ result = Math.tan(input.value);
2882
+ break;
2883
+ case "log":
2884
+ result = Math.log(input.value);
2885
+ break;
2886
+ case "exp":
2887
+ result = Math.exp(input.value);
2888
+ break;
2889
+ default:
2890
+ return {
2891
+ success: false,
2892
+ error: "Unknown function"
2893
+ };
2894
+ }
2895
+ if (isNaN(result) || !isFinite(result)) {
2896
+ return {
2897
+ success: false,
2898
+ error: "Invalid result (NaN or Infinity)"
2899
+ };
2900
+ }
2901
+ return {
2902
+ success: true,
2903
+ result,
2904
+ function: input.function,
2905
+ input: input.value
2906
+ };
2907
+ } catch (error) {
2044
2908
  return {
2045
2909
  success: false,
2046
- error: "Invalid result (NaN or Infinity)"
2910
+ error: error instanceof Error ? error.message : "Math operation failed"
2047
2911
  };
2048
2912
  }
2913
+ }).build();
2914
+ }
2915
+ function createRandomNumberTool() {
2916
+ return toolBuilder().name("random-number").description("Generate a random number within a specified range. Supports integers and decimals.").category(ToolCategory.UTILITY).tags(["random", "number", "generator"]).schema(RandomNumberSchema).implement(async (input) => {
2917
+ const min = input.min ?? 0;
2918
+ const max = input.max ?? 1;
2919
+ const integer = input.integer ?? false;
2920
+ let result;
2921
+ if (integer) {
2922
+ result = Math.floor(Math.random() * (max - min + 1)) + min;
2923
+ } else {
2924
+ result = Math.random() * (max - min) + min;
2925
+ }
2049
2926
  return {
2050
- success: true,
2051
2927
  result,
2052
- function: input.function,
2053
- input: input.value
2054
- };
2055
- } catch (error) {
2056
- return {
2057
- success: false,
2058
- error: error instanceof Error ? error.message : "Math operation failed"
2928
+ min,
2929
+ max,
2930
+ integer
2059
2931
  };
2060
- }
2061
- }).build();
2062
- var randomNumber = toolBuilder().name("random-number").description("Generate a random number within a specified range. Supports integers and decimals.").category(ToolCategory.UTILITY).tags(["random", "number", "generator"]).schema(z.object({
2063
- min: z.number().default(0).describe("Minimum value (inclusive)"),
2064
- max: z.number().default(1).describe("Maximum value (exclusive for decimals, inclusive for integers)"),
2065
- integer: z.boolean().default(false).describe("Generate an integer (true) or decimal (false)")
2066
- })).implement(async (input) => {
2067
- const min = input.min ?? 0;
2068
- const max = input.max ?? 1;
2069
- const integer = input.integer ?? false;
2070
- let result;
2071
- if (integer) {
2072
- result = Math.floor(Math.random() * (max - min + 1)) + min;
2073
- } else {
2074
- result = Math.random() * (max - min) + min;
2075
- }
2076
- return {
2077
- result,
2078
- min,
2079
- max,
2080
- integer
2081
- };
2082
- }).build();
2083
- var statistics = toolBuilder().name("statistics").description("Calculate statistics for an array of numbers: sum, average, min, max, median, standard deviation.").category(ToolCategory.UTILITY).tags(["math", "statistics", "average", "sum"]).schema(z.object({
2084
- numbers: z.array(z.number().describe("Number value")).describe("Array of numbers to analyze")
2085
- })).implement(async (input) => {
2086
- if (input.numbers.length === 0) {
2932
+ }).build();
2933
+ }
2934
+ function createStatisticsTool() {
2935
+ return toolBuilder().name("statistics").description("Calculate statistics for an array of numbers: sum, average, min, max, median, standard deviation.").category(ToolCategory.UTILITY).tags(["math", "statistics", "average", "sum"]).schema(StatisticsSchema).implement(async (input) => {
2936
+ if (input.numbers.length === 0) {
2937
+ return {
2938
+ success: false,
2939
+ error: "Empty array"
2940
+ };
2941
+ }
2942
+ const sorted = [...input.numbers].sort((a, b) => a - b);
2943
+ const sum = input.numbers.reduce((acc, n) => acc + n, 0);
2944
+ const average = sum / input.numbers.length;
2945
+ const min = sorted[0];
2946
+ const max = sorted[sorted.length - 1];
2947
+ const mid = Math.floor(sorted.length / 2);
2948
+ const median = sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
2949
+ const variance = input.numbers.reduce((acc, n) => acc + Math.pow(n - average, 2), 0) / input.numbers.length;
2950
+ const stdDev = Math.sqrt(variance);
2087
2951
  return {
2088
- success: false,
2089
- error: "Empty array"
2952
+ success: true,
2953
+ count: input.numbers.length,
2954
+ sum,
2955
+ average,
2956
+ min,
2957
+ max,
2958
+ median,
2959
+ standardDeviation: stdDev,
2960
+ variance
2090
2961
  };
2091
- }
2092
- const sorted = [...input.numbers].sort((a, b) => a - b);
2093
- const sum = input.numbers.reduce((acc, n) => acc + n, 0);
2094
- const average = sum / input.numbers.length;
2095
- const min = sorted[0];
2096
- const max = sorted[sorted.length - 1];
2097
- const mid = Math.floor(sorted.length / 2);
2098
- const median = sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
2099
- const variance = input.numbers.reduce((acc, n) => acc + Math.pow(n - average, 2), 0) / input.numbers.length;
2100
- const stdDev = Math.sqrt(variance);
2101
- return {
2102
- success: true,
2103
- count: input.numbers.length,
2104
- sum,
2105
- average,
2106
- min,
2107
- max,
2108
- median,
2109
- standardDeviation: stdDev,
2110
- variance
2111
- };
2112
- }).build();
2113
- var emailValidator = toolBuilder().name("email-validator").description("Validate if a string is a valid email address format.").category(ToolCategory.UTILITY).tags(["validation", "email", "validate"]).schema(z.object({
2962
+ }).build();
2963
+ }
2964
+
2965
+ // src/utility/math/index.ts
2966
+ var calculator = createCalculatorTool();
2967
+ var mathFunctions = createMathFunctionsTool();
2968
+ var randomNumber = createRandomNumberTool();
2969
+ var statistics = createStatisticsTool();
2970
+ var mathOperationTools = [
2971
+ calculator,
2972
+ mathFunctions,
2973
+ randomNumber,
2974
+ statistics
2975
+ ];
2976
+ function createMathOperationTools(config = {}) {
2977
+ return [
2978
+ createCalculatorTool(),
2979
+ createMathFunctionsTool(),
2980
+ createRandomNumberTool(),
2981
+ createStatisticsTool()
2982
+ ];
2983
+ }
2984
+ var EmailValidatorSchema = z.object({
2114
2985
  email: z.string().describe("Email address to validate")
2115
- })).implement(async (input) => {
2116
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2117
- const valid = emailRegex.test(input.email);
2118
- return {
2119
- valid,
2120
- email: input.email,
2121
- message: valid ? "Valid email address" : "Invalid email address format"
2122
- };
2123
- }).build();
2124
- var urlValidatorSimple = toolBuilder().name("url-validator-simple").description("Validate if a string is a valid URL format.").category(ToolCategory.UTILITY).tags(["validation", "url", "validate"]).schema(z.object({
2986
+ });
2987
+ var UrlValidatorSimpleSchema = z.object({
2125
2988
  url: z.string().describe("URL to validate")
2126
- })).implement(async (input) => {
2127
- try {
2128
- new URL(input.url);
2989
+ });
2990
+ var PhoneValidatorSchema = z.object({
2991
+ phone: z.string().describe("Phone number to validate"),
2992
+ strict: z.boolean().default(false).describe("Use strict validation (requires country code)")
2993
+ });
2994
+ var CreditCardValidatorSchema = z.object({
2995
+ cardNumber: z.string().describe("Credit card number to validate")
2996
+ });
2997
+ var IpValidatorSchema = z.object({
2998
+ ip: z.string().describe("IP address to validate"),
2999
+ version: z.enum(["v4", "v6", "any"]).default("any").describe("IP version to validate against")
3000
+ });
3001
+ var UuidValidatorSchema = z.object({
3002
+ uuid: z.string().describe("UUID to validate")
3003
+ });
3004
+
3005
+ // src/utility/validation/tools/email-validator.ts
3006
+ function createEmailValidatorTool() {
3007
+ return toolBuilder().name("email-validator").description("Validate if a string is a valid email address format.").category(ToolCategory.UTILITY).tags(["validation", "email", "validate"]).schema(EmailValidatorSchema).implement(async (input) => {
3008
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
3009
+ const valid = emailRegex.test(input.email);
2129
3010
  return {
2130
- valid: true,
2131
- url: input.url,
2132
- message: "Valid URL"
3011
+ valid,
3012
+ email: input.email,
3013
+ message: valid ? "Valid email address" : "Invalid email address format"
2133
3014
  };
2134
- } catch {
3015
+ }).build();
3016
+ }
3017
+ function createUrlValidatorSimpleTool() {
3018
+ return toolBuilder().name("url-validator-simple").description("Validate if a string is a valid URL format.").category(ToolCategory.UTILITY).tags(["validation", "url", "validate"]).schema(UrlValidatorSimpleSchema).implement(async (input) => {
3019
+ try {
3020
+ new URL(input.url);
3021
+ return {
3022
+ valid: true,
3023
+ url: input.url,
3024
+ message: "Valid URL"
3025
+ };
3026
+ } catch {
3027
+ return {
3028
+ valid: false,
3029
+ url: input.url,
3030
+ message: "Invalid URL format"
3031
+ };
3032
+ }
3033
+ }).build();
3034
+ }
3035
+ function createPhoneValidatorTool() {
3036
+ return toolBuilder().name("phone-validator").description("Validate if a string is a valid phone number format. Supports various international formats.").category(ToolCategory.UTILITY).tags(["validation", "phone", "validate"]).schema(PhoneValidatorSchema).implement(async (input) => {
3037
+ const basicRegex = /^[\d\s\-\+\(\)]+$/;
3038
+ const strictRegex = /^\+?[1-9]\d{1,14}$/;
3039
+ const regex = input.strict ? strictRegex : basicRegex;
3040
+ const valid = regex.test(input.phone.replace(/\s/g, ""));
2135
3041
  return {
2136
- valid: false,
2137
- url: input.url,
2138
- message: "Invalid URL format"
3042
+ valid,
3043
+ phone: input.phone,
3044
+ message: valid ? "Valid phone number format" : "Invalid phone number format"
2139
3045
  };
2140
- }
2141
- }).build();
2142
- var phoneValidator = toolBuilder().name("phone-validator").description("Validate if a string is a valid phone number format. Supports various international formats.").category(ToolCategory.UTILITY).tags(["validation", "phone", "validate"]).schema(z.object({
2143
- phone: z.string().describe("Phone number to validate"),
2144
- strict: z.boolean().default(false).describe("Use strict validation (requires country code)")
2145
- })).implement(async (input) => {
2146
- const basicRegex = /^[\d\s\-\+\(\)]+$/;
2147
- const strictRegex = /^\+?[1-9]\d{1,14}$/;
2148
- const regex = input.strict ? strictRegex : basicRegex;
2149
- const valid = regex.test(input.phone.replace(/\s/g, ""));
2150
- return {
2151
- valid,
2152
- phone: input.phone,
2153
- message: valid ? "Valid phone number format" : "Invalid phone number format"
2154
- };
2155
- }).build();
2156
- var creditCardValidator = toolBuilder().name("credit-card-validator").description("Validate if a string is a valid credit card number using the Luhn algorithm.").category(ToolCategory.UTILITY).tags(["validation", "credit-card", "validate", "luhn"]).schema(z.object({
2157
- cardNumber: z.string().describe("Credit card number to validate")
2158
- })).implement(async (input) => {
2159
- const cleaned = input.cardNumber.replace(/[\s\-]/g, "");
2160
- if (!/^\d+$/.test(cleaned)) {
3046
+ }).build();
3047
+ }
3048
+ function createCreditCardValidatorTool() {
3049
+ return toolBuilder().name("credit-card-validator").description("Validate if a string is a valid credit card number using the Luhn algorithm.").category(ToolCategory.UTILITY).tags(["validation", "credit-card", "validate", "luhn"]).schema(CreditCardValidatorSchema).implement(async (input) => {
3050
+ const cleaned = input.cardNumber.replace(/[\s\-]/g, "");
3051
+ if (!/^\d+$/.test(cleaned)) {
3052
+ return {
3053
+ valid: false,
3054
+ message: "Card number must contain only digits"
3055
+ };
3056
+ }
3057
+ let sum = 0;
3058
+ let isEven = false;
3059
+ for (let i = cleaned.length - 1; i >= 0; i--) {
3060
+ let digit = parseInt(cleaned[i], 10);
3061
+ if (isEven) {
3062
+ digit *= 2;
3063
+ if (digit > 9) {
3064
+ digit -= 9;
3065
+ }
3066
+ }
3067
+ sum += digit;
3068
+ isEven = !isEven;
3069
+ }
3070
+ const valid = sum % 10 === 0;
2161
3071
  return {
2162
- valid: false,
2163
- message: "Card number must contain only digits"
3072
+ valid,
3073
+ cardNumber: input.cardNumber,
3074
+ message: valid ? "Valid credit card number" : "Invalid credit card number (failed Luhn check)"
2164
3075
  };
2165
- }
2166
- let sum = 0;
2167
- let isEven = false;
2168
- for (let i = cleaned.length - 1; i >= 0; i--) {
2169
- let digit = parseInt(cleaned[i], 10);
2170
- if (isEven) {
2171
- digit *= 2;
2172
- if (digit > 9) {
2173
- digit -= 9;
3076
+ }).build();
3077
+ }
3078
+ function createIpValidatorTool() {
3079
+ return toolBuilder().name("ip-validator").description("Validate if a string is a valid IPv4 or IPv6 address.").category(ToolCategory.UTILITY).tags(["validation", "ip", "validate", "network"]).schema(IpValidatorSchema).implement(async (input) => {
3080
+ const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
3081
+ const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
3082
+ let valid = false;
3083
+ let detectedVersion;
3084
+ if (input.version === "v4" || input.version === "any") {
3085
+ if (ipv4Regex.test(input.ip)) {
3086
+ const parts = input.ip.split(".");
3087
+ valid = parts.every((part) => {
3088
+ const num = parseInt(part, 10);
3089
+ return num >= 0 && num <= 255;
3090
+ });
3091
+ if (valid) detectedVersion = "IPv4";
2174
3092
  }
2175
3093
  }
2176
- sum += digit;
2177
- isEven = !isEven;
2178
- }
2179
- const valid = sum % 10 === 0;
2180
- return {
2181
- valid,
2182
- cardNumber: input.cardNumber,
2183
- message: valid ? "Valid credit card number" : "Invalid credit card number (failed Luhn check)"
2184
- };
2185
- }).build();
2186
- var ipValidator = toolBuilder().name("ip-validator").description("Validate if a string is a valid IPv4 or IPv6 address.").category(ToolCategory.UTILITY).tags(["validation", "ip", "validate", "network"]).schema(z.object({
2187
- ip: z.string().describe("IP address to validate"),
2188
- version: z.enum(["v4", "v6", "any"]).default("any").describe("IP version to validate against")
2189
- })).implement(async (input) => {
2190
- const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
2191
- const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
2192
- let valid = false;
2193
- let detectedVersion;
2194
- if (input.version === "v4" || input.version === "any") {
2195
- if (ipv4Regex.test(input.ip)) {
2196
- const parts = input.ip.split(".");
2197
- valid = parts.every((part) => {
2198
- const num = parseInt(part, 10);
2199
- return num >= 0 && num <= 255;
2200
- });
2201
- if (valid) detectedVersion = "IPv4";
3094
+ if (!valid && (input.version === "v6" || input.version === "any")) {
3095
+ if (ipv6Regex.test(input.ip)) {
3096
+ valid = true;
3097
+ detectedVersion = "IPv6";
3098
+ }
2202
3099
  }
2203
- }
2204
- if (!valid && (input.version === "v6" || input.version === "any")) {
2205
- if (ipv6Regex.test(input.ip)) {
2206
- valid = true;
2207
- detectedVersion = "IPv6";
3100
+ return {
3101
+ valid,
3102
+ ip: input.ip,
3103
+ version: detectedVersion,
3104
+ message: valid ? `Valid ${detectedVersion} address` : "Invalid IP address format"
3105
+ };
3106
+ }).build();
3107
+ }
3108
+ function createUuidValidatorTool() {
3109
+ return toolBuilder().name("uuid-validator").description("Validate if a string is a valid UUID (v1, v3, v4, or v5).").category(ToolCategory.UTILITY).tags(["validation", "uuid", "validate", "guid"]).schema(UuidValidatorSchema).implement(async (input) => {
3110
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
3111
+ const valid = uuidRegex.test(input.uuid);
3112
+ let version;
3113
+ if (valid) {
3114
+ version = parseInt(input.uuid[14], 10);
2208
3115
  }
2209
- }
2210
- return {
2211
- valid,
2212
- ip: input.ip,
2213
- version: detectedVersion,
2214
- message: valid ? `Valid ${detectedVersion} address` : "Invalid IP address format"
2215
- };
2216
- }).build();
2217
- var uuidValidator = toolBuilder().name("uuid-validator").description("Validate if a string is a valid UUID (v1, v3, v4, or v5).").category(ToolCategory.UTILITY).tags(["validation", "uuid", "validate", "guid"]).schema(z.object({
2218
- uuid: z.string().describe("UUID to validate")
2219
- })).implement(async (input) => {
2220
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
2221
- const valid = uuidRegex.test(input.uuid);
2222
- let version;
2223
- if (valid) {
2224
- version = parseInt(input.uuid[14], 10);
2225
- }
2226
- return {
2227
- valid,
2228
- uuid: input.uuid,
2229
- version,
2230
- message: valid ? `Valid UUID v${version}` : "Invalid UUID format"
2231
- };
2232
- }).build();
3116
+ return {
3117
+ valid,
3118
+ uuid: input.uuid,
3119
+ version,
3120
+ message: valid ? `Valid UUID v${version}` : "Invalid UUID format"
3121
+ };
3122
+ }).build();
3123
+ }
3124
+
3125
+ // src/utility/validation/index.ts
3126
+ var emailValidator = createEmailValidatorTool();
3127
+ var urlValidatorSimple = createUrlValidatorSimpleTool();
3128
+ var phoneValidator = createPhoneValidatorTool();
3129
+ var creditCardValidator = createCreditCardValidatorTool();
3130
+ var ipValidator = createIpValidatorTool();
3131
+ var uuidValidator = createUuidValidatorTool();
3132
+ var validationTools = [
3133
+ emailValidator,
3134
+ urlValidatorSimple,
3135
+ phoneValidator,
3136
+ creditCardValidator,
3137
+ ipValidator,
3138
+ uuidValidator
3139
+ ];
3140
+ function createValidationTools(config = {}) {
3141
+ return [
3142
+ createEmailValidatorTool(),
3143
+ createUrlValidatorSimpleTool(),
3144
+ createPhoneValidatorTool(),
3145
+ createCreditCardValidatorTool(),
3146
+ createIpValidatorTool(),
3147
+ createUuidValidatorTool()
3148
+ ];
3149
+ }
2233
3150
  var AskHumanInputSchema = z.object({
2234
3151
  /**
2235
3152
  * The question to ask the human
@@ -2256,8 +3173,8 @@ var AskHumanInputSchema = z.object({
2256
3173
  */
2257
3174
  suggestions: z.array(z.string()).optional().describe("Suggested responses for the human")
2258
3175
  });
2259
- var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
2260
- var logger2 = createLogger("askHuman", { level: logLevel2 });
3176
+ var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
3177
+ var logger3 = createLogger("askHuman", { level: logLevel3 });
2261
3178
  function createAskHumanTool() {
2262
3179
  return toolBuilder().name("ask-human").description(
2263
3180
  "Ask a human for input or approval. Use this when you need human guidance, approval for a critical action, or clarification on ambiguous requirements. The agent execution will pause until the human responds."
@@ -2290,13 +3207,13 @@ function createAskHumanTool() {
2290
3207
  suggestions: validatedInput.suggestions,
2291
3208
  status: "pending"
2292
3209
  };
2293
- logger2.debug("About to call interrupt()", { humanRequest });
3210
+ logger3.debug("About to call interrupt()", { humanRequest });
2294
3211
  let response;
2295
3212
  try {
2296
3213
  response = interrupt(humanRequest);
2297
- logger2.debug("interrupt() returned successfully", { response, responseType: typeof response });
3214
+ logger3.debug("interrupt() returned successfully", { response, responseType: typeof response });
2298
3215
  } catch (error) {
2299
- logger2.debug("interrupt() threw error (expected for GraphInterrupt)", {
3216
+ logger3.debug("interrupt() threw error (expected for GraphInterrupt)", {
2300
3217
  errorType: error?.constructor?.name,
2301
3218
  error: error instanceof Error ? error.message : String(error)
2302
3219
  });
@@ -2321,6 +3238,6 @@ function createAskHumanTool() {
2321
3238
  }
2322
3239
  var askHumanTool = createAskHumanTool();
2323
3240
 
2324
- export { AskHumanInputSchema, DuckDuckGoProvider, SerperProvider, arrayFilter, arrayGroupBy, arrayMap, arraySort, askHumanTool, calculator, createAskHumanTool, createDuckDuckGoProvider, createSerperProvider, createSlackTools, creditCardValidator, csvGenerator, csvParser, csvToJson, currentDateTime, dateArithmetic, dateComparison, dateDifference, dateFormatter, directoryCreate, directoryDelete, directoryList, emailValidator, extractImages, extractLinks, fileAppend, fileDelete, fileExists, fileReader, fileSearch, fileWriter, getSlackChannels, getSlackMessages, htmlParser, httpClient, httpGet, httpPost, ipValidator, jsonMerge, jsonParser, jsonQuery, jsonStringify, jsonToCsv, jsonToXml, jsonValidator, mathFunctions, notifySlack, objectOmit, objectPick, pathBasename, pathDirname, pathExtension, pathJoin, pathNormalize, pathParse, pathRelative, pathResolve, phoneValidator, randomNumber, searchResultSchema, sendSlackMessage, slackTools, statistics, stringCaseConverter, stringJoin, stringLength, stringReplace, stringSplit, stringSubstring, stringTrim, urlBuilder, urlQueryParser, urlValidator, urlValidatorSimple, uuidValidator, webScraper, webSearch, webSearchOutputSchema, webSearchSchema, xmlGenerator, xmlParser, xmlToJson };
3241
+ export { AskHumanInputSchema, CalculatorSchema, CreditCardValidatorSchema, CurrentDateTimeSchema, DateArithmeticSchema, DateComparisonSchema, DateDifferenceSchema, DateFormatterSchema, DuckDuckGoProvider, EmailValidatorSchema, HttpMethod, IpValidatorSchema, MathFunctionsSchema, PhoneValidatorSchema, RandomNumberSchema, SerperProvider, StatisticsSchema, StringCaseConverterSchema, StringJoinSchema, StringLengthSchema, StringReplaceSchema, StringSplitSchema, StringSubstringSchema, StringTrimSchema, UrlValidatorSimpleSchema, UuidValidatorSchema, archiveConfluencePage, arrayFilter, arrayFilterSchema, arrayGroupBy, arrayGroupBySchema, arrayMap, arrayMapSchema, arraySort, arraySortSchema, askHumanTool, calculator, confluenceTools, createArrayFilterTool, createArrayGroupByTool, createArrayMapTool, createArraySortTool, createAskHumanTool, createCalculatorTool, createConfluencePage, createConfluenceTools, createCreditCardValidatorTool, createCsvGeneratorTool, createCsvParserTool, createCsvToJsonTool, createCsvTools, createCurrentDateTimeTool, createDateArithmeticTool, createDateComparisonTool, createDateDifferenceTool, createDateFormatterTool, createDateTimeTools, createDirectoryCreateTool, createDirectoryDeleteTool, createDirectoryListTool, createDirectoryOperationTools, createDuckDuckGoProvider, createEmailValidatorTool, createExtractImagesTool, createExtractLinksTool, createFileAppendTool, createFileDeleteTool, createFileExistsTool, createFileOperationTools, createFileReaderTool, createFileSearchTool, createFileWriterTool, createHtmlParserTool, createHtmlParserTools, createHttpTools, createIpValidatorTool, createJsonMergeTool, createJsonParserTool, createJsonQueryTool, createJsonStringifyTool, createJsonToCsvTool, createJsonToXmlTool, createJsonTools, createJsonValidatorTool, createMathFunctionsTool, createMathOperationTools, createObjectOmitTool, createObjectPickTool, createPathBasenameTool, createPathDirnameTool, createPathExtensionTool, createPathJoinTool, createPathNormalizeTool, createPathParseTool, createPathRelativeTool, createPathResolveTool, createPathUtilityTools, createPhoneValidatorTool, createRandomNumberTool, createScraperTools, createSerperProvider, createSlackTools, createStatisticsTool, createStringCaseConverterTool, createStringJoinTool, createStringLengthTool, createStringReplaceTool, createStringSplitTool, createStringSubstringTool, createStringTrimTool, createStringUtilityTools, createTransformerTools, createUrlBuilderTool, createUrlQueryParserTool, createUrlValidatorSimpleTool, createUrlValidatorTool, createUrlValidatorTools, createUuidValidatorTool, createValidationTools, createWebScraperTool, createXmlGeneratorTool, createXmlParserTool, createXmlToJsonTool, createXmlTools, creditCardValidator, csvGenerator, csvGeneratorSchema, csvParser, csvParserSchema, csvToJson, csvToJsonSchema, csvTools, currentDateTime, dateArithmetic, dateComparison, dateDifference, dateFormatter, dateTimeTools, directoryCreate, directoryCreateSchema, directoryDelete, directoryDeleteSchema, directoryList, directoryListSchema, directoryOperationTools, emailValidator, extractImages, extractImagesSchema, extractLinks, extractLinksSchema, fileAppend, fileAppendSchema, fileDelete, fileDeleteSchema, fileExists, fileExistsSchema, fileOperationTools, fileReader, fileReaderSchema, fileSearch, fileSearchSchema, fileWriter, fileWriterSchema, getConfluencePage, getSlackChannels, getSlackMessages, getSpacePages, htmlParser, htmlParserSchema, htmlParserTools, httpClient, httpGet, httpGetSchema, httpPost, httpPostSchema, httpRequestSchema, httpTools, ipValidator, jsonMerge, jsonMergeSchema, jsonParser, jsonParserSchema, jsonQuery, jsonQuerySchema, jsonStringify, jsonStringifySchema, jsonToCsv, jsonToCsvSchema, jsonToXml, jsonToXmlSchema, jsonTools, jsonValidator, jsonValidatorSchema, listConfluenceSpaces, mathFunctions, mathOperationTools, notifySlack, objectOmit, objectOmitSchema, objectPick, objectPickSchema, pathBasename, pathBasenameSchema, pathDirname, pathDirnameSchema, pathExtension, pathExtensionSchema, pathJoin, pathJoinSchema, pathNormalize, pathNormalizeSchema, pathParse, pathParseSchema, pathRelative, pathRelativeSchema, pathResolve, pathResolveSchema, pathUtilityTools, phoneValidator, randomNumber, scraperTools, searchConfluence, searchResultSchema, sendSlackMessage, slackTools, statistics, stringCaseConverter, stringJoin, stringLength, stringReplace, stringSplit, stringSubstring, stringTrim, stringUtilityTools, transformerTools, updateConfluencePage, urlBuilder, urlBuilderSchema, urlQueryParser, urlQueryParserSchema, urlValidator, urlValidatorSchema, urlValidatorSimple, urlValidatorTools, uuidValidator, validationTools, webScraper, webScraperSchema, webSearch, webSearchOutputSchema, webSearchSchema, xmlGenerator, xmlGeneratorSchema, xmlParser, xmlParserSchema, xmlToJson, xmlToJsonSchema, xmlTools };
2325
3242
  //# sourceMappingURL=index.js.map
2326
3243
  //# sourceMappingURL=index.js.map