@agentforge/tools 0.18.4 → 0.18.5
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 +332 -272
- 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 +331 -271
- 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,
|
|
@@ -1244,38 +1244,91 @@ function createGetConfiguredAuth(apiKey, email, siteUrl) {
|
|
|
1244
1244
|
return { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, ATLASSIAN_SITE_URL };
|
|
1245
1245
|
};
|
|
1246
1246
|
}
|
|
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
1247
|
function getConfig() {
|
|
1255
1248
|
const ATLASSIAN_API_KEY = process.env.ATLASSIAN_API_KEY || "";
|
|
1256
1249
|
const ATLASSIAN_EMAIL = process.env.ATLASSIAN_EMAIL || "";
|
|
1257
1250
|
const ATLASSIAN_SITE_URL = (process.env.ATLASSIAN_SITE_URL || "").replace(/\/$/, "");
|
|
1258
1251
|
if (!ATLASSIAN_API_KEY || !ATLASSIAN_EMAIL || !ATLASSIAN_SITE_URL) {
|
|
1259
|
-
throw new Error(
|
|
1252
|
+
throw new Error(
|
|
1253
|
+
"Confluence credentials not configured. Set ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, and ATLASSIAN_SITE_URL in .env"
|
|
1254
|
+
);
|
|
1260
1255
|
}
|
|
1261
1256
|
return { ATLASSIAN_API_KEY, ATLASSIAN_EMAIL, ATLASSIAN_SITE_URL };
|
|
1262
1257
|
}
|
|
1263
|
-
function
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1258
|
+
function isRecord(value) {
|
|
1259
|
+
return typeof value === "object" && value !== null;
|
|
1260
|
+
}
|
|
1261
|
+
function describeError(error) {
|
|
1262
|
+
const errorRecord = isRecord(error) ? error : void 0;
|
|
1263
|
+
const response = isRecord(errorRecord?.response) ? errorRecord.response : void 0;
|
|
1264
|
+
const responseData = isRecord(response?.data) ? response.data : void 0;
|
|
1265
|
+
const providerMessage = typeof responseData?.message === "string" ? responseData.message : void 0;
|
|
1266
|
+
const errorMessage = typeof errorRecord?.message === "string" ? errorRecord.message : void 0;
|
|
1267
|
+
return {
|
|
1268
|
+
message: providerMessage || errorMessage,
|
|
1269
|
+
status: typeof response?.status === "number" ? response.status : void 0
|
|
1270
|
+
};
|
|
1267
1271
|
}
|
|
1268
|
-
function
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1272
|
+
function authenticatedConfig(auth2, config = {}) {
|
|
1273
|
+
const credentials = Buffer.from(`${auth2.ATLASSIAN_EMAIL}:${auth2.ATLASSIAN_API_KEY}`).toString(
|
|
1274
|
+
"base64"
|
|
1275
|
+
);
|
|
1276
|
+
return {
|
|
1277
|
+
...config,
|
|
1278
|
+
headers: {
|
|
1279
|
+
...config.headers,
|
|
1280
|
+
Authorization: `Basic ${credentials}`
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
function createConfluenceRequest(getAuth) {
|
|
1285
|
+
return {
|
|
1286
|
+
async get(path13, config = {}) {
|
|
1287
|
+
const auth2 = getAuth();
|
|
1288
|
+
const response = await axios5__default.default.get(
|
|
1289
|
+
`${auth2.ATLASSIAN_SITE_URL}${path13}`,
|
|
1290
|
+
authenticatedConfig(auth2, config)
|
|
1291
|
+
);
|
|
1292
|
+
return { data: response.data, siteUrl: auth2.ATLASSIAN_SITE_URL };
|
|
1293
|
+
},
|
|
1294
|
+
async post(path13, data, config = {}) {
|
|
1295
|
+
const auth2 = getAuth();
|
|
1296
|
+
const response = await axios5__default.default.post(
|
|
1297
|
+
`${auth2.ATLASSIAN_SITE_URL}${path13}`,
|
|
1298
|
+
data,
|
|
1299
|
+
authenticatedConfig(auth2, config)
|
|
1300
|
+
);
|
|
1301
|
+
return { data: response.data, siteUrl: auth2.ATLASSIAN_SITE_URL };
|
|
1302
|
+
},
|
|
1303
|
+
async put(path13, data, config = {}) {
|
|
1304
|
+
const auth2 = getAuth();
|
|
1305
|
+
const response = await axios5__default.default.put(
|
|
1306
|
+
`${auth2.ATLASSIAN_SITE_URL}${path13}`,
|
|
1307
|
+
data,
|
|
1308
|
+
authenticatedConfig(auth2, config)
|
|
1309
|
+
);
|
|
1310
|
+
return { data: response.data, siteUrl: auth2.ATLASSIAN_SITE_URL };
|
|
1311
|
+
},
|
|
1312
|
+
describeError
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1315
|
+
function createSearchConfluenceTool(request2, logger20) {
|
|
1316
|
+
return core.toolBuilder().name("search-confluence").description(
|
|
1317
|
+
"Search for pages in Confluence using keywords or CQL (Confluence Query Language). Returns matching pages with titles, IDs, and excerpts."
|
|
1318
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("search").tag("knowledge-base").usageNotes(
|
|
1319
|
+
"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."
|
|
1320
|
+
).suggests(["get-confluence-page"]).schema(
|
|
1321
|
+
zod.z.object({
|
|
1322
|
+
query: zod.z.string().describe(
|
|
1323
|
+
"Search query or CQL expression (e.g., 'payment processing' or 'space=BL3 AND title~payment')"
|
|
1324
|
+
),
|
|
1325
|
+
limit: zod.z.number().optional().describe("Maximum number of results to return (default: 10, max: 25)")
|
|
1326
|
+
})
|
|
1327
|
+
).implement(async ({ query, limit = 10 }) => {
|
|
1273
1328
|
logger20.info("search-confluence called", { query, limit });
|
|
1274
1329
|
try {
|
|
1275
|
-
const
|
|
1276
|
-
const response = await axios11__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/search`, {
|
|
1330
|
+
const response = await request2.get("/wiki/rest/api/content/search", {
|
|
1277
1331
|
headers: {
|
|
1278
|
-
Authorization: getAuthHeader2(),
|
|
1279
1332
|
Accept: "application/json"
|
|
1280
1333
|
},
|
|
1281
1334
|
params: {
|
|
@@ -1284,22 +1337,24 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1284
1337
|
expand: "space,version"
|
|
1285
1338
|
}
|
|
1286
1339
|
});
|
|
1287
|
-
const { ATLASSIAN_SITE_URL: siteUrl } = getAuth();
|
|
1288
1340
|
const results = response.data.results.map((page) => ({
|
|
1289
1341
|
id: page.id,
|
|
1290
1342
|
title: page.title,
|
|
1291
1343
|
type: page.type,
|
|
1292
1344
|
space: page.space?.name || "Unknown",
|
|
1293
1345
|
spaceKey: page.space?.key || "",
|
|
1294
|
-
url: `${siteUrl}/wiki${page._links.webui}`,
|
|
1346
|
+
url: `${response.siteUrl}/wiki${page._links.webui}`,
|
|
1295
1347
|
lastModified: page.version?.when || ""
|
|
1296
1348
|
}));
|
|
1297
1349
|
if (results.length === 0) {
|
|
1298
|
-
logger20.warn(
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1350
|
+
logger20.warn(
|
|
1351
|
+
"search-confluence returned NO RESULTS - this is a valid outcome, agent should not retry",
|
|
1352
|
+
{
|
|
1353
|
+
query,
|
|
1354
|
+
limit,
|
|
1355
|
+
totalSize: response.data.totalSize
|
|
1356
|
+
}
|
|
1357
|
+
);
|
|
1303
1358
|
} else {
|
|
1304
1359
|
logger20.info("search-confluence result", {
|
|
1305
1360
|
query,
|
|
@@ -1316,28 +1371,33 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1316
1371
|
results
|
|
1317
1372
|
});
|
|
1318
1373
|
} catch (error) {
|
|
1374
|
+
const description = request2.describeError(error);
|
|
1319
1375
|
logger20.error("search-confluence error", {
|
|
1320
1376
|
query,
|
|
1321
|
-
error:
|
|
1322
|
-
status:
|
|
1377
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1378
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1323
1379
|
});
|
|
1324
1380
|
return JSON.stringify({
|
|
1325
1381
|
success: false,
|
|
1326
|
-
error:
|
|
1382
|
+
error: description.message
|
|
1327
1383
|
});
|
|
1328
1384
|
}
|
|
1329
1385
|
}).build();
|
|
1330
1386
|
}
|
|
1331
|
-
function createGetConfluencePageTool(
|
|
1332
|
-
return core.toolBuilder().name("get-confluence-page").description(
|
|
1333
|
-
|
|
1334
|
-
|
|
1387
|
+
function createGetConfluencePageTool(request2, logger20) {
|
|
1388
|
+
return core.toolBuilder().name("get-confluence-page").description(
|
|
1389
|
+
"Get the full content of a specific Confluence page by its ID. Returns the page title, content (in storage format), space, and metadata."
|
|
1390
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("page").tag("content").usageNotes(
|
|
1391
|
+
"Use this after search-confluence to retrieve the full content of a specific page. The page ID can be found in search results."
|
|
1392
|
+
).requires(["search-confluence"]).schema(
|
|
1393
|
+
zod.z.object({
|
|
1394
|
+
page_id: zod.z.string().describe("The Confluence page ID (from search results)")
|
|
1395
|
+
})
|
|
1396
|
+
).implement(async ({ page_id }) => {
|
|
1335
1397
|
logger20.info("get-confluence-page called", { page_id });
|
|
1336
1398
|
try {
|
|
1337
|
-
const
|
|
1338
|
-
const response = await axios11__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`, {
|
|
1399
|
+
const response = await request2.get(`/wiki/rest/api/content/${page_id}`, {
|
|
1339
1400
|
headers: {
|
|
1340
|
-
Authorization: getAuthHeader2(),
|
|
1341
1401
|
Accept: "application/json"
|
|
1342
1402
|
},
|
|
1343
1403
|
params: {
|
|
@@ -1360,35 +1420,40 @@ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1360
1420
|
space: page.space?.name || "Unknown",
|
|
1361
1421
|
spaceKey: page.space?.key || "",
|
|
1362
1422
|
content: page.body?.storage?.value || "",
|
|
1363
|
-
url: `${
|
|
1423
|
+
url: `${response.siteUrl}/wiki${page._links.webui}`,
|
|
1364
1424
|
created: page.history?.createdDate || "",
|
|
1365
1425
|
lastModified: page.version?.when || "",
|
|
1366
1426
|
version: page.version?.number || 1
|
|
1367
1427
|
}
|
|
1368
1428
|
});
|
|
1369
1429
|
} catch (error) {
|
|
1430
|
+
const description = request2.describeError(error);
|
|
1370
1431
|
logger20.error("get-confluence-page error", {
|
|
1371
1432
|
page_id,
|
|
1372
|
-
error:
|
|
1373
|
-
status:
|
|
1433
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1434
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1374
1435
|
});
|
|
1375
1436
|
return JSON.stringify({
|
|
1376
1437
|
success: false,
|
|
1377
|
-
error:
|
|
1438
|
+
error: description.message
|
|
1378
1439
|
});
|
|
1379
1440
|
}
|
|
1380
1441
|
}).build();
|
|
1381
1442
|
}
|
|
1382
|
-
function createListConfluenceSpacesTool(
|
|
1383
|
-
return core.toolBuilder().name("list-confluence-spaces").description(
|
|
1384
|
-
|
|
1385
|
-
|
|
1443
|
+
function createListConfluenceSpacesTool(request2, logger20) {
|
|
1444
|
+
return core.toolBuilder().name("list-confluence-spaces").description(
|
|
1445
|
+
"List all available Confluence spaces. Returns space names, keys, types, and descriptions to help identify where to search for information."
|
|
1446
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("spaces").tag("list").usageNotes(
|
|
1447
|
+
"Use this first to discover available spaces before searching. Helps narrow down searches to specific areas (e.g., 'AI', 'BL3', 'Finance')."
|
|
1448
|
+
).follows(["search-confluence"]).schema(
|
|
1449
|
+
zod.z.object({
|
|
1450
|
+
limit: zod.z.number().optional().describe("Maximum number of spaces to return (default: 25)")
|
|
1451
|
+
})
|
|
1452
|
+
).implement(async ({ limit = 25 }) => {
|
|
1386
1453
|
logger20.info("list-confluence-spaces called", { limit });
|
|
1387
1454
|
try {
|
|
1388
|
-
const
|
|
1389
|
-
const response = await axios11__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/space`, {
|
|
1455
|
+
const response = await request2.get("/wiki/rest/api/space", {
|
|
1390
1456
|
headers: {
|
|
1391
|
-
Authorization: getAuthHeader2(),
|
|
1392
1457
|
Accept: "application/json"
|
|
1393
1458
|
},
|
|
1394
1459
|
params: {
|
|
@@ -1400,7 +1465,7 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1400
1465
|
name: space.name,
|
|
1401
1466
|
type: space.type,
|
|
1402
1467
|
description: space.description?.plain?.value || "",
|
|
1403
|
-
url: `${
|
|
1468
|
+
url: `${response.siteUrl}/wiki${space._links.webui}`
|
|
1404
1469
|
}));
|
|
1405
1470
|
logger20.info("list-confluence-spaces result", {
|
|
1406
1471
|
spaceCount: spaces.length,
|
|
@@ -1413,28 +1478,33 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1413
1478
|
spaces
|
|
1414
1479
|
});
|
|
1415
1480
|
} catch (error) {
|
|
1481
|
+
const description = request2.describeError(error);
|
|
1416
1482
|
logger20.error("list-confluence-spaces error", {
|
|
1417
|
-
error:
|
|
1418
|
-
status:
|
|
1483
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1484
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1419
1485
|
});
|
|
1420
1486
|
return JSON.stringify({
|
|
1421
1487
|
success: false,
|
|
1422
|
-
error:
|
|
1488
|
+
error: description.message
|
|
1423
1489
|
});
|
|
1424
1490
|
}
|
|
1425
1491
|
}).build();
|
|
1426
1492
|
}
|
|
1427
|
-
function createGetSpacePagesTool(
|
|
1428
|
-
return core.toolBuilder().name("get-space-pages").description(
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1493
|
+
function createGetSpacePagesTool(request2, logger20) {
|
|
1494
|
+
return core.toolBuilder().name("get-space-pages").description(
|
|
1495
|
+
"Get all pages from a specific Confluence space by space key. Useful for browsing content in a particular area."
|
|
1496
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("space").tag("pages").usageNotes(
|
|
1497
|
+
"Use this to explore all pages in a specific space. Get the space key from list-confluence-spaces first."
|
|
1498
|
+
).requires(["list-confluence-spaces"]).schema(
|
|
1499
|
+
zod.z.object({
|
|
1500
|
+
space_key: zod.z.string().describe("The space key (e.g., 'AI', 'BL3', 'FIN')"),
|
|
1501
|
+
limit: zod.z.number().optional().describe("Maximum number of pages to return (default: 25)")
|
|
1502
|
+
})
|
|
1503
|
+
).implement(async ({ space_key, limit = 25 }) => {
|
|
1432
1504
|
logger20.info("get-space-pages called", { space_key, limit });
|
|
1433
1505
|
try {
|
|
1434
|
-
const
|
|
1435
|
-
const response = await axios11__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content`, {
|
|
1506
|
+
const response = await request2.get("/wiki/rest/api/content", {
|
|
1436
1507
|
headers: {
|
|
1437
|
-
Authorization: getAuthHeader2(),
|
|
1438
1508
|
Accept: "application/json"
|
|
1439
1509
|
},
|
|
1440
1510
|
params: {
|
|
@@ -1447,14 +1517,17 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1447
1517
|
const pages = response.data.results.map((page) => ({
|
|
1448
1518
|
id: page.id,
|
|
1449
1519
|
title: page.title,
|
|
1450
|
-
url: `${
|
|
1520
|
+
url: `${response.siteUrl}/wiki${page._links.webui}`,
|
|
1451
1521
|
lastModified: page.version?.when || ""
|
|
1452
1522
|
}));
|
|
1453
1523
|
if (pages.length === 0) {
|
|
1454
|
-
logger20.warn(
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1524
|
+
logger20.warn(
|
|
1525
|
+
"get-space-pages returned NO PAGES - this is a valid outcome, agent should not retry",
|
|
1526
|
+
{
|
|
1527
|
+
space_key,
|
|
1528
|
+
limit
|
|
1529
|
+
}
|
|
1530
|
+
);
|
|
1458
1531
|
} else {
|
|
1459
1532
|
logger20.info("get-space-pages result", {
|
|
1460
1533
|
space_key,
|
|
@@ -1470,28 +1543,38 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1470
1543
|
pages
|
|
1471
1544
|
});
|
|
1472
1545
|
} catch (error) {
|
|
1546
|
+
const description = request2.describeError(error);
|
|
1473
1547
|
logger20.error("get-space-pages error", {
|
|
1474
1548
|
space_key,
|
|
1475
|
-
error:
|
|
1476
|
-
status:
|
|
1549
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1550
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1477
1551
|
});
|
|
1478
1552
|
return JSON.stringify({
|
|
1479
1553
|
success: false,
|
|
1480
|
-
error:
|
|
1554
|
+
error: description.message
|
|
1481
1555
|
});
|
|
1482
1556
|
}
|
|
1483
1557
|
}).build();
|
|
1484
1558
|
}
|
|
1485
|
-
function createCreateConfluencePageTool(
|
|
1486
|
-
return core.toolBuilder().name("create-confluence-page").description(
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1559
|
+
function createCreateConfluencePageTool(request2, logger20) {
|
|
1560
|
+
return core.toolBuilder().name("create-confluence-page").description(
|
|
1561
|
+
"Create a new page in a Confluence space. Requires space key, page title, and content (in HTML storage format)."
|
|
1562
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("create").tag("write").usageNotes(
|
|
1563
|
+
"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."
|
|
1564
|
+
).requires(["list-confluence-spaces"]).schema(
|
|
1565
|
+
zod.z.object({
|
|
1566
|
+
space_key: zod.z.string().describe("The space key where the page will be created (e.g., 'AI', 'BL3')"),
|
|
1567
|
+
title: zod.z.string().describe("The title of the new page"),
|
|
1568
|
+
content: zod.z.string().describe("The page content in HTML format (Confluence storage format)"),
|
|
1569
|
+
parent_page_id: zod.z.string().optional().describe("Optional parent page ID to create this as a child page")
|
|
1570
|
+
})
|
|
1571
|
+
).implement(async ({ space_key, title, content, parent_page_id }) => {
|
|
1572
|
+
logger20.info("create-confluence-page called", {
|
|
1573
|
+
space_key,
|
|
1574
|
+
title,
|
|
1575
|
+
hasParent: !!parent_page_id
|
|
1576
|
+
});
|
|
1493
1577
|
try {
|
|
1494
|
-
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1495
1578
|
const pageData = {
|
|
1496
1579
|
type: "page",
|
|
1497
1580
|
title,
|
|
@@ -1506,16 +1589,11 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1506
1589
|
if (parent_page_id) {
|
|
1507
1590
|
pageData.ancestors = [{ id: parent_page_id }];
|
|
1508
1591
|
}
|
|
1509
|
-
const response = await
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
{
|
|
1513
|
-
headers: {
|
|
1514
|
-
Authorization: getAuthHeader2(),
|
|
1515
|
-
"Content-Type": "application/json"
|
|
1516
|
-
}
|
|
1592
|
+
const response = await request2.post("/wiki/rest/api/content", pageData, {
|
|
1593
|
+
headers: {
|
|
1594
|
+
"Content-Type": "application/json"
|
|
1517
1595
|
}
|
|
1518
|
-
);
|
|
1596
|
+
});
|
|
1519
1597
|
logger20.info("create-confluence-page result", {
|
|
1520
1598
|
page_id: response.data.id,
|
|
1521
1599
|
title: response.data.title,
|
|
@@ -1527,45 +1605,45 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1527
1605
|
id: response.data.id,
|
|
1528
1606
|
title: response.data.title,
|
|
1529
1607
|
space: space_key,
|
|
1530
|
-
url: `${
|
|
1608
|
+
url: `${response.siteUrl}/wiki${response.data._links.webui}`,
|
|
1531
1609
|
version: response.data.version?.number || 1
|
|
1532
1610
|
}
|
|
1533
1611
|
});
|
|
1534
1612
|
} catch (error) {
|
|
1613
|
+
const description = request2.describeError(error);
|
|
1535
1614
|
logger20.error("create-confluence-page error", {
|
|
1536
1615
|
space_key,
|
|
1537
1616
|
title,
|
|
1538
|
-
error:
|
|
1539
|
-
status:
|
|
1617
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1618
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1540
1619
|
});
|
|
1541
1620
|
return JSON.stringify({
|
|
1542
1621
|
success: false,
|
|
1543
|
-
error:
|
|
1622
|
+
error: description.message
|
|
1544
1623
|
});
|
|
1545
1624
|
}
|
|
1546
1625
|
}).build();
|
|
1547
1626
|
}
|
|
1548
|
-
function createUpdateConfluencePageTool(
|
|
1549
|
-
return core.toolBuilder().name("update-confluence-page").description(
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1627
|
+
function createUpdateConfluencePageTool(request2, logger20) {
|
|
1628
|
+
return core.toolBuilder().name("update-confluence-page").description(
|
|
1629
|
+
"Update an existing Confluence page's content. Requires page ID, new title, and new content."
|
|
1630
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("update").tag("write").usageNotes(
|
|
1631
|
+
"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."
|
|
1632
|
+
).requires(["get-confluence-page"]).schema(
|
|
1633
|
+
zod.z.object({
|
|
1634
|
+
page_id: zod.z.string().describe("The ID of the page to update"),
|
|
1635
|
+
title: zod.z.string().describe("The new title for the page"),
|
|
1636
|
+
content: zod.z.string().describe("The new content in HTML format (Confluence storage format)")
|
|
1637
|
+
})
|
|
1638
|
+
).implement(async ({ page_id, title, content }) => {
|
|
1554
1639
|
logger20.info("update-confluence-page called", { page_id, title });
|
|
1555
1640
|
try {
|
|
1556
|
-
const
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
{
|
|
1560
|
-
headers: {
|
|
1561
|
-
Authorization: getAuthHeader2()
|
|
1562
|
-
},
|
|
1563
|
-
params: { expand: "version" }
|
|
1564
|
-
}
|
|
1565
|
-
);
|
|
1641
|
+
const getResponse = await request2.get(`/wiki/rest/api/content/${page_id}`, {
|
|
1642
|
+
params: { expand: "version" }
|
|
1643
|
+
});
|
|
1566
1644
|
const currentVersion = getResponse.data.version.number;
|
|
1567
|
-
const updateResponse = await
|
|
1568
|
-
|
|
1645
|
+
const updateResponse = await request2.put(
|
|
1646
|
+
`/wiki/rest/api/content/${page_id}`,
|
|
1569
1647
|
{
|
|
1570
1648
|
type: "page",
|
|
1571
1649
|
title,
|
|
@@ -1579,7 +1657,6 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1579
1657
|
},
|
|
1580
1658
|
{
|
|
1581
1659
|
headers: {
|
|
1582
|
-
Authorization: getAuthHeader2(),
|
|
1583
1660
|
"Content-Type": "application/json"
|
|
1584
1661
|
}
|
|
1585
1662
|
}
|
|
@@ -1595,49 +1672,49 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1595
1672
|
page: {
|
|
1596
1673
|
id: updateResponse.data.id,
|
|
1597
1674
|
title: updateResponse.data.title,
|
|
1598
|
-
url: `${
|
|
1675
|
+
url: `${updateResponse.siteUrl}/wiki${updateResponse.data._links.webui}`,
|
|
1599
1676
|
version: updateResponse.data.version.number,
|
|
1600
1677
|
previousVersion: currentVersion
|
|
1601
1678
|
}
|
|
1602
1679
|
});
|
|
1603
1680
|
} catch (error) {
|
|
1681
|
+
const description = request2.describeError(error);
|
|
1604
1682
|
logger20.error("update-confluence-page error", {
|
|
1605
1683
|
page_id,
|
|
1606
1684
|
title,
|
|
1607
|
-
error:
|
|
1608
|
-
status:
|
|
1685
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1686
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1609
1687
|
});
|
|
1610
1688
|
return JSON.stringify({
|
|
1611
1689
|
success: false,
|
|
1612
|
-
error:
|
|
1690
|
+
error: description.message
|
|
1613
1691
|
});
|
|
1614
1692
|
}
|
|
1615
1693
|
}).build();
|
|
1616
1694
|
}
|
|
1617
|
-
function createArchiveConfluencePageTool(
|
|
1618
|
-
return core.toolBuilder().name("archive-confluence-page").description(
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1695
|
+
function createArchiveConfluencePageTool(request2, logger20) {
|
|
1696
|
+
return core.toolBuilder().name("archive-confluence-page").description(
|
|
1697
|
+
"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."
|
|
1698
|
+
).category(core.ToolCategory.WEB).tag("confluence").tag("archive").tag("delete").usageNotes(
|
|
1699
|
+
"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."
|
|
1700
|
+
).conflicts(["create-confluence-page"]).schema(
|
|
1701
|
+
zod.z.object({
|
|
1702
|
+
page_id: zod.z.string().describe("The ID of the page to archive"),
|
|
1703
|
+
reason: zod.z.string().optional().describe("Optional reason for archiving (for audit trail)")
|
|
1704
|
+
})
|
|
1705
|
+
).implement(async ({ page_id, reason }) => {
|
|
1622
1706
|
logger20.info("archive-confluence-page called", {
|
|
1623
1707
|
page_id,
|
|
1624
1708
|
...reason ? { reason } : {}
|
|
1625
1709
|
});
|
|
1626
1710
|
try {
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
{
|
|
1631
|
-
headers: {
|
|
1632
|
-
Authorization: getAuthHeader2()
|
|
1633
|
-
},
|
|
1634
|
-
params: { expand: "version,body.storage,space" }
|
|
1635
|
-
}
|
|
1636
|
-
);
|
|
1711
|
+
const getResponse = await request2.get(`/wiki/rest/api/content/${page_id}`, {
|
|
1712
|
+
params: { expand: "version,body.storage,space" }
|
|
1713
|
+
});
|
|
1637
1714
|
const currentVersion = getResponse.data.version.number;
|
|
1638
1715
|
const pageData = getResponse.data;
|
|
1639
|
-
await
|
|
1640
|
-
|
|
1716
|
+
await request2.put(
|
|
1717
|
+
`/wiki/rest/api/content/${page_id}`,
|
|
1641
1718
|
{
|
|
1642
1719
|
version: { number: currentVersion + 1 },
|
|
1643
1720
|
title: pageData.title,
|
|
@@ -1648,7 +1725,6 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1648
1725
|
},
|
|
1649
1726
|
{
|
|
1650
1727
|
headers: {
|
|
1651
|
-
Authorization: getAuthHeader2(),
|
|
1652
1728
|
"Content-Type": "application/json"
|
|
1653
1729
|
}
|
|
1654
1730
|
}
|
|
@@ -1671,14 +1747,15 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1671
1747
|
}
|
|
1672
1748
|
});
|
|
1673
1749
|
} catch (error) {
|
|
1750
|
+
const description = request2.describeError(error);
|
|
1674
1751
|
logger20.error("archive-confluence-page error", {
|
|
1675
1752
|
page_id,
|
|
1676
|
-
error:
|
|
1677
|
-
status:
|
|
1753
|
+
...description.message !== void 0 ? { error: description.message } : {},
|
|
1754
|
+
...description.status !== void 0 ? { status: description.status } : {}
|
|
1678
1755
|
});
|
|
1679
1756
|
return JSON.stringify({
|
|
1680
1757
|
success: false,
|
|
1681
|
-
error:
|
|
1758
|
+
error: description.message
|
|
1682
1759
|
});
|
|
1683
1760
|
}
|
|
1684
1761
|
}).build();
|
|
@@ -1687,13 +1764,14 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger20) {
|
|
|
1687
1764
|
// src/web/confluence/index.ts
|
|
1688
1765
|
var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
|
|
1689
1766
|
var logger2 = core.createLogger("[tools:confluence]", { level: logLevel2 });
|
|
1690
|
-
var
|
|
1691
|
-
var
|
|
1692
|
-
var
|
|
1693
|
-
var
|
|
1694
|
-
var
|
|
1695
|
-
var
|
|
1696
|
-
var
|
|
1767
|
+
var request = createConfluenceRequest(getConfig);
|
|
1768
|
+
var searchConfluence = createSearchConfluenceTool(request, logger2);
|
|
1769
|
+
var getConfluencePage = createGetConfluencePageTool(request, logger2);
|
|
1770
|
+
var listConfluenceSpaces = createListConfluenceSpacesTool(request, logger2);
|
|
1771
|
+
var getSpacePages = createGetSpacePagesTool(request, logger2);
|
|
1772
|
+
var createConfluencePage = createCreateConfluencePageTool(request, logger2);
|
|
1773
|
+
var updateConfluencePage = createUpdateConfluencePageTool(request, logger2);
|
|
1774
|
+
var archiveConfluencePage = createArchiveConfluencePageTool(request, logger2);
|
|
1697
1775
|
var confluenceTools = [
|
|
1698
1776
|
// Read tools
|
|
1699
1777
|
searchConfluence,
|
|
@@ -1706,22 +1784,17 @@ var confluenceTools = [
|
|
|
1706
1784
|
archiveConfluencePage
|
|
1707
1785
|
];
|
|
1708
1786
|
function createConfluenceTools(config = {}) {
|
|
1709
|
-
const {
|
|
1710
|
-
apiKey,
|
|
1711
|
-
email,
|
|
1712
|
-
siteUrl,
|
|
1713
|
-
logLevel: customLogLevel
|
|
1714
|
-
} = config;
|
|
1787
|
+
const { apiKey, email, siteUrl, logLevel: customLogLevel } = config;
|
|
1715
1788
|
const getConfiguredAuth = createGetConfiguredAuth(apiKey, email, siteUrl);
|
|
1716
|
-
const
|
|
1789
|
+
const request2 = createConfluenceRequest(getConfiguredAuth);
|
|
1717
1790
|
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(
|
|
1791
|
+
const searchConfluence2 = createSearchConfluenceTool(request2, toolLogger);
|
|
1792
|
+
const getConfluencePage2 = createGetConfluencePageTool(request2, toolLogger);
|
|
1793
|
+
const listConfluenceSpaces2 = createListConfluenceSpacesTool(request2, toolLogger);
|
|
1794
|
+
const getSpacePages2 = createGetSpacePagesTool(request2, toolLogger);
|
|
1795
|
+
const createConfluencePage2 = createCreateConfluencePageTool(request2, toolLogger);
|
|
1796
|
+
const updateConfluencePage2 = createUpdateConfluencePageTool(request2, toolLogger);
|
|
1797
|
+
const archiveConfluencePage2 = createArchiveConfluencePageTool(request2, toolLogger);
|
|
1725
1798
|
return {
|
|
1726
1799
|
searchConfluence: searchConfluence2,
|
|
1727
1800
|
getConfluencePage: getConfluencePage2,
|
|
@@ -1912,14 +1985,14 @@ function createJsonStringifyTool(defaultIndent = 2, defaultPretty = false) {
|
|
|
1912
1985
|
};
|
|
1913
1986
|
}).build();
|
|
1914
1987
|
}
|
|
1915
|
-
function
|
|
1988
|
+
function isRecord2(value) {
|
|
1916
1989
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1917
1990
|
}
|
|
1918
1991
|
function getPathValue(current, part) {
|
|
1919
1992
|
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
|
|
1920
1993
|
if (arrayMatch) {
|
|
1921
1994
|
const [, key, index] = arrayMatch;
|
|
1922
|
-
if (!
|
|
1995
|
+
if (!isRecord2(current)) {
|
|
1923
1996
|
return void 0;
|
|
1924
1997
|
}
|
|
1925
1998
|
const candidate = current[key];
|
|
@@ -1928,7 +2001,7 @@ function getPathValue(current, part) {
|
|
|
1928
2001
|
}
|
|
1929
2002
|
return candidate[parseInt(index, 10)];
|
|
1930
2003
|
}
|
|
1931
|
-
if (!
|
|
2004
|
+
if (!isRecord2(current)) {
|
|
1932
2005
|
return void 0;
|
|
1933
2006
|
}
|
|
1934
2007
|
return current[part];
|
|
@@ -2584,7 +2657,7 @@ async function initializeFromEnv() {
|
|
|
2584
2657
|
// src/data/neo4j/embeddings/utils.ts
|
|
2585
2658
|
function withProviderErrorMetadata(error, message) {
|
|
2586
2659
|
const wrappedError = new Error(message);
|
|
2587
|
-
if (!
|
|
2660
|
+
if (!isRecord3(error)) return wrappedError;
|
|
2588
2661
|
if (typeof error.code === "string") wrappedError.code = error.code;
|
|
2589
2662
|
if (error.response !== void 0) wrappedError.response = error.response;
|
|
2590
2663
|
return wrappedError;
|
|
@@ -2597,12 +2670,12 @@ var DEFAULT_RETRY_CONFIG2 = {
|
|
|
2597
2670
|
// 10 seconds
|
|
2598
2671
|
backoffMultiplier: 2
|
|
2599
2672
|
};
|
|
2600
|
-
function
|
|
2673
|
+
function isRecord3(value) {
|
|
2601
2674
|
return typeof value === "object" && value !== null;
|
|
2602
2675
|
}
|
|
2603
2676
|
function isRetryableError2(error) {
|
|
2604
|
-
if (!
|
|
2605
|
-
const response =
|
|
2677
|
+
if (!isRecord3(error)) return false;
|
|
2678
|
+
const response = isRecord3(error.response) ? error.response : void 0;
|
|
2606
2679
|
const status = typeof response?.status === "number" ? response.status : void 0;
|
|
2607
2680
|
const code = typeof error.code === "string" ? error.code : void 0;
|
|
2608
2681
|
const message = typeof error.message === "string" ? error.message : void 0;
|
|
@@ -2728,7 +2801,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2728
2801
|
const modelToUse = model || this.defaultModel;
|
|
2729
2802
|
return retryWithBackoff2(async () => {
|
|
2730
2803
|
try {
|
|
2731
|
-
const response = await
|
|
2804
|
+
const response = await axios5__default.default.post(
|
|
2732
2805
|
`${this.baseURL}/embeddings`,
|
|
2733
2806
|
{
|
|
2734
2807
|
input: text,
|
|
@@ -2758,7 +2831,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2758
2831
|
};
|
|
2759
2832
|
} catch (error) {
|
|
2760
2833
|
let message;
|
|
2761
|
-
const response =
|
|
2834
|
+
const response = axios5__default.default.isAxiosError(error) ? error.response : void 0;
|
|
2762
2835
|
if (response?.status === 401) {
|
|
2763
2836
|
message = "Invalid OpenAI API key. Get your key at https://platform.openai.com/api-keys";
|
|
2764
2837
|
} else if (response?.status === 429) {
|
|
@@ -2785,7 +2858,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2785
2858
|
const modelToUse = model || this.defaultModel;
|
|
2786
2859
|
return retryWithBackoff2(async () => {
|
|
2787
2860
|
try {
|
|
2788
|
-
const response = await
|
|
2861
|
+
const response = await axios5__default.default.post(
|
|
2789
2862
|
`${this.baseURL}/embeddings`,
|
|
2790
2863
|
{
|
|
2791
2864
|
input: texts,
|
|
@@ -2816,7 +2889,7 @@ var OpenAIEmbeddingProvider = class {
|
|
|
2816
2889
|
};
|
|
2817
2890
|
} catch (error) {
|
|
2818
2891
|
let message;
|
|
2819
|
-
const response =
|
|
2892
|
+
const response = axios5__default.default.isAxiosError(error) ? error.response : void 0;
|
|
2820
2893
|
if (response?.status === 401) {
|
|
2821
2894
|
message = "Invalid OpenAI API key. Get your key at https://platform.openai.com/api-keys";
|
|
2822
2895
|
} else if (response?.status === 429) {
|
|
@@ -2858,7 +2931,7 @@ var CohereEmbeddingProvider = class {
|
|
|
2858
2931
|
const modelToUse = model || this.defaultModel;
|
|
2859
2932
|
return retryWithBackoff2(async () => {
|
|
2860
2933
|
try {
|
|
2861
|
-
const response = await
|
|
2934
|
+
const response = await axios5__default.default.post(
|
|
2862
2935
|
`${this.baseUrl}/embed`,
|
|
2863
2936
|
{
|
|
2864
2937
|
texts,
|
|
@@ -2886,7 +2959,7 @@ var CohereEmbeddingProvider = class {
|
|
|
2886
2959
|
} : void 0
|
|
2887
2960
|
};
|
|
2888
2961
|
} catch (error) {
|
|
2889
|
-
if (
|
|
2962
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
2890
2963
|
const status = error.response?.status;
|
|
2891
2964
|
const providerMessage = error.response?.data?.message || error.message;
|
|
2892
2965
|
let message;
|
|
@@ -2924,7 +2997,7 @@ var HuggingFaceEmbeddingProvider = class {
|
|
|
2924
2997
|
const modelToUse = model || this.defaultModel;
|
|
2925
2998
|
return retryWithBackoff2(async () => {
|
|
2926
2999
|
try {
|
|
2927
|
-
const response = await
|
|
3000
|
+
const response = await axios5__default.default.post(
|
|
2928
3001
|
`${this.baseUrl}/${modelToUse}`,
|
|
2929
3002
|
{
|
|
2930
3003
|
inputs: text,
|
|
@@ -2946,7 +3019,7 @@ var HuggingFaceEmbeddingProvider = class {
|
|
|
2946
3019
|
dimensions: embedding.length
|
|
2947
3020
|
};
|
|
2948
3021
|
} catch (error) {
|
|
2949
|
-
if (
|
|
3022
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
2950
3023
|
const status = error.response?.status;
|
|
2951
3024
|
const message = error.response?.data?.error || error.message;
|
|
2952
3025
|
let messageText;
|
|
@@ -2971,7 +3044,7 @@ var HuggingFaceEmbeddingProvider = class {
|
|
|
2971
3044
|
const modelToUse = model || this.defaultModel;
|
|
2972
3045
|
return retryWithBackoff2(async () => {
|
|
2973
3046
|
try {
|
|
2974
|
-
const response = await
|
|
3047
|
+
const response = await axios5__default.default.post(
|
|
2975
3048
|
`${this.baseUrl}/${modelToUse}`,
|
|
2976
3049
|
{
|
|
2977
3050
|
inputs: texts,
|
|
@@ -2994,7 +3067,7 @@ var HuggingFaceEmbeddingProvider = class {
|
|
|
2994
3067
|
dimensions
|
|
2995
3068
|
};
|
|
2996
3069
|
} catch (error) {
|
|
2997
|
-
if (
|
|
3070
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
2998
3071
|
const status = error.response?.status;
|
|
2999
3072
|
const message = error.response?.data?.error || error.message;
|
|
3000
3073
|
let messageText;
|
|
@@ -3043,7 +3116,7 @@ var VoyageEmbeddingProvider = class {
|
|
|
3043
3116
|
const modelToUse = model || this.defaultModel;
|
|
3044
3117
|
return retryWithBackoff2(async () => {
|
|
3045
3118
|
try {
|
|
3046
|
-
const response = await
|
|
3119
|
+
const response = await axios5__default.default.post(
|
|
3047
3120
|
`${this.baseUrl}/embeddings`,
|
|
3048
3121
|
{
|
|
3049
3122
|
input: texts,
|
|
@@ -3070,7 +3143,7 @@ var VoyageEmbeddingProvider = class {
|
|
|
3070
3143
|
} : void 0
|
|
3071
3144
|
};
|
|
3072
3145
|
} catch (error) {
|
|
3073
|
-
if (
|
|
3146
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
3074
3147
|
const status = error.response?.status;
|
|
3075
3148
|
const message = error.response?.data?.message || error.message;
|
|
3076
3149
|
let messageText;
|
|
@@ -3107,7 +3180,7 @@ var OllamaEmbeddingProvider = class {
|
|
|
3107
3180
|
const modelToUse = model || this.defaultModel;
|
|
3108
3181
|
return retryWithBackoff2(async () => {
|
|
3109
3182
|
try {
|
|
3110
|
-
const response = await
|
|
3183
|
+
const response = await axios5__default.default.post(
|
|
3111
3184
|
`${this.baseUrl}/api/embeddings`,
|
|
3112
3185
|
{
|
|
3113
3186
|
model: modelToUse,
|
|
@@ -3126,7 +3199,7 @@ var OllamaEmbeddingProvider = class {
|
|
|
3126
3199
|
dimensions: embedding.length
|
|
3127
3200
|
};
|
|
3128
3201
|
} catch (error) {
|
|
3129
|
-
if (
|
|
3202
|
+
if (axios5__default.default.isAxiosError(error)) {
|
|
3130
3203
|
const status = error.response?.status;
|
|
3131
3204
|
const message = error.response?.data?.error || error.message;
|
|
3132
3205
|
let messageText;
|
|
@@ -3519,6 +3592,16 @@ function formatResults(records) {
|
|
|
3519
3592
|
});
|
|
3520
3593
|
}
|
|
3521
3594
|
|
|
3595
|
+
// src/data/neo4j/tools/session-owner.ts
|
|
3596
|
+
async function withNeo4jSession(database, operation) {
|
|
3597
|
+
const session = neo4jPool.getSession(database);
|
|
3598
|
+
try {
|
|
3599
|
+
return await operation(session);
|
|
3600
|
+
} finally {
|
|
3601
|
+
await session.close();
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
|
|
3522
3605
|
// src/data/neo4j/tools/neo4j-query.ts
|
|
3523
3606
|
var logger4 = core.createLogger("agentforge:tools:neo4j:query");
|
|
3524
3607
|
function createNeo4jQueryTool() {
|
|
@@ -3539,8 +3622,7 @@ function createNeo4jQueryTool() {
|
|
|
3539
3622
|
...input.database ? { database: input.database } : {}
|
|
3540
3623
|
});
|
|
3541
3624
|
try {
|
|
3542
|
-
|
|
3543
|
-
try {
|
|
3625
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3544
3626
|
const result = await session.run(input.cypher, input.parameters || {});
|
|
3545
3627
|
const formattedResults = formatResults(result.records);
|
|
3546
3628
|
const duration = Date.now() - startTime;
|
|
@@ -3569,9 +3651,7 @@ function createNeo4jQueryTool() {
|
|
|
3569
3651
|
}
|
|
3570
3652
|
}
|
|
3571
3653
|
};
|
|
3572
|
-
}
|
|
3573
|
-
await session.close();
|
|
3574
|
-
}
|
|
3654
|
+
});
|
|
3575
3655
|
} catch (error) {
|
|
3576
3656
|
const duration = Date.now() - startTime;
|
|
3577
3657
|
const errorMessage = error instanceof Error ? error.message : "Failed to execute query";
|
|
@@ -3599,8 +3679,7 @@ function createNeo4jGetSchemaTool() {
|
|
|
3599
3679
|
};
|
|
3600
3680
|
}
|
|
3601
3681
|
try {
|
|
3602
|
-
|
|
3603
|
-
try {
|
|
3682
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3604
3683
|
const labelsResult = await session.run("CALL db.labels()");
|
|
3605
3684
|
const nodeLabels = labelsResult.records.map((r) => r.get("label"));
|
|
3606
3685
|
const relTypesResult = await session.run("CALL db.relationshipTypes()");
|
|
@@ -3640,9 +3719,7 @@ function createNeo4jGetSchemaTool() {
|
|
|
3640
3719
|
totalIndexes: indexes.length
|
|
3641
3720
|
}
|
|
3642
3721
|
};
|
|
3643
|
-
}
|
|
3644
|
-
await session.close();
|
|
3645
|
-
}
|
|
3722
|
+
});
|
|
3646
3723
|
} catch (error) {
|
|
3647
3724
|
return {
|
|
3648
3725
|
success: false,
|
|
@@ -3721,8 +3798,7 @@ function createNeo4jFindNodesTool() {
|
|
|
3721
3798
|
}
|
|
3722
3799
|
try {
|
|
3723
3800
|
const safeLabel = validateLabel(input.label);
|
|
3724
|
-
|
|
3725
|
-
try {
|
|
3801
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3726
3802
|
let cypher = `MATCH (n:${safeLabel})`;
|
|
3727
3803
|
let parameters = {};
|
|
3728
3804
|
if (input.properties && Object.keys(input.properties).length > 0) {
|
|
@@ -3744,9 +3820,7 @@ function createNeo4jFindNodesTool() {
|
|
|
3744
3820
|
limit: input.limit
|
|
3745
3821
|
}
|
|
3746
3822
|
};
|
|
3747
|
-
}
|
|
3748
|
-
await session.close();
|
|
3749
|
-
}
|
|
3823
|
+
});
|
|
3750
3824
|
} catch (error) {
|
|
3751
3825
|
return {
|
|
3752
3826
|
success: false,
|
|
@@ -3772,8 +3846,7 @@ function createNeo4jTraverseTool() {
|
|
|
3772
3846
|
try {
|
|
3773
3847
|
const safeDirection = validateDirection(input.direction || "outgoing");
|
|
3774
3848
|
const safeRelType = input.relationshipType ? validateRelationshipType(input.relationshipType) : null;
|
|
3775
|
-
|
|
3776
|
-
try {
|
|
3849
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3777
3850
|
let relPattern = "";
|
|
3778
3851
|
if (safeDirection === "OUTGOING") {
|
|
3779
3852
|
relPattern = safeRelType ? `-[r:${safeRelType}*1..${input.maxDepth}]->` : `-[r*1..${input.maxDepth}]->`;
|
|
@@ -3810,9 +3883,7 @@ function createNeo4jTraverseTool() {
|
|
|
3810
3883
|
maxDepth: input.maxDepth
|
|
3811
3884
|
}
|
|
3812
3885
|
};
|
|
3813
|
-
}
|
|
3814
|
-
await session.close();
|
|
3815
|
-
}
|
|
3886
|
+
});
|
|
3816
3887
|
} catch (error) {
|
|
3817
3888
|
return {
|
|
3818
3889
|
success: false,
|
|
@@ -3837,8 +3908,7 @@ function createNeo4jVectorSearchTool() {
|
|
|
3837
3908
|
};
|
|
3838
3909
|
}
|
|
3839
3910
|
try {
|
|
3840
|
-
|
|
3841
|
-
try {
|
|
3911
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3842
3912
|
const cypher = `
|
|
3843
3913
|
CALL db.index.vector.queryNodes($indexName, $limit, $queryVector)
|
|
3844
3914
|
YIELD node, score
|
|
@@ -3865,9 +3935,7 @@ function createNeo4jVectorSearchTool() {
|
|
|
3865
3935
|
limit: input.limit
|
|
3866
3936
|
}
|
|
3867
3937
|
};
|
|
3868
|
-
}
|
|
3869
|
-
await session.close();
|
|
3870
|
-
}
|
|
3938
|
+
});
|
|
3871
3939
|
} catch (error) {
|
|
3872
3940
|
const errorMessage = error instanceof Error ? error.message : "Failed to perform vector search";
|
|
3873
3941
|
let helpText = "";
|
|
@@ -3913,8 +3981,7 @@ function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
|
3913
3981
|
});
|
|
3914
3982
|
try {
|
|
3915
3983
|
const embeddingResult = await embeddingManager.generateEmbedding(input.queryText, input.model);
|
|
3916
|
-
|
|
3917
|
-
try {
|
|
3984
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
3918
3985
|
const cypher = `
|
|
3919
3986
|
CALL db.index.vector.queryNodes($indexName, $limit, $queryVector)
|
|
3920
3987
|
YIELD node, score
|
|
@@ -3956,9 +4023,7 @@ function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
|
3956
4023
|
usage: embeddingResult.usage
|
|
3957
4024
|
}
|
|
3958
4025
|
};
|
|
3959
|
-
}
|
|
3960
|
-
await session.close();
|
|
3961
|
-
}
|
|
4026
|
+
});
|
|
3962
4027
|
} catch (error) {
|
|
3963
4028
|
const duration = Date.now() - startTime;
|
|
3964
4029
|
const errorMessage = error instanceof Error ? error.message : "Failed to perform vector search with embedding";
|
|
@@ -4014,8 +4079,7 @@ function createNeo4jCreateNodeWithEmbeddingTool() {
|
|
|
4014
4079
|
const embeddingResult = await embeddingManager.generateEmbedding(textToEmbed, input.model);
|
|
4015
4080
|
const safeLabel = validateLabel(input.label);
|
|
4016
4081
|
const safeEmbeddingProp = validatePropertyKey(input.embeddingProperty || "embedding");
|
|
4017
|
-
|
|
4018
|
-
try {
|
|
4082
|
+
return await withNeo4jSession(input.database, async (session) => {
|
|
4019
4083
|
const allProperties = {
|
|
4020
4084
|
...input.properties
|
|
4021
4085
|
};
|
|
@@ -4049,9 +4113,7 @@ function createNeo4jCreateNodeWithEmbeddingTool() {
|
|
|
4049
4113
|
},
|
|
4050
4114
|
message: `Created node with label '${input.label}' and ${embeddingResult.dimensions}-dimensional embedding`
|
|
4051
4115
|
};
|
|
4052
|
-
}
|
|
4053
|
-
await session.close();
|
|
4054
|
-
}
|
|
4116
|
+
});
|
|
4055
4117
|
} catch (error) {
|
|
4056
4118
|
const errorMessage = error instanceof Error ? error.message : "Failed to create node with embedding";
|
|
4057
4119
|
let helpText = "";
|
|
@@ -10338,49 +10400,57 @@ var fileSearchSchema = zod.z.object({
|
|
|
10338
10400
|
recursive: zod.z.boolean().default(true).describe("Search in subdirectories"),
|
|
10339
10401
|
caseSensitive: zod.z.boolean().default(false).describe("Case-sensitive pattern matching")
|
|
10340
10402
|
});
|
|
10403
|
+
async function* traverseDirectory(directory, recursive) {
|
|
10404
|
+
const entries = await fs.promises.readdir(directory, { withFileTypes: true });
|
|
10405
|
+
for (const entry of entries) {
|
|
10406
|
+
const fullPath = path__namespace.join(directory, entry.name);
|
|
10407
|
+
const isDirectory = entry.isDirectory();
|
|
10408
|
+
yield {
|
|
10409
|
+
name: entry.name,
|
|
10410
|
+
fullPath,
|
|
10411
|
+
isFile: entry.isFile(),
|
|
10412
|
+
isDirectory
|
|
10413
|
+
};
|
|
10414
|
+
if (recursive && isDirectory) {
|
|
10415
|
+
yield* traverseDirectory(fullPath, true);
|
|
10416
|
+
}
|
|
10417
|
+
}
|
|
10418
|
+
}
|
|
10419
|
+
|
|
10420
|
+
// src/file/directory/tools/directory-list.ts
|
|
10341
10421
|
function createDirectoryListTool(defaultRecursive = false, defaultIncludeDetails = false, policy = DEFAULT_FILE_SYSTEM_POLICY) {
|
|
10342
10422
|
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
10423
|
const safePath = await policy.resolvePath(input.path, "directory listing");
|
|
10344
10424
|
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);
|
|
10425
|
+
const recursive = input.recursive ?? defaultRecursive;
|
|
10426
|
+
const files = [];
|
|
10427
|
+
for await (const entry of traverseDirectory(safePath, recursive)) {
|
|
10428
|
+
const relativePath = path__namespace.relative(safePath, entry.fullPath);
|
|
10429
|
+
if (input.extension && !entry.name.endsWith(input.extension)) {
|
|
10430
|
+
if (!entry.isDirectory || !recursive) {
|
|
10431
|
+
continue;
|
|
10378
10432
|
}
|
|
10379
10433
|
}
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10383
|
-
|
|
10434
|
+
if (includeDetails) {
|
|
10435
|
+
const stats = await fs.promises.lstat(entry.fullPath);
|
|
10436
|
+
files.push({
|
|
10437
|
+
name: entry.name,
|
|
10438
|
+
path: relativePath,
|
|
10439
|
+
fullPath: entry.fullPath,
|
|
10440
|
+
isFile: entry.isFile,
|
|
10441
|
+
isDirectory: entry.isDirectory,
|
|
10442
|
+
size: stats.size,
|
|
10443
|
+
modified: stats.mtime.toISOString()
|
|
10444
|
+
});
|
|
10445
|
+
} else {
|
|
10446
|
+
files.push({
|
|
10447
|
+
name: entry.name,
|
|
10448
|
+
path: relativePath,
|
|
10449
|
+
isFile: entry.isFile,
|
|
10450
|
+
isDirectory: entry.isDirectory
|
|
10451
|
+
});
|
|
10452
|
+
}
|
|
10453
|
+
}
|
|
10384
10454
|
const result = {
|
|
10385
10455
|
path: input.path,
|
|
10386
10456
|
files,
|
|
@@ -10416,24 +10486,14 @@ function createFileSearchTool(defaultRecursive = true, defaultCaseSensitive = fa
|
|
|
10416
10486
|
const recursive = input.recursive ?? defaultRecursive;
|
|
10417
10487
|
const caseSensitive = input.caseSensitive ?? defaultCaseSensitive;
|
|
10418
10488
|
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
|
-
}
|
|
10489
|
+
const regexPattern = input.pattern.replace(/\./g, "\\.").replace(/\*/g, ".*");
|
|
10490
|
+
const regex = new RegExp(`^${regexPattern}$`, caseSensitive ? "" : "i");
|
|
10491
|
+
const matches = [];
|
|
10492
|
+
for await (const entry of traverseDirectory(safeDirectory, recursive)) {
|
|
10493
|
+
if (entry.isFile && regex.test(entry.name)) {
|
|
10494
|
+
matches.push(entry.fullPath);
|
|
10433
10495
|
}
|
|
10434
|
-
|
|
10435
|
-
};
|
|
10436
|
-
const matches = await searchFiles(safeDirectory);
|
|
10496
|
+
}
|
|
10437
10497
|
return {
|
|
10438
10498
|
directory: input.directory,
|
|
10439
10499
|
pattern: input.pattern,
|
|
@@ -11395,11 +11455,11 @@ var AskHumanInputSchema = zod.z.object({
|
|
|
11395
11455
|
});
|
|
11396
11456
|
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
|
|
11397
11457
|
var logger19 = core.createLogger("agentforge:tools:agent:ask-human", { level: logLevel3 });
|
|
11398
|
-
function
|
|
11458
|
+
function isRecord4(value) {
|
|
11399
11459
|
return typeof value === "object" && value !== null;
|
|
11400
11460
|
}
|
|
11401
11461
|
function resolveInterrupt(module) {
|
|
11402
|
-
if (!
|
|
11462
|
+
if (!isRecord4(module)) {
|
|
11403
11463
|
return void 0;
|
|
11404
11464
|
}
|
|
11405
11465
|
const candidate = module.interrupt;
|