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