@agentforge/tools 0.18.4 → 0.18.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +385 -367
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -322
- package/dist/index.d.ts +118 -322
- package/dist/index.js +384 -366
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var core = require('@agentforge/core');
|
|
4
4
|
var promises = require('dns/promises');
|
|
5
5
|
var net = require('net');
|
|
6
|
-
var
|
|
6
|
+
var axios5 = require('axios');
|
|
7
7
|
var zod = require('zod');
|
|
8
8
|
var cheerio = require('cheerio');
|
|
9
9
|
var webApi = require('@slack/web-api');
|
|
@@ -41,7 +41,7 @@ function _interopNamespace(e) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
var net__default = /*#__PURE__*/_interopDefault(net);
|
|
44
|
-
var
|
|
44
|
+
var axios5__default = /*#__PURE__*/_interopDefault(axios5);
|
|
45
45
|
var cheerio__namespace = /*#__PURE__*/_interopNamespace(cheerio);
|
|
46
46
|
var neo4j__default = /*#__PURE__*/_interopDefault(neo4j);
|
|
47
47
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
@@ -229,7 +229,7 @@ async function requestWithDestinationPolicy(config, policy = {}) {
|
|
|
229
229
|
for (let redirectCount = 0; ; redirectCount += 1) {
|
|
230
230
|
const validatedAddresses = await validateDestinationAllowed(currentUrl, effectivePolicy);
|
|
231
231
|
currentConfig.lookup = createPinnedLookup(validatedAddresses);
|
|
232
|
-
const response = await
|
|
232
|
+
const response = await axios5__default.default(currentConfig);
|
|
233
233
|
if (!isRedirectStatus(response.status)) return response;
|
|
234
234
|
if (effectivePolicy.allowRedirects === false) blockDestination(currentUrl, "redirect");
|
|
235
235
|
if (redirectCount >= maxRedirects) throw new DestinationPolicyError(currentUrl, "redirect", `Maximum redirect count (${maxRedirects}) exceeded for ${currentUrl}`);
|
|
@@ -740,7 +740,7 @@ var DuckDuckGoProvider = class {
|
|
|
740
740
|
async search(query, maxResults, timeout = DEFAULT_TIMEOUT) {
|
|
741
741
|
try {
|
|
742
742
|
return await retryWithBackoff(async () => {
|
|
743
|
-
const response = await
|
|
743
|
+
const response = await axios5__default.default.get("https://api.duckduckgo.com/", {
|
|
744
744
|
params: {
|
|
745
745
|
q: query,
|
|
746
746
|
format: "json"
|
|
@@ -841,7 +841,7 @@ var SerperProvider = class {
|
|
|
841
841
|
}
|
|
842
842
|
try {
|
|
843
843
|
return await retryWithBackoff(async () => {
|
|
844
|
-
const response = await
|
|
844
|
+
const response = await axios5__default.default.post(
|
|
845
845
|
"https://google.serper.dev/search",
|
|
846
846
|
{
|
|
847
847
|
q: query,
|
|
@@ -977,47 +977,33 @@ var webSearch = core.toolBuilder().name("web-search").description(
|
|
|
977
977
|
};
|
|
978
978
|
}
|
|
979
979
|
}).build();
|
|
980
|
-
function
|
|
981
|
-
let
|
|
982
|
-
return
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
if (!
|
|
986
|
-
throw new Error(
|
|
987
|
-
"Slack token not configured. Please provide a token in config or set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
|
|
988
|
-
);
|
|
980
|
+
function createLazySlackClient(resolveToken, config, missingTokenError) {
|
|
981
|
+
let client = null;
|
|
982
|
+
return () => {
|
|
983
|
+
const token = resolveToken();
|
|
984
|
+
if (!client) {
|
|
985
|
+
if (!token) {
|
|
986
|
+
throw new Error(missingTokenError);
|
|
989
987
|
}
|
|
990
|
-
|
|
988
|
+
client = new webApi.WebClient(token);
|
|
991
989
|
}
|
|
992
|
-
return {
|
|
993
|
-
client: configuredClient,
|
|
994
|
-
config: {
|
|
995
|
-
token: token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN || "",
|
|
996
|
-
botName,
|
|
997
|
-
botIcon
|
|
998
|
-
}
|
|
999
|
-
};
|
|
990
|
+
return { client, config: { token: token || "", ...config } };
|
|
1000
991
|
};
|
|
1001
992
|
}
|
|
1002
|
-
|
|
993
|
+
function createGetConfiguredSlackClient(token, botName = "AgentForge Bot", botIcon = ":robot_face:") {
|
|
994
|
+
return createLazySlackClient(
|
|
995
|
+
() => token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN,
|
|
996
|
+
{ botName, botIcon },
|
|
997
|
+
"Slack token not configured. Please provide a token in config or set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
|
|
998
|
+
);
|
|
999
|
+
}
|
|
1000
|
+
var getLazyDefaultSlackClient = createLazySlackClient(
|
|
1001
|
+
() => process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN,
|
|
1002
|
+
{ botName: "AgentForge Bot", botIcon: ":robot_face:" },
|
|
1003
|
+
"Slack token not configured. Please set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
|
|
1004
|
+
);
|
|
1003
1005
|
function getDefaultSlackClient() {
|
|
1004
|
-
|
|
1005
|
-
const token = process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN;
|
|
1006
|
-
if (!token) {
|
|
1007
|
-
throw new Error(
|
|
1008
|
-
"Slack token not configured. Please set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
|
|
1009
|
-
);
|
|
1010
|
-
}
|
|
1011
|
-
defaultSlackClient = new webApi.WebClient(token);
|
|
1012
|
-
}
|
|
1013
|
-
return {
|
|
1014
|
-
client: defaultSlackClient,
|
|
1015
|
-
config: {
|
|
1016
|
-
token: process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN || "",
|
|
1017
|
-
botName: "AgentForge Bot",
|
|
1018
|
-
botIcon: ":robot_face:"
|
|
1019
|
-
}
|
|
1020
|
-
};
|
|
1006
|
+
return getLazyDefaultSlackClient();
|
|
1021
1007
|
}
|
|
1022
1008
|
function createSendSlackMessageTool(getSlackClient, logger20) {
|
|
1023
1009
|
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(
|
|
@@ -1244,38 +1230,91 @@ function createGetConfiguredAuth(apiKey, email, siteUrl) {
|
|
|
1244
1230
|
return { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, ATLASSIAN_SITE_URL };
|
|
1245
1231
|
};
|
|
1246
1232
|
}
|
|
1247
|
-
function createGetConfiguredAuthHeader(getConfiguredAuth) {
|
|
1248
|
-
return function getConfiguredAuthHeader() {
|
|
1249
|
-
const { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL } = getConfiguredAuth();
|
|
1250
|
-
const auth2 = Buffer.from(`${ATLASSIAN_EMAIL}:${ATLASSIAN_API_KEY}`).toString("base64");
|
|
1251
|
-
return `Basic ${auth2}`;
|
|
1252
|
-
};
|
|
1253
|
-
}
|
|
1254
1233
|
function getConfig() {
|
|
1255
1234
|
const ATLASSIAN_API_KEY = process.env.ATLASSIAN_API_KEY || "";
|
|
1256
1235
|
const ATLASSIAN_EMAIL = process.env.ATLASSIAN_EMAIL || "";
|
|
1257
1236
|
const ATLASSIAN_SITE_URL = (process.env.ATLASSIAN_SITE_URL || "").replace(/\/$/, "");
|
|
1258
1237
|
if (!ATLASSIAN_API_KEY || !ATLASSIAN_EMAIL || !ATLASSIAN_SITE_URL) {
|
|
1259
|
-
throw new Error(
|
|
1238
|
+
throw new Error(
|
|
1239
|
+
"Confluence credentials not configured. Set ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, and ATLASSIAN_SITE_URL in .env"
|
|
1240
|
+
);
|
|
1260
1241
|
}
|
|
1261
1242
|
return { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, ATLASSIAN_SITE_URL };
|
|
1262
1243
|
}
|
|
1263
|
-
function
|
|
1264
|
-
|
|
1265
|
-
const auth2 = Buffer.from(`${ATLASSIAN_EMAIL}:${ATLASSIAN_API_KEY}`).toString("base64");
|
|
1266
|
-
return `Basic ${auth2}`;
|
|
1244
|
+
function isRecord(value) {
|
|
1245
|
+
return typeof value === "object" && value !== null;
|
|
1267
1246
|
}
|
|
1268
|
-
function
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1247
|
+
function describeError(error) {
|
|
1248
|
+
const errorRecord = isRecord(error) ? error : void 0;
|
|
1249
|
+
const response = isRecord(errorRecord?.response) ? errorRecord.response : void 0;
|
|
1250
|
+
const responseData = isRecord(response?.data) ? response.data : void 0;
|
|
1251
|
+
const providerMessage = typeof responseData?.message === "string" ? responseData.message : void 0;
|
|
1252
|
+
const errorMessage = typeof errorRecord?.message === "string" ? errorRecord.message : void 0;
|
|
1253
|
+
return {
|
|
1254
|
+
message: providerMessage || errorMessage,
|
|
1255
|
+
status: typeof response?.status === "number" ? response.status : void 0
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
function authenticatedConfig(auth2, config = {}) {
|
|
1259
|
+
const credentials = Buffer.from(`${auth2.ATLASSIAN_EMAIL}:${auth2.ATLASSIAN_API_KEY}`).toString(
|
|
1260
|
+
"base64"
|
|
1261
|
+
);
|
|
1262
|
+
return {
|
|
1263
|
+
...config,
|
|
1264
|
+
headers: {
|
|
1265
|
+
...config.headers,
|
|
1266
|
+
Authorization: `Basic ${credentials}`
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
function createConfluenceRequest(getAuth) {
|
|
1271
|
+
return {
|
|
1272
|
+
async get(path13, config = {}) {
|
|
1273
|
+
const auth2 = getAuth();
|
|
1274
|
+
const response = await axios5__default.default.get(
|
|
1275
|
+
`${auth2.ATLASSIAN_SITE_URL}${path13}`,
|
|
1276
|
+
authenticatedConfig(auth2, config)
|
|
1277
|
+
);
|
|
1278
|
+
return { data: response.data, siteUrl: auth2.ATLASSIAN_SITE_URL };
|
|
1279
|
+
},
|
|
1280
|
+
async post(path13, data, config = {}) {
|
|
1281
|
+
const auth2 = getAuth();
|
|
1282
|
+
const response = await axios5__default.default.post(
|
|
1283
|
+
`${auth2.ATLASSIAN_SITE_URL}${path13}`,
|
|
1284
|
+
data,
|
|
1285
|
+
authenticatedConfig(auth2, config)
|
|
1286
|
+
);
|
|
1287
|
+
return { data: response.data, siteUrl: auth2.ATLASSIAN_SITE_URL };
|
|
1288
|
+
},
|
|
1289
|
+
async put(path13, data, config = {}) {
|
|
1290
|
+
const auth2 = getAuth();
|
|
1291
|
+
const response = await axios5__default.default.put(
|
|
1292
|
+
`${auth2.ATLASSIAN_SITE_URL}${path13}`,
|
|
1293
|
+
data,
|
|
1294
|
+
authenticatedConfig(auth2, config)
|
|
1295
|
+
);
|
|
1296
|
+
return { data: response.data, siteUrl: auth2.ATLASSIAN_SITE_URL };
|
|
1297
|
+
},
|
|
1298
|
+
describeError
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
function createSearchConfluenceTool(request2, logger20) {
|
|
1302
|
+
return core.toolBuilder().name("search-confluence").description(
|
|
1303
|
+
"Search for pages in Confluence using keywords or CQL (Confluence Query Language). Returns matching pages with titles, IDs, and excerpts."
|
|
1304
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("search").tag("knowledge-base").usageNotes(
|
|
1305
|
+
"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."
|
|
1306
|
+
).suggests(["get-confluence-page"]).schema(
|
|
1307
|
+
zod.z.object({
|
|
1308
|
+
query: zod.z.string().describe(
|
|
1309
|
+
"Search query or CQL expression (e.g., 'payment processing' or 'space=BL3 AND title~payment')"
|
|
1310
|
+
),
|
|
1311
|
+
limit: zod.z.number().optional().describe("Maximum number of results to return (default: 10, max: 25)")
|
|
1312
|
+
})
|
|
1313
|
+
).implement(async ({ query, limit = 10 }) => {
|
|
1273
1314
|
logger20.info("search-confluence called", { query, limit });
|
|
1274
1315
|
try {
|
|
1275
|
-
const
|
|
1276
|
-
const response = await axios11__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/search`, {
|
|
1316
|
+
const response = await request2.get("/wiki/rest/api/content/search", {
|
|
1277
1317
|
headers: {
|
|
1278
|
-
Authorization: getAuthHeader2(),
|
|
1279
1318
|
Accept: "application/json"
|
|
1280
1319
|
},
|
|
1281
1320
|
params: {
|
|
@@ -1284,22 +1323,24 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1284
1323
|
expand: "space,version"
|
|
1285
1324
|
}
|
|
1286
1325
|
});
|
|
1287
|
-
const { ATLASSIAN_SITE_URL: siteUrl } = getAuth();
|
|
1288
1326
|
const results = response.data.results.map((page) => ({
|
|
1289
1327
|
id: page.id,
|
|
1290
1328
|
title: page.title,
|
|
1291
1329
|
type: page.type,
|
|
1292
1330
|
space: page.space?.name || "Unknown",
|
|
1293
1331
|
spaceKey: page.space?.key || "",
|
|
1294
|
-
url: `${siteUrl}/wiki${page._links.webui}`,
|
|
1332
|
+
url: `${response.siteUrl}/wiki${page._links.webui}`,
|
|
1295
1333
|
lastModified: page.version?.when || ""
|
|
1296
1334
|
}));
|
|
1297
1335
|
if (results.length === 0) {
|
|
1298
|
-
logger20.warn(
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1336
|
+
logger20.warn(
|
|
1337
|
+
"search-confluence returned NO RESULTS - this is a valid outcome, agent should not retry",
|
|
1338
|
+
{
|
|
1339
|
+
query,
|
|
1340
|
+
limit,
|
|
1341
|
+
totalSize: response.data.totalSize
|
|
1342
|
+
}
|
|
1343
|
+
);
|
|
1303
1344
|
} else {
|
|
1304
1345
|
logger20.info("search-confluence result", {
|
|
1305
1346
|
query,
|
|
@@ -1316,28 +1357,33 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1316
1357
|
results
|
|
1317
1358
|
});
|
|
1318
1359
|
} catch (error) {
|
|
1360
|
+
const description = request2.describeError(error);
|
|
1319
1361
|
logger20.error("search-confluence error", {
|
|
1320
1362
|
query,
|
|
1321
|
-
error:
|
|
1322
|
-
status:
|
|
1363
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1364
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1323
1365
|
});
|
|
1324
1366
|
return JSON.stringify({
|
|
1325
1367
|
success: false,
|
|
1326
|
-
error:
|
|
1368
|
+
error: description.message
|
|
1327
1369
|
});
|
|
1328
1370
|
}
|
|
1329
1371
|
}).build();
|
|
1330
1372
|
}
|
|
1331
|
-
function createGetConfluencePageTool(
|
|
1332
|
-
return core.toolBuilder().name("get-confluence-page").description(
|
|
1333
|
-
|
|
1334
|
-
|
|
1373
|
+
function createGetConfluencePageTool(request2, logger20) {
|
|
1374
|
+
return core.toolBuilder().name("get-confluence-page").description(
|
|
1375
|
+
"Get the full content of a specific Confluence page by its ID. Returns the page title, content (in storage format), space, and metadata."
|
|
1376
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("page").tag("content").usageNotes(
|
|
1377
|
+
"Use this after search-confluence to retrieve the full content of a specific page. The page ID can be found in search results."
|
|
1378
|
+
).requires(["search-confluence"]).schema(
|
|
1379
|
+
zod.z.object({
|
|
1380
|
+
page_id: zod.z.string().describe("The Confluence page ID (from search results)")
|
|
1381
|
+
})
|
|
1382
|
+
).implement(async ({ page_id }) => {
|
|
1335
1383
|
logger20.info("get-confluence-page called", { page_id });
|
|
1336
1384
|
try {
|
|
1337
|
-
const
|
|
1338
|
-
const response = await axios11__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`, {
|
|
1385
|
+
const response = await request2.get(`/wiki/rest/api/content/${page_id}`, {
|
|
1339
1386
|
headers: {
|
|
1340
|
-
Authorization: getAuthHeader2(),
|
|
1341
1387
|
Accept: "application/json"
|
|
1342
1388
|
},
|
|
1343
1389
|
params: {
|
|
@@ -1360,35 +1406,40 @@ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1360
1406
|
space: page.space?.name || "Unknown",
|
|
1361
1407
|
spaceKey: page.space?.key || "",
|
|
1362
1408
|
content: page.body?.storage?.value || "",
|
|
1363
|
-
url: `${
|
|
1409
|
+
url: `${response.siteUrl}/wiki${page._links.webui}`,
|
|
1364
1410
|
created: page.history?.createdDate || "",
|
|
1365
1411
|
lastModified: page.version?.when || "",
|
|
1366
1412
|
version: page.version?.number || 1
|
|
1367
1413
|
}
|
|
1368
1414
|
});
|
|
1369
1415
|
} catch (error) {
|
|
1416
|
+
const description = request2.describeError(error);
|
|
1370
1417
|
logger20.error("get-confluence-page error", {
|
|
1371
1418
|
page_id,
|
|
1372
|
-
error:
|
|
1373
|
-
status:
|
|
1419
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1420
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1374
1421
|
});
|
|
1375
1422
|
return JSON.stringify({
|
|
1376
1423
|
success: false,
|
|
1377
|
-
error:
|
|
1424
|
+
error: description.message
|
|
1378
1425
|
});
|
|
1379
1426
|
}
|
|
1380
1427
|
}).build();
|
|
1381
1428
|
}
|
|
1382
|
-
function createListConfluenceSpacesTool(
|
|
1383
|
-
return core.toolBuilder().name("list-confluence-spaces").description(
|
|
1384
|
-
|
|
1385
|
-
|
|
1429
|
+
function createListConfluenceSpacesTool(request2, logger20) {
|
|
1430
|
+
return core.toolBuilder().name("list-confluence-spaces").description(
|
|
1431
|
+
"List all available Confluence spaces. Returns space names, keys, types, and descriptions to help identify where to search for information."
|
|
1432
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("spaces").tag("list").usageNotes(
|
|
1433
|
+
"Use this first to discover available spaces before searching. Helps narrow down searches to specific areas (e.g., 'AI', 'BL3', 'Finance')."
|
|
1434
|
+
).follows(["search-confluence"]).schema(
|
|
1435
|
+
zod.z.object({
|
|
1436
|
+
limit: zod.z.number().optional().describe("Maximum number of spaces to return (default: 25)")
|
|
1437
|
+
})
|
|
1438
|
+
).implement(async ({ limit = 25 }) => {
|
|
1386
1439
|
logger20.info("list-confluence-spaces called", { limit });
|
|
1387
1440
|
try {
|
|
1388
|
-
const
|
|
1389
|
-
const response = await axios11__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/space`, {
|
|
1441
|
+
const response = await request2.get("/wiki/rest/api/space", {
|
|
1390
1442
|
headers: {
|
|
1391
|
-
Authorization: getAuthHeader2(),
|
|
1392
1443
|
Accept: "application/json"
|
|
1393
1444
|
},
|
|
1394
1445
|
params: {
|
|
@@ -1400,7 +1451,7 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1400
1451
|
name: space.name,
|
|
1401
1452
|
type: space.type,
|
|
1402
1453
|
description: space.description?.plain?.value || "",
|
|
1403
|
-
url: `${
|
|
1454
|
+
url: `${response.siteUrl}/wiki${space._links.webui}`
|
|
1404
1455
|
}));
|
|
1405
1456
|
logger20.info("list-confluence-spaces result", {
|
|
1406
1457
|
spaceCount: spaces.length,
|
|
@@ -1413,28 +1464,33 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1413
1464
|
spaces
|
|
1414
1465
|
});
|
|
1415
1466
|
} catch (error) {
|
|
1467
|
+
const description = request2.describeError(error);
|
|
1416
1468
|
logger20.error("list-confluence-spaces error", {
|
|
1417
|
-
error:
|
|
1418
|
-
status:
|
|
1469
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1470
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1419
1471
|
});
|
|
1420
1472
|
return JSON.stringify({
|
|
1421
1473
|
success: false,
|
|
1422
|
-
error:
|
|
1474
|
+
error: description.message
|
|
1423
1475
|
});
|
|
1424
1476
|
}
|
|
1425
1477
|
}).build();
|
|
1426
1478
|
}
|
|
1427
|
-
function createGetSpacePagesTool(
|
|
1428
|
-
return core.toolBuilder().name("get-space-pages").description(
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1479
|
+
function createGetSpacePagesTool(request2, logger20) {
|
|
1480
|
+
return core.toolBuilder().name("get-space-pages").description(
|
|
1481
|
+
"Get all pages from a specific Confluence space by space key. Useful for browsing content in a particular area."
|
|
1482
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("space").tag("pages").usageNotes(
|
|
1483
|
+
"Use this to explore all pages in a specific space. Get the space key from list-confluence-spaces first."
|
|
1484
|
+
).requires(["list-confluence-spaces"]).schema(
|
|
1485
|
+
zod.z.object({
|
|
1486
|
+
space_key: zod.z.string().describe("The space key (e.g., 'AI', 'BL3', 'FIN')"),
|
|
1487
|
+
limit: zod.z.number().optional().describe("Maximum number of pages to return (default: 25)")
|
|
1488
|
+
})
|
|
1489
|
+
).implement(async ({ space_key, limit = 25 }) => {
|
|
1432
1490
|
logger20.info("get-space-pages called", { space_key, limit });
|
|
1433
1491
|
try {
|
|
1434
|
-
const
|
|
1435
|
-
const response = await axios11__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content`, {
|
|
1492
|
+
const response = await request2.get("/wiki/rest/api/content", {
|
|
1436
1493
|
headers: {
|
|
1437
|
-
Authorization: getAuthHeader2(),
|
|
1438
1494
|
Accept: "application/json"
|
|
1439
1495
|
},
|
|
1440
1496
|
params: {
|
|
@@ -1447,14 +1503,17 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1447
1503
|
const pages = response.data.results.map((page) => ({
|
|
1448
1504
|
id: page.id,
|
|
1449
1505
|
title: page.title,
|
|
1450
|
-
url: `${
|
|
1506
|
+
url: `${response.siteUrl}/wiki${page._links.webui}`,
|
|
1451
1507
|
lastModified: page.version?.when || ""
|
|
1452
1508
|
}));
|
|
1453
1509
|
if (pages.length === 0) {
|
|
1454
|
-
logger20.warn(
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1510
|
+
logger20.warn(
|
|
1511
|
+
"get-space-pages returned NO PAGES - this is a valid outcome, agent should not retry",
|
|
1512
|
+
{
|
|
1513
|
+
space_key,
|
|
1514
|
+
limit
|
|
1515
|
+
}
|
|
1516
|
+
);
|
|
1458
1517
|
} else {
|
|
1459
1518
|
logger20.info("get-space-pages result", {
|
|
1460
1519
|
space_key,
|
|
@@ -1470,28 +1529,38 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1470
1529
|
pages
|
|
1471
1530
|
});
|
|
1472
1531
|
} catch (error) {
|
|
1532
|
+
const description = request2.describeError(error);
|
|
1473
1533
|
logger20.error("get-space-pages error", {
|
|
1474
1534
|
space_key,
|
|
1475
|
-
error:
|
|
1476
|
-
status:
|
|
1535
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1536
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1477
1537
|
});
|
|
1478
1538
|
return JSON.stringify({
|
|
1479
1539
|
success: false,
|
|
1480
|
-
error:
|
|
1540
|
+
error: description.message
|
|
1481
1541
|
});
|
|
1482
1542
|
}
|
|
1483
1543
|
}).build();
|
|
1484
1544
|
}
|
|
1485
|
-
function createCreateConfluencePageTool(
|
|
1486
|
-
return core.toolBuilder().name("create-confluence-page").description(
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1545
|
+
function createCreateConfluencePageTool(request2, logger20) {
|
|
1546
|
+
return core.toolBuilder().name("create-confluence-page").description(
|
|
1547
|
+
"Create a new page in a Confluence space. Requires space key, page title, and content (in HTML storage format)."
|
|
1548
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("create").tag("write").usageNotes(
|
|
1549
|
+
"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."
|
|
1550
|
+
).requires(["list-confluence-spaces"]).schema(
|
|
1551
|
+
zod.z.object({
|
|
1552
|
+
space_key: zod.z.string().describe("The space key where the page will be created (e.g., 'AI', 'BL3')"),
|
|
1553
|
+
title: zod.z.string().describe("The title of the new page"),
|
|
1554
|
+
content: zod.z.string().describe("The page content in HTML format (Confluence storage format)"),
|
|
1555
|
+
parent_page_id: zod.z.string().optional().describe("Optional parent page ID to create this as a child page")
|
|
1556
|
+
})
|
|
1557
|
+
).implement(async ({ space_key, title, content, parent_page_id }) => {
|
|
1558
|
+
logger20.info("create-confluence-page called", {
|
|
1559
|
+
space_key,
|
|
1560
|
+
title,
|
|
1561
|
+
hasParent: !!parent_page_id
|
|
1562
|
+
});
|
|
1493
1563
|
try {
|
|
1494
|
-
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1495
1564
|
const pageData = {
|
|
1496
1565
|
type: "page",
|
|
1497
1566
|
title,
|
|
@@ -1506,16 +1575,11 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1506
1575
|
if (parent_page_id) {
|
|
1507
1576
|
pageData.ancestors = [{ id: parent_page_id }];
|
|
1508
1577
|
}
|
|
1509
|
-
const response = await
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
{
|
|
1513
|
-
headers: {
|
|
1514
|
-
Authorization: getAuthHeader2(),
|
|
1515
|
-
"Content-Type": "application/json"
|
|
1516
|
-
}
|
|
1578
|
+
const response = await request2.post("/wiki/rest/api/content", pageData, {
|
|
1579
|
+
headers: {
|
|
1580
|
+
"Content-Type": "application/json"
|
|
1517
1581
|
}
|
|
1518
|
-
);
|
|
1582
|
+
});
|
|
1519
1583
|
logger20.info("create-confluence-page result", {
|
|
1520
1584
|
page_id: response.data.id,
|
|
1521
1585
|
title: response.data.title,
|
|
@@ -1527,45 +1591,45 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1527
1591
|
id: response.data.id,
|
|
1528
1592
|
title: response.data.title,
|
|
1529
1593
|
space: space_key,
|
|
1530
|
-
url: `${
|
|
1594
|
+
url: `${response.siteUrl}/wiki${response.data._links.webui}`,
|
|
1531
1595
|
version: response.data.version?.number || 1
|
|
1532
1596
|
}
|
|
1533
1597
|
});
|
|
1534
1598
|
} catch (error) {
|
|
1599
|
+
const description = request2.describeError(error);
|
|
1535
1600
|
logger20.error("create-confluence-page error", {
|
|
1536
1601
|
space_key,
|
|
1537
1602
|
title,
|
|
1538
|
-
error:
|
|
1539
|
-
status:
|
|
1603
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1604
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1540
1605
|
});
|
|
1541
1606
|
return JSON.stringify({
|
|
1542
1607
|
success: false,
|
|
1543
|
-
error:
|
|
1608
|
+
error: description.message
|
|
1544
1609
|
});
|
|
1545
1610
|
}
|
|
1546
1611
|
}).build();
|
|
1547
1612
|
}
|
|
1548
|
-
function createUpdateConfluencePageTool(
|
|
1549
|
-
return core.toolBuilder().name("update-confluence-page").description(
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1613
|
+
function createUpdateConfluencePageTool(request2, logger20) {
|
|
1614
|
+
return core.toolBuilder().name("update-confluence-page").description(
|
|
1615
|
+
"Update an existing Confluence page's content. Requires page ID, new title, and new content."
|
|
1616
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("update").tag("write").usageNotes(
|
|
1617
|
+
"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."
|
|
1618
|
+
).requires(["get-confluence-page"]).schema(
|
|
1619
|
+
zod.z.object({
|
|
1620
|
+
page_id: zod.z.string().describe("The ID of the page to update"),
|
|
1621
|
+
title: zod.z.string().describe("The new title for the page"),
|
|
1622
|
+
content: zod.z.string().describe("The new content in HTML format (Confluence storage format)")
|
|
1623
|
+
})
|
|
1624
|
+
).implement(async ({ page_id, title, content }) => {
|
|
1554
1625
|
logger20.info("update-confluence-page called", { page_id, title });
|
|
1555
1626
|
try {
|
|
1556
|
-
const
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
{
|
|
1560
|
-
headers: {
|
|
1561
|
-
Authorization: getAuthHeader2()
|
|
1562
|
-
},
|
|
1563
|
-
params: { expand: "version" }
|
|
1564
|
-
}
|
|
1565
|
-
);
|
|
1627
|
+
const getResponse = await request2.get(`/wiki/rest/api/content/${page_id}`, {
|
|
1628
|
+
params: { expand: "version" }
|
|
1629
|
+
});
|
|
1566
1630
|
const currentVersion = getResponse.data.version.number;
|
|
1567
|
-
const updateResponse = await
|
|
1568
|
-
|
|
1631
|
+
const updateResponse = await request2.put(
|
|
1632
|
+
`/wiki/rest/api/content/${page_id}`,
|
|
1569
1633
|
{
|
|
1570
1634
|
type: "page",
|
|
1571
1635
|
title,
|
|
@@ -1579,7 +1643,6 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1579
1643
|
},
|
|
1580
1644
|
{
|
|
1581
1645
|
headers: {
|
|
1582
|
-
Authorization: getAuthHeader2(),
|
|
1583
1646
|
"Content-Type": "application/json"
|
|
1584
1647
|
}
|
|
1585
1648
|
}
|
|
@@ -1595,49 +1658,49 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1595
1658
|
page: {
|
|
1596
1659
|
id: updateResponse.data.id,
|
|
1597
1660
|
title: updateResponse.data.title,
|
|
1598
|
-
url: `${
|
|
1661
|
+
url: `${updateResponse.siteUrl}/wiki${updateResponse.data._links.webui}`,
|
|
1599
1662
|
version: updateResponse.data.version.number,
|
|
1600
1663
|
previousVersion: currentVersion
|
|
1601
1664
|
}
|
|
1602
1665
|
});
|
|
1603
1666
|
} catch (error) {
|
|
1667
|
+
const description = request2.describeError(error);
|
|
1604
1668
|
logger20.error("update-confluence-page error", {
|
|
1605
1669
|
page_id,
|
|
1606
1670
|
title,
|
|
1607
|
-
error:
|
|
1608
|
-
status:
|
|
1671
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1672
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1609
1673
|
});
|
|
1610
1674
|
return JSON.stringify({
|
|
1611
1675
|
success: false,
|
|
1612
|
-
error:
|
|
1676
|
+
error: description.message
|
|
1613
1677
|
});
|
|
1614
1678
|
}
|
|
1615
1679
|
}).build();
|
|
1616
1680
|
}
|
|
1617
|
-
function createArchiveConfluencePageTool(
|
|
1618
|
-
return core.toolBuilder().name("archive-confluence-page").description(
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1681
|
+
function createArchiveConfluencePageTool(request2, logger20) {
|
|
1682
|
+
return core.toolBuilder().name("archive-confluence-page").description(
|
|
1683
|
+
"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."
|
|
1684
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("archive").tag("delete").usageNotes(
|
|
1685
|
+
"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."
|
|
1686
|
+
).conflicts(["create-confluence-page"]).schema(
|
|
1687
|
+
zod.z.object({
|
|
1688
|
+
page_id: zod.z.string().describe("The ID of the page to archive"),
|
|
1689
|
+
reason: zod.z.string().optional().describe("Optional reason for archiving (for audit trail)")
|
|
1690
|
+
})
|
|
1691
|
+
).implement(async ({ page_id, reason }) => {
|
|
1622
1692
|
logger20.info("archive-confluence-page called", {
|
|
1623
1693
|
page_id,
|
|
1624
1694
|
...reason ? { reason } : {}
|
|
1625
1695
|
});
|
|
1626
1696
|
try {
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
{
|
|
1631
|
-
headers: {
|
|
1632
|
-
Authorization: getAuthHeader2()
|
|
1633
|
-
},
|
|
1634
|
-
params: { expand: "version,body.storage,space" }
|
|
1635
|
-
}
|
|
1636
|
-
);
|
|
1697
|
+
const getResponse = await request2.get(`/wiki/rest/api/content/${page_id}`, {
|
|
1698
|
+
params: { expand: "version,body.storage,space" }
|
|
1699
|
+
});
|
|
1637
1700
|
const currentVersion = getResponse.data.version.number;
|
|
1638
1701
|
const pageData = getResponse.data;
|
|
1639
|
-
await
|
|
1640
|
-
|
|
1702
|
+
await request2.put(
|
|
1703
|
+
`/wiki/rest/api/content/${page_id}`,
|
|
1641
1704
|
{
|
|
1642
1705
|
version: { number: currentVersion + 1 },
|
|
1643
1706
|
title: pageData.title,
|
|
@@ -1648,7 +1711,6 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1648
1711
|
},
|
|
1649
1712
|
{
|
|
1650
1713
|
headers: {
|
|
1651
|
-
Authorization: getAuthHeader2(),
|
|
1652
1714
|
"Content-Type": "application/json"
|
|
1653
1715
|
}
|
|
1654
1716
|
}
|
|
@@ -1671,14 +1733,15 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1671
1733
|
}
|
|
1672
1734
|
});
|
|
1673
1735
|
} catch (error) {
|
|
1736
|
+
const description = request2.describeError(error);
|
|
1674
1737
|
logger20.error("archive-confluence-page error", {
|
|
1675
1738
|
page_id,
|
|
1676
|
-
error:
|
|
1677
|
-
status:
|
|
1739
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1740
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1678
1741
|
});
|
|
1679
1742
|
return JSON.stringify({
|
|
1680
1743
|
success: false,
|
|
1681
|
-
error:
|
|
1744
|
+
error: description.message
|
|
1682
1745
|
});
|
|
1683
1746
|
}
|
|
1684
1747
|
}).build();
|
|
@@ -1687,13 +1750,14 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1687
1750
|
// src/web/confluence/index.ts
|
|
1688
1751
|
var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
|
|
1689
1752
|
var logger2 = core.createLogger("[tools:confluence]", { level: logLevel2 });
|
|
1690
|
-
var
|
|
1691
|
-
var
|
|
1692
|
-
var
|
|
1693
|
-
var
|
|
1694
|
-
var
|
|
1695
|
-
var
|
|
1696
|
-
var
|
|
1753
|
+
var request = createConfluenceRequest(getConfig);
|
|
1754
|
+
var searchConfluence = createSearchConfluenceTool(request, logger2);
|
|
1755
|
+
var getConfluencePage = createGetConfluencePageTool(request, logger2);
|
|
1756
|
+
var listConfluenceSpaces = createListConfluenceSpacesTool(request, logger2);
|
|
1757
|
+
var getSpacePages = createGetSpacePagesTool(request, logger2);
|
|
1758
|
+
var createConfluencePage = createCreateConfluencePageTool(request, logger2);
|
|
1759
|
+
var updateConfluencePage = createUpdateConfluencePageTool(request, logger2);
|
|
1760
|
+
var archiveConfluencePage = createArchiveConfluencePageTool(request, logger2);
|
|
1697
1761
|
var confluenceTools = [
|
|
1698
1762
|
// Read tools
|
|
1699
1763
|
searchConfluence,
|
|
@@ -1706,22 +1770,17 @@ var confluenceTools = [
|
|
|
1706
1770
|
archiveConfluencePage
|
|
1707
1771
|
];
|
|
1708
1772
|
function createConfluenceTools(config = {}) {
|
|
1709
|
-
const {
|
|
1710
|
-
apiKey,
|
|
1711
|
-
email,
|
|
1712
|
-
siteUrl,
|
|
1713
|
-
logLevel: customLogLevel
|
|
1714
|
-
} = config;
|
|
1773
|
+
const { apiKey, email, siteUrl, logLevel: customLogLevel } = config;
|
|
1715
1774
|
const getConfiguredAuth = createGetConfiguredAuth(apiKey, email, siteUrl);
|
|
1716
|
-
const
|
|
1775
|
+
const request2 = createConfluenceRequest(getConfiguredAuth);
|
|
1717
1776
|
const toolLogger = customLogLevel ? core.createLogger("tools:confluence", { level: customLogLevel }) : logger2;
|
|
1718
|
-
const searchConfluence2 = createSearchConfluenceTool(
|
|
1719
|
-
const getConfluencePage2 = createGetConfluencePageTool(
|
|
1720
|
-
const listConfluenceSpaces2 = createListConfluenceSpacesTool(
|
|
1721
|
-
const getSpacePages2 = createGetSpacePagesTool(
|
|
1722
|
-
const createConfluencePage2 = createCreateConfluencePageTool(
|
|
1723
|
-
const updateConfluencePage2 = createUpdateConfluencePageTool(
|
|
1724
|
-
const archiveConfluencePage2 = createArchiveConfluencePageTool(
|
|
1777
|
+
const searchConfluence2 = createSearchConfluenceTool(request2, toolLogger);
|
|
1778
|
+
const getConfluencePage2 = createGetConfluencePageTool(request2, toolLogger);
|
|
1779
|
+
const listConfluenceSpaces2 = createListConfluenceSpacesTool(request2, toolLogger);
|
|
1780
|
+
const getSpacePages2 = createGetSpacePagesTool(request2, toolLogger);
|
|
1781
|
+
const createConfluencePage2 = createCreateConfluencePageTool(request2, toolLogger);
|
|
1782
|
+
const updateConfluencePage2 = createUpdateConfluencePageTool(request2, toolLogger);
|
|
1783
|
+
const archiveConfluencePage2 = createArchiveConfluencePageTool(request2, toolLogger);
|
|
1725
1784
|
return {
|
|
1726
1785
|
searchConfluence: searchConfluence2,
|
|
1727
1786
|
getConfluencePage: getConfluencePage2,
|
|
@@ -1912,14 +1971,14 @@ function createJsonStringifyTool(defaultIndent = 2, defaultPretty = false) {
|
|
|
1912
1971
|
};
|
|
1913
1972
|
}).build();
|
|
1914
1973
|
}
|
|
1915
|
-
function
|
|
1974
|
+
function isRecord2(value) {
|
|
1916
1975
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1917
1976
|
}
|
|
1918
1977
|
function getPathValue(current, part) {
|
|
1919
1978
|
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
|
|
1920
1979
|
if (arrayMatch) {
|
|
1921
1980
|
const [, key, index] = arrayMatch;
|
|
1922
|
-
if (!
|
|
1981
|
+
if (!isRecord2(current)) {
|
|
1923
1982
|
return void 0;
|
|
1924
1983
|
}
|
|
1925
1984
|
const candidate = current[key];
|
|
@@ -1928,7 +1987,7 @@ function getPathValue(current, part) {
|
|
|
1928
1987
|
}
|
|
1929
1988
|
return candidate[parseInt(index, 10)];
|
|
1930
1989
|
}
|
|
1931
|
-
if (!
|
|
1990
|
+
if (!isRecord2(current)) {
|
|
1932
1991
|
return void 0;
|
|
1933
1992
|
}
|
|
1934
1993
|
return current[part];
|
|
@@ -2584,7 +2643,7 @@ async function initializeFromEnv() {
|
|
|
2584
2643
|
// src/data/neo4j/embeddings/utils.ts
|
|
2585
2644
|
function withProviderErrorMetadata(error, message) {
|
|
2586
2645
|
const wrappedError = new Error(message);
|
|
2587
|
-
if (!
|
|
2646
|
+
if (!isRecord3(error)) return wrappedError;
|
|
2588
2647
|
if (typeof error.code === "string") wrappedError.code = error.code;
|
|
2589
2648
|
if (error.response !== void 0) wrappedError.response = error.response;
|
|
2590
2649
|
return wrappedError;
|
|
@@ -2597,12 +2656,12 @@ var DEFAULT_RETRY_CONFIG2 = {
|
|
|
2597
2656
|
// 10 seconds
|
|
2598
2657
|
backoffMultiplier: 2
|
|
2599
2658
|
};
|
|
2600
|
-
function
|
|
2659
|
+
function isRecord3(value) {
|
|
2601
2660
|
return typeof value === "object" && value !== null;
|
|
2602
2661
|
}
|
|
2603
2662
|
function isRetryableError2(error) {
|
|
2604
|
-
if (!
|
|
2605
|
-
const response =
|
|
2663
|
+
if (!isRecord3(error)) return false;
|
|
2664
|
+
const response = isRecord3(error.response) ? error.response : void 0;
|
|
2606
2665
|
const status = typeof response?.status === "number" ? response.status : void 0;
|
|
2607
2666
|
const code = typeof error.code === "string" ? error.code : void 0;
|
|
2608
2667
|
const message = typeof error.message === "string" ? error.message : void 0;
|
|
@@ -2728,7 +2787,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2728
2787
|
const modelToUse = model || this.defaultModel;
|
|
2729
2788
|
return retryWithBackoff2(async () => {
|
|
2730
2789
|
try {
|
|
2731
|
-
const response = await
|
|
2790
|
+
const response = await axios5__default.default.post(
|
|
2732
2791
|
`${this.baseURL}/embeddings`,
|
|
2733
2792
|
{
|
|
2734
2793
|
input: text,
|
|
@@ -2758,7 +2817,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2758
2817
|
};
|
|
2759
2818
|
} catch (error) {
|
|
2760
2819
|
let message;
|
|
2761
|
-
const response =
|
|
2820
|
+
const response = axios5__default.default.isAxiosError(error) ? error.response : void 0;
|
|
2762
2821
|
if (response?.status === 401) {
|
|
2763
2822
|
message = "Invalid OpenAI API key. Get your key at https://platform.openai.com/api-keys";
|
|
2764
2823
|
} else if (response?.status === 429) {
|
|
@@ -2785,7 +2844,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2785
2844
|
const modelToUse = model || this.defaultModel;
|
|
2786
2845
|
return retryWithBackoff2(async () => {
|
|
2787
2846
|
try {
|
|
2788
|
-
const response = await
|
|
2847
|
+
const response = await axios5__default.default.post(
|
|
2789
2848
|
`${this.baseURL}/embeddings`,
|
|
2790
2849
|
{
|
|
2791
2850
|
input: texts,
|
|
@@ -2816,7 +2875,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2816
2875
|
};
|
|
2817
2876
|
} catch (error) {
|
|
2818
2877
|
let message;
|
|
2819
|
-
const response =
|
|
2878
|
+
const response = axios5__default.default.isAxiosError(error) ? error.response : void 0;
|
|
2820
2879
|
if (response?.status === 401) {
|
|
2821
2880
|
message = "Invalid OpenAI API key. Get your key at https://platform.openai.com/api-keys";
|
|
2822
2881
|
} else if (response?.status === 429) {
|
|
@@ -2858,7 +2917,7 @@ var CohereEmbeddingProvider = class {
|
|
|
2858
2917
|
const modelToUse = model || this.defaultModel;
|
|
2859
2918
|
return retryWithBackoff2(async () => {
|
|
2860
2919
|
try {
|
|
2861
|
-
const response = await
|
|
2920
|
+
const response = await axios5__default.default.post(
|
|
2862
2921
|
`${this.baseUrl}/embed`,
|
|
2863
2922
|
{
|
|
2864
2923
|
texts,
|
|
@@ -2886,7 +2945,7 @@ var CohereEmbeddingProvider = class {
|
|
|
2886
2945
|
} : void 0
|
|
2887
2946
|
};
|
|
2888
2947
|
} catch (error) {
|
|
2889
|
-
if (
|
|
2948
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
2890
2949
|
const status = error.response?.status;
|
|
2891
2950
|
const providerMessage = error.response?.data?.message || error.message;
|
|
2892
2951
|
let message;
|
|
@@ -2921,80 +2980,54 @@ var HuggingFaceEmbeddingProvider = class {
|
|
|
2921
2980
|
return !!this.apiKey;
|
|
2922
2981
|
}
|
|
2923
2982
|
async generateEmbedding(text, model) {
|
|
2924
|
-
const modelToUse =
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
},
|
|
2935
|
-
{
|
|
2936
|
-
headers: {
|
|
2937
|
-
"Authorization": `Bearer ${this.apiKey}`,
|
|
2938
|
-
"Content-Type": "application/json"
|
|
2939
|
-
}
|
|
2940
|
-
}
|
|
2941
|
-
);
|
|
2942
|
-
const embedding = Array.isArray(response.data) ? response.data : response.data[0];
|
|
2943
|
-
return {
|
|
2944
|
-
embedding,
|
|
2945
|
-
model: modelToUse,
|
|
2946
|
-
dimensions: embedding.length
|
|
2947
|
-
};
|
|
2948
|
-
} catch (error) {
|
|
2949
|
-
if (axios11__default.default.isAxiosError(error)) {
|
|
2950
|
-
const status = error.response?.status;
|
|
2951
|
-
const message = error.response?.data?.error || error.message;
|
|
2952
|
-
let messageText;
|
|
2953
|
-
if (status === 401) {
|
|
2954
|
-
messageText = `HuggingFace API authentication failed. Please check your HUGGINGFACE_API_KEY. ${message}`;
|
|
2955
|
-
} else if (status === 429) {
|
|
2956
|
-
messageText = `HuggingFace API rate limit exceeded. ${message}`;
|
|
2957
|
-
} else if (status === 400) {
|
|
2958
|
-
messageText = `HuggingFace API request invalid: ${message}`;
|
|
2959
|
-
} else if (status === 503) {
|
|
2960
|
-
messageText = `HuggingFace model is loading. Please retry in a moment. ${message}`;
|
|
2961
|
-
} else {
|
|
2962
|
-
messageText = `HuggingFace API error (${status}): ${message}`;
|
|
2963
|
-
}
|
|
2964
|
-
throw withProviderErrorMetadata(error, messageText);
|
|
2965
|
-
}
|
|
2966
|
-
throw error;
|
|
2967
|
-
}
|
|
2968
|
-
});
|
|
2983
|
+
const { data, model: modelToUse } = await this.requestEmbeddings(
|
|
2984
|
+
text,
|
|
2985
|
+
model
|
|
2986
|
+
);
|
|
2987
|
+
const embedding = Array.isArray(data) ? data : data[0];
|
|
2988
|
+
return {
|
|
2989
|
+
embedding,
|
|
2990
|
+
model: modelToUse,
|
|
2991
|
+
dimensions: embedding.length
|
|
2992
|
+
};
|
|
2969
2993
|
}
|
|
2970
2994
|
async generateBatchEmbeddings(texts, model) {
|
|
2995
|
+
const { data: embeddings, model: modelToUse } = await this.requestEmbeddings(
|
|
2996
|
+
texts,
|
|
2997
|
+
model
|
|
2998
|
+
);
|
|
2999
|
+
const dimensions = embeddings[0]?.length || 0;
|
|
3000
|
+
return {
|
|
3001
|
+
embeddings,
|
|
3002
|
+
model: modelToUse,
|
|
3003
|
+
dimensions
|
|
3004
|
+
};
|
|
3005
|
+
}
|
|
3006
|
+
async requestEmbeddings(inputs, model) {
|
|
2971
3007
|
const modelToUse = model || this.defaultModel;
|
|
2972
3008
|
return retryWithBackoff2(async () => {
|
|
2973
3009
|
try {
|
|
2974
|
-
const response = await
|
|
3010
|
+
const response = await axios5__default.default.post(
|
|
2975
3011
|
`${this.baseUrl}/${modelToUse}`,
|
|
2976
3012
|
{
|
|
2977
|
-
inputs
|
|
3013
|
+
inputs,
|
|
2978
3014
|
options: {
|
|
2979
3015
|
wait_for_model: true
|
|
2980
3016
|
}
|
|
2981
3017
|
},
|
|
2982
3018
|
{
|
|
2983
3019
|
headers: {
|
|
2984
|
-
|
|
3020
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
2985
3021
|
"Content-Type": "application/json"
|
|
2986
3022
|
}
|
|
2987
3023
|
}
|
|
2988
3024
|
);
|
|
2989
|
-
const embeddings = response.data;
|
|
2990
|
-
const dimensions = embeddings[0]?.length || 0;
|
|
2991
3025
|
return {
|
|
2992
|
-
|
|
2993
|
-
model: modelToUse
|
|
2994
|
-
dimensions
|
|
3026
|
+
data: response.data,
|
|
3027
|
+
model: modelToUse
|
|
2995
3028
|
};
|
|
2996
3029
|
} catch (error) {
|
|
2997
|
-
if (
|
|
3030
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
2998
3031
|
const status = error.response?.status;
|
|
2999
3032
|
const message = error.response?.data?.error || error.message;
|
|
3000
3033
|
let messageText;
|
|
@@ -3043,7 +3076,7 @@ var VoyageEmbeddingProvider = class {
|
|
|
3043
3076
|
const modelToUse = model || this.defaultModel;
|
|
3044
3077
|
return retryWithBackoff2(async () => {
|
|
3045
3078
|
try {
|
|
3046
|
-
const response = await
|
|
3079
|
+
const response = await axios5__default.default.post(
|
|
3047
3080
|
`${this.baseUrl}/embeddings`,
|
|
3048
3081
|
{
|
|
3049
3082
|
input: texts,
|
|
@@ -3070,7 +3103,7 @@ var VoyageEmbeddingProvider = class {
|
|
|
3070
3103
|
} : void 0
|
|
3071
3104
|
};
|
|
3072
3105
|
} catch (error) {
|
|
3073
|
-
if (
|
|
3106
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
3074
3107
|
const status = error.response?.status;
|
|
3075
3108
|
const message = error.response?.data?.message || error.message;
|
|
3076
3109
|
let messageText;
|
|
@@ -3107,7 +3140,7 @@ var OllamaEmbeddingProvider = class {
|
|
|
3107
3140
|
const modelToUse = model || this.defaultModel;
|
|
3108
3141
|
return retryWithBackoff2(async () => {
|
|
3109
3142
|
try {
|
|
3110
|
-
const response = await
|
|
3143
|
+
const response = await axios5__default.default.post(
|
|
3111
3144
|
`${this.baseUrl}/api/embeddings`,
|
|
3112
3145
|
{
|
|
3113
3146
|
model: modelToUse,
|
|
@@ -3126,7 +3159,7 @@ var OllamaEmbeddingProvider = class {
|
|
|
3126
3159
|
dimensions: embedding.length
|
|
3127
3160
|
};
|
|
3128
3161
|
} catch (error) {
|
|
3129
|
-
if (
|
|
3162
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
3130
3163
|
const status = error.response?.status;
|
|
3131
3164
|
const message = error.response?.data?.error || error.message;
|
|
3132
3165
|
let messageText;
|
|
@@ -3519,6 +3552,16 @@ function formatResults(records) {
|
|
|
3519
3552
|
});
|
|
3520
3553
|
}
|
|
3521
3554
|
|
|
3555
|
+
// src/data/neo4j/tools/session-owner.ts
|
|
3556
|
+
async function withNeo4jSession(database, operation) {
|
|
3557
|
+
const session = neo4jPool.getSession(database);
|
|
3558
|
+
try {
|
|
3559
|
+
return await operation(session);
|
|
3560
|
+
} finally {
|
|
3561
|
+
await session.close();
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3522
3565
|
// src/data/neo4j/tools/neo4j-query.ts
|
|
3523
3566
|
var logger4 = core.createLogger("agentforge:tools:neo4j:query");
|
|
3524
3567
|
function createNeo4jQueryTool() {
|
|
@@ -3539,8 +3582,7 @@ function createNeo4jQueryTool() {
|
|
|
3539
3582
|
...input.database ? { database: input.database } : {}
|
|
3540
3583
|
});
|
|
3541
3584
|
try {
|
|
3542
|
-
|
|
3543
|
-
try {
|
|
3585
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3544
3586
|
const result = await session.run(input.cypher, input.parameters || {});
|
|
3545
3587
|
const formattedResults = formatResults(result.records);
|
|
3546
3588
|
const duration = Date.now() - startTime;
|
|
@@ -3569,9 +3611,7 @@ function createNeo4jQueryTool() {
|
|
|
3569
3611
|
}
|
|
3570
3612
|
}
|
|
3571
3613
|
};
|
|
3572
|
-
}
|
|
3573
|
-
await session.close();
|
|
3574
|
-
}
|
|
3614
|
+
});
|
|
3575
3615
|
} catch (error) {
|
|
3576
3616
|
const duration = Date.now() - startTime;
|
|
3577
3617
|
const errorMessage = error instanceof Error ? error.message : "Failed to execute query";
|
|
@@ -3599,8 +3639,7 @@ function createNeo4jGetSchemaTool() {
|
|
|
3599
3639
|
};
|
|
3600
3640
|
}
|
|
3601
3641
|
try {
|
|
3602
|
-
|
|
3603
|
-
try {
|
|
3642
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3604
3643
|
const labelsResult = await session.run("CALL db.labels()");
|
|
3605
3644
|
const nodeLabels = labelsResult.records.map((r) => r.get("label"));
|
|
3606
3645
|
const relTypesResult = await session.run("CALL db.relationshipTypes()");
|
|
@@ -3640,9 +3679,7 @@ function createNeo4jGetSchemaTool() {
|
|
|
3640
3679
|
totalIndexes: indexes.length
|
|
3641
3680
|
}
|
|
3642
3681
|
};
|
|
3643
|
-
}
|
|
3644
|
-
await session.close();
|
|
3645
|
-
}
|
|
3682
|
+
});
|
|
3646
3683
|
} catch (error) {
|
|
3647
3684
|
return {
|
|
3648
3685
|
success: false,
|
|
@@ -3721,8 +3758,7 @@ function createNeo4jFindNodesTool() {
|
|
|
3721
3758
|
}
|
|
3722
3759
|
try {
|
|
3723
3760
|
const safeLabel = validateLabel(input.label);
|
|
3724
|
-
|
|
3725
|
-
try {
|
|
3761
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3726
3762
|
let cypher = `MATCH (n:${safeLabel})`;
|
|
3727
3763
|
let parameters = {};
|
|
3728
3764
|
if (input.properties && Object.keys(input.properties).length > 0) {
|
|
@@ -3744,9 +3780,7 @@ function createNeo4jFindNodesTool() {
|
|
|
3744
3780
|
limit: input.limit
|
|
3745
3781
|
}
|
|
3746
3782
|
};
|
|
3747
|
-
}
|
|
3748
|
-
await session.close();
|
|
3749
|
-
}
|
|
3783
|
+
});
|
|
3750
3784
|
} catch (error) {
|
|
3751
3785
|
return {
|
|
3752
3786
|
success: false,
|
|
@@ -3772,8 +3806,7 @@ function createNeo4jTraverseTool() {
|
|
|
3772
3806
|
try {
|
|
3773
3807
|
const safeDirection = validateDirection(input.direction || "outgoing");
|
|
3774
3808
|
const safeRelType = input.relationshipType ? validateRelationshipType(input.relationshipType) : null;
|
|
3775
|
-
|
|
3776
|
-
try {
|
|
3809
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3777
3810
|
let relPattern = "";
|
|
3778
3811
|
if (safeDirection === "OUTGOING") {
|
|
3779
3812
|
relPattern = safeRelType ? `-[r:${safeRelType}*1..${input.maxDepth}]->` : `-[r*1..${input.maxDepth}]->`;
|
|
@@ -3810,9 +3843,7 @@ function createNeo4jTraverseTool() {
|
|
|
3810
3843
|
maxDepth: input.maxDepth
|
|
3811
3844
|
}
|
|
3812
3845
|
};
|
|
3813
|
-
}
|
|
3814
|
-
await session.close();
|
|
3815
|
-
}
|
|
3846
|
+
});
|
|
3816
3847
|
} catch (error) {
|
|
3817
3848
|
return {
|
|
3818
3849
|
success: false,
|
|
@@ -3837,8 +3868,7 @@ function createNeo4jVectorSearchTool() {
|
|
|
3837
3868
|
};
|
|
3838
3869
|
}
|
|
3839
3870
|
try {
|
|
3840
|
-
|
|
3841
|
-
try {
|
|
3871
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3842
3872
|
const cypher = `
|
|
3843
3873
|
CALL db.index.vector.queryNodes($indexName, $limit, $queryVector)
|
|
3844
3874
|
YIELD node, score
|
|
@@ -3865,9 +3895,7 @@ function createNeo4jVectorSearchTool() {
|
|
|
3865
3895
|
limit: input.limit
|
|
3866
3896
|
}
|
|
3867
3897
|
};
|
|
3868
|
-
}
|
|
3869
|
-
await session.close();
|
|
3870
|
-
}
|
|
3898
|
+
});
|
|
3871
3899
|
} catch (error) {
|
|
3872
3900
|
const errorMessage = error instanceof Error ? error.message : "Failed to perform vector search";
|
|
3873
3901
|
let helpText = "";
|
|
@@ -3913,8 +3941,7 @@ function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
|
3913
3941
|
});
|
|
3914
3942
|
try {
|
|
3915
3943
|
const embeddingResult = await embeddingManager.generateEmbedding(input.queryText, input.model);
|
|
3916
|
-
|
|
3917
|
-
try {
|
|
3944
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3918
3945
|
const cypher = `
|
|
3919
3946
|
CALL db.index.vector.queryNodes($indexName, $limit, $queryVector)
|
|
3920
3947
|
YIELD node, score
|
|
@@ -3956,9 +3983,7 @@ function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
|
3956
3983
|
usage: embeddingResult.usage
|
|
3957
3984
|
}
|
|
3958
3985
|
};
|
|
3959
|
-
}
|
|
3960
|
-
await session.close();
|
|
3961
|
-
}
|
|
3986
|
+
});
|
|
3962
3987
|
} catch (error) {
|
|
3963
3988
|
const duration = Date.now() - startTime;
|
|
3964
3989
|
const errorMessage = error instanceof Error ? error.message : "Failed to perform vector search with embedding";
|
|
@@ -4014,8 +4039,7 @@ function createNeo4jCreateNodeWithEmbeddingTool() {
|
|
|
4014
4039
|
const embeddingResult = await embeddingManager.generateEmbedding(textToEmbed, input.model);
|
|
4015
4040
|
const safeLabel = validateLabel(input.label);
|
|
4016
4041
|
const safeEmbeddingProp = validatePropertyKey(input.embeddingProperty || "embedding");
|
|
4017
|
-
|
|
4018
|
-
try {
|
|
4042
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
4019
4043
|
const allProperties = {
|
|
4020
4044
|
...input.properties
|
|
4021
4045
|
};
|
|
@@ -4049,9 +4073,7 @@ function createNeo4jCreateNodeWithEmbeddingTool() {
|
|
|
4049
4073
|
},
|
|
4050
4074
|
message: `Created node with label '${input.label}' and ${embeddingResult.dimensions}-dimensional embedding`
|
|
4051
4075
|
};
|
|
4052
|
-
}
|
|
4053
|
-
await session.close();
|
|
4054
|
-
}
|
|
4076
|
+
});
|
|
4055
4077
|
} catch (error) {
|
|
4056
4078
|
const errorMessage = error instanceof Error ? error.message : "Failed to create node with embedding";
|
|
4057
4079
|
let helpText = "";
|
|
@@ -7139,15 +7161,6 @@ function formatTableName(table) {
|
|
|
7139
7161
|
return table.schema ? `${table.schema}.${table.name}` : table.name;
|
|
7140
7162
|
}
|
|
7141
7163
|
|
|
7142
|
-
// src/data/relational/schema/type-mapper-normalization.ts
|
|
7143
|
-
function normaliseDbType(raw) {
|
|
7144
|
-
let type = raw.toLowerCase().trim();
|
|
7145
|
-
type = type.replace(/\[\]$/, "");
|
|
7146
|
-
type = type.replace(/\([\d,\s]+\)/, "");
|
|
7147
|
-
type = type.replace(/\s+unsigned$/, "");
|
|
7148
|
-
return type.trim();
|
|
7149
|
-
}
|
|
7150
|
-
|
|
7151
7164
|
// src/data/relational/schema/type-mapper-vendor-maps.ts
|
|
7152
7165
|
var POSTGRES_TYPE_MAP = {
|
|
7153
7166
|
smallint: "number",
|
|
@@ -7323,6 +7336,13 @@ function getVendorTypeMap(vendor) {
|
|
|
7323
7336
|
function usesStringPrecisionFallback(vendor, normalised) {
|
|
7324
7337
|
return (normalised === "bigint" || normalised === "int8" || normalised === "bigserial") && (vendor === "postgresql" || vendor === "mysql");
|
|
7325
7338
|
}
|
|
7339
|
+
function normaliseDbType(raw) {
|
|
7340
|
+
let type = raw.toLowerCase().trim();
|
|
7341
|
+
type = type.replace(/\[\]$/, "");
|
|
7342
|
+
type = type.replace(/\([\d,\s]+\)/, "");
|
|
7343
|
+
type = type.replace(/\s+unsigned$/, "");
|
|
7344
|
+
return type.trim();
|
|
7345
|
+
}
|
|
7326
7346
|
var logger14 = core.createLogger("agentforge:tools:data:relational:schema-diff");
|
|
7327
7347
|
function diffSchemas(before, after) {
|
|
7328
7348
|
const tableDiffs = [];
|
|
@@ -10338,49 +10358,57 @@ var fileSearchSchema = zod.z.object({
|
|
|
10338
10358
|
recursive: zod.z.boolean().default(true).describe("Search in subdirectories"),
|
|
10339
10359
|
caseSensitive: zod.z.boolean().default(false).describe("Case-sensitive pattern matching")
|
|
10340
10360
|
});
|
|
10361
|
+
async function* traverseDirectory(directory, recursive) {
|
|
10362
|
+
const entries = await fs.promises.readdir(directory, { withFileTypes: true });
|
|
10363
|
+
for (const entry of entries) {
|
|
10364
|
+
const fullPath = path__namespace.join(directory, entry.name);
|
|
10365
|
+
const isDirectory = entry.isDirectory();
|
|
10366
|
+
yield {
|
|
10367
|
+
name: entry.name,
|
|
10368
|
+
fullPath,
|
|
10369
|
+
isFile: entry.isFile(),
|
|
10370
|
+
isDirectory
|
|
10371
|
+
};
|
|
10372
|
+
if (recursive && isDirectory) {
|
|
10373
|
+
yield* traverseDirectory(fullPath, true);
|
|
10374
|
+
}
|
|
10375
|
+
}
|
|
10376
|
+
}
|
|
10377
|
+
|
|
10378
|
+
// src/file/directory/tools/directory-list.ts
|
|
10341
10379
|
function createDirectoryListTool(defaultRecursive = false, defaultIncludeDetails = false, policy = DEFAULT_FILE_SYSTEM_POLICY) {
|
|
10342
10380
|
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) => {
|
|
10343
10381
|
const safePath = await policy.resolvePath(input.path, "directory listing");
|
|
10344
10382
|
const includeDetails = input.includeDetails ?? defaultIncludeDetails;
|
|
10345
|
-
const
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
|
|
10349
|
-
|
|
10350
|
-
|
|
10351
|
-
|
|
10352
|
-
if (!entry.isDirectory() || !recursive2) {
|
|
10353
|
-
continue;
|
|
10354
|
-
}
|
|
10355
|
-
}
|
|
10356
|
-
if (includeDetails) {
|
|
10357
|
-
const stats = await fs.promises.lstat(fullPath);
|
|
10358
|
-
files2.push({
|
|
10359
|
-
name: entry.name,
|
|
10360
|
-
path: relativePath,
|
|
10361
|
-
fullPath,
|
|
10362
|
-
isFile: entry.isFile(),
|
|
10363
|
-
isDirectory: entry.isDirectory(),
|
|
10364
|
-
size: stats.size,
|
|
10365
|
-
modified: stats.mtime.toISOString()
|
|
10366
|
-
});
|
|
10367
|
-
} else {
|
|
10368
|
-
files2.push({
|
|
10369
|
-
name: entry.name,
|
|
10370
|
-
path: relativePath,
|
|
10371
|
-
isFile: entry.isFile(),
|
|
10372
|
-
isDirectory: entry.isDirectory()
|
|
10373
|
-
});
|
|
10374
|
-
}
|
|
10375
|
-
if (recursive2 && entry.isDirectory()) {
|
|
10376
|
-
const subFiles = await listFiles(fullPath, true);
|
|
10377
|
-
files2.push(...subFiles);
|
|
10383
|
+
const recursive = input.recursive ?? defaultRecursive;
|
|
10384
|
+
const files = [];
|
|
10385
|
+
for await (const entry of traverseDirectory(safePath, recursive)) {
|
|
10386
|
+
const relativePath = path__namespace.relative(safePath, entry.fullPath);
|
|
10387
|
+
if (input.extension && !entry.name.endsWith(input.extension)) {
|
|
10388
|
+
if (!entry.isDirectory || !recursive) {
|
|
10389
|
+
continue;
|
|
10378
10390
|
}
|
|
10379
10391
|
}
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10383
|
-
|
|
10392
|
+
if (includeDetails) {
|
|
10393
|
+
const stats = await fs.promises.lstat(entry.fullPath);
|
|
10394
|
+
files.push({
|
|
10395
|
+
name: entry.name,
|
|
10396
|
+
path: relativePath,
|
|
10397
|
+
fullPath: entry.fullPath,
|
|
10398
|
+
isFile: entry.isFile,
|
|
10399
|
+
isDirectory: entry.isDirectory,
|
|
10400
|
+
size: stats.size,
|
|
10401
|
+
modified: stats.mtime.toISOString()
|
|
10402
|
+
});
|
|
10403
|
+
} else {
|
|
10404
|
+
files.push({
|
|
10405
|
+
name: entry.name,
|
|
10406
|
+
path: relativePath,
|
|
10407
|
+
isFile: entry.isFile,
|
|
10408
|
+
isDirectory: entry.isDirectory
|
|
10409
|
+
});
|
|
10410
|
+
}
|
|
10411
|
+
}
|
|
10384
10412
|
const result = {
|
|
10385
10413
|
path: input.path,
|
|
10386
10414
|
files,
|
|
@@ -10416,24 +10444,14 @@ function createFileSearchTool(defaultRecursive = true, defaultCaseSensitive = fa
|
|
|
10416
10444
|
const recursive = input.recursive ?? defaultRecursive;
|
|
10417
10445
|
const caseSensitive = input.caseSensitive ?? defaultCaseSensitive;
|
|
10418
10446
|
const safeDirectory = await policy.resolvePath(input.directory, "file search");
|
|
10419
|
-
const
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
const fullPath = path__namespace.join(dir, entry.name);
|
|
10426
|
-
if (entry.isFile() && regex.test(entry.name)) {
|
|
10427
|
-
matches2.push(fullPath);
|
|
10428
|
-
}
|
|
10429
|
-
if (recursive && entry.isDirectory()) {
|
|
10430
|
-
const subMatches = await searchFiles(fullPath);
|
|
10431
|
-
matches2.push(...subMatches);
|
|
10432
|
-
}
|
|
10447
|
+
const regexPattern = input.pattern.replace(/\./g, "\\.").replace(/\*/g, ".*");
|
|
10448
|
+
const regex = new RegExp(`^${regexPattern}$`, caseSensitive ? "" : "i");
|
|
10449
|
+
const matches = [];
|
|
10450
|
+
for await (const entry of traverseDirectory(safeDirectory, recursive)) {
|
|
10451
|
+
if (entry.isFile && regex.test(entry.name)) {
|
|
10452
|
+
matches.push(entry.fullPath);
|
|
10433
10453
|
}
|
|
10434
|
-
|
|
10435
|
-
};
|
|
10436
|
-
const matches = await searchFiles(safeDirectory);
|
|
10454
|
+
}
|
|
10437
10455
|
return {
|
|
10438
10456
|
directory: input.directory,
|
|
10439
10457
|
pattern: input.pattern,
|
|
@@ -11395,11 +11413,11 @@ var AskHumanInputSchema = zod.z.object({
|
|
|
11395
11413
|
});
|
|
11396
11414
|
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
|
|
11397
11415
|
var logger19 = core.createLogger("agentforge:tools:agent:ask-human", { level: logLevel3 });
|
|
11398
|
-
function
|
|
11416
|
+
function isRecord4(value) {
|
|
11399
11417
|
return typeof value === "object" && value !== null;
|
|
11400
11418
|
}
|
|
11401
11419
|
function resolveInterrupt(module) {
|
|
11402
|
-
if (!
|
|
11420
|
+
if (!isRecord4(module)) {
|
|
11403
11421
|
return void 0;
|
|
11404
11422
|
}
|
|
11405
11423
|
const candidate = module.interrupt;
|