@agentforge/tools 0.16.52 → 0.16.54
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 +215 -204
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -13
- package/dist/index.d.ts +28 -13
- package/dist/index.js +215 -204
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -467,7 +467,7 @@ function sleep(ms) {
|
|
|
467
467
|
}
|
|
468
468
|
async function retryWithBackoff(fn, config = DEFAULT_RETRY_CONFIG) {
|
|
469
469
|
let lastError;
|
|
470
|
-
let
|
|
470
|
+
let delay = config.initialDelay;
|
|
471
471
|
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
|
472
472
|
try {
|
|
473
473
|
return await fn();
|
|
@@ -479,8 +479,8 @@ async function retryWithBackoff(fn, config = DEFAULT_RETRY_CONFIG) {
|
|
|
479
479
|
if (attempt === config.maxRetries) {
|
|
480
480
|
break;
|
|
481
481
|
}
|
|
482
|
-
await sleep(
|
|
483
|
-
|
|
482
|
+
await sleep(delay);
|
|
483
|
+
delay = Math.min(delay * config.backoffMultiplier, config.maxDelay);
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
throw lastError;
|
|
@@ -788,7 +788,7 @@ function getDefaultSlackClient() {
|
|
|
788
788
|
}
|
|
789
789
|
};
|
|
790
790
|
}
|
|
791
|
-
function createSendSlackMessageTool(getSlackClient,
|
|
791
|
+
function createSendSlackMessageTool(getSlackClient, logger23) {
|
|
792
792
|
return toolBuilder().name("send-slack-message").description("Send a message to a Slack channel for team communication and notifications").category(ToolCategory.WEB).tags(["slack", "messaging", "communication"]).usageNotes(
|
|
793
793
|
"Use this for general team communication. For notifications with @mentions, consider using notify-slack instead. Use get-slack-channels first if you need to find the right channel."
|
|
794
794
|
).suggests(["get-slack-channels"]).schema(
|
|
@@ -797,7 +797,7 @@ function createSendSlackMessageTool(getSlackClient, logger24) {
|
|
|
797
797
|
message: z.string().describe("Message content to send")
|
|
798
798
|
})
|
|
799
799
|
).implementSafe(async ({ channel, message }) => {
|
|
800
|
-
|
|
800
|
+
logger23.info("send-slack-message called", { channel, messageLength: message.length });
|
|
801
801
|
try {
|
|
802
802
|
const { client: slack, config } = getSlackClient();
|
|
803
803
|
const result = await slack.chat.postMessage({
|
|
@@ -806,7 +806,7 @@ function createSendSlackMessageTool(getSlackClient, logger24) {
|
|
|
806
806
|
username: config.botName,
|
|
807
807
|
icon_emoji: config.botIcon
|
|
808
808
|
});
|
|
809
|
-
|
|
809
|
+
logger23.info("send-slack-message result", {
|
|
810
810
|
...result.channel ? { channel: result.channel } : {},
|
|
811
811
|
...result.ts ? { timestamp: result.ts } : {},
|
|
812
812
|
messageLength: message.length,
|
|
@@ -819,7 +819,7 @@ function createSendSlackMessageTool(getSlackClient, logger24) {
|
|
|
819
819
|
message_id: result.ts
|
|
820
820
|
};
|
|
821
821
|
} catch (error) {
|
|
822
|
-
|
|
822
|
+
logger23.error("send-slack-message failed", {
|
|
823
823
|
channel,
|
|
824
824
|
error: error.message,
|
|
825
825
|
data: error.data
|
|
@@ -828,7 +828,7 @@ function createSendSlackMessageTool(getSlackClient, logger24) {
|
|
|
828
828
|
}
|
|
829
829
|
}).build();
|
|
830
830
|
}
|
|
831
|
-
function createNotifySlackTool(getSlackClient,
|
|
831
|
+
function createNotifySlackTool(getSlackClient, logger23) {
|
|
832
832
|
return toolBuilder().name("notify-slack").description("Send a notification to a Slack channel with optional @mentions for urgent alerts").category(ToolCategory.WEB).tags(["slack", "notification", "alert"]).usageNotes(
|
|
833
833
|
"Use this for urgent notifications that require @mentions. For general messages without mentions, use send-slack-message instead."
|
|
834
834
|
).suggests(["get-slack-channels"]).schema(
|
|
@@ -838,7 +838,7 @@ function createNotifySlackTool(getSlackClient, logger24) {
|
|
|
838
838
|
mentions: z.array(z.string()).optional().describe("List of usernames to mention (without @)")
|
|
839
839
|
})
|
|
840
840
|
).implementSafe(async ({ channel, message, mentions = [] }) => {
|
|
841
|
-
|
|
841
|
+
logger23.info("notify-slack called", {
|
|
842
842
|
channel,
|
|
843
843
|
messageLength: message.length,
|
|
844
844
|
mentionCount: mentions.length
|
|
@@ -852,7 +852,7 @@ function createNotifySlackTool(getSlackClient, logger24) {
|
|
|
852
852
|
username: config.botName,
|
|
853
853
|
icon_emoji: config.botIcon
|
|
854
854
|
});
|
|
855
|
-
|
|
855
|
+
logger23.info("notify-slack result", {
|
|
856
856
|
...result.channel ? { channel: result.channel } : {},
|
|
857
857
|
...result.ts ? { timestamp: result.ts } : {},
|
|
858
858
|
mentions: mentions.length
|
|
@@ -866,7 +866,7 @@ function createNotifySlackTool(getSlackClient, logger24) {
|
|
|
866
866
|
};
|
|
867
867
|
}).build();
|
|
868
868
|
}
|
|
869
|
-
function createGetSlackChannelsTool(getSlackClient,
|
|
869
|
+
function createGetSlackChannelsTool(getSlackClient, logger23) {
|
|
870
870
|
return toolBuilder().name("get-slack-channels").description("Get a list of available Slack channels to find the right channel for messaging").category(ToolCategory.WEB).tags(["slack", "channels", "list"]).usageNotes(
|
|
871
871
|
"Use this first to discover available channels before sending messages. Helps ensure you are sending to the correct channel."
|
|
872
872
|
).follows(["send-slack-message", "notify-slack"]).schema(
|
|
@@ -874,7 +874,7 @@ function createGetSlackChannelsTool(getSlackClient, logger24) {
|
|
|
874
874
|
include_private: z.boolean().optional().describe("Include private channels (default: false)")
|
|
875
875
|
})
|
|
876
876
|
).implementSafe(async ({ include_private = false }) => {
|
|
877
|
-
|
|
877
|
+
logger23.info("get-slack-channels called", { include_private });
|
|
878
878
|
const { client: slack } = getSlackClient();
|
|
879
879
|
const publicChannels = await slack.conversations.list({
|
|
880
880
|
types: "public_channel",
|
|
@@ -888,7 +888,7 @@ function createGetSlackChannelsTool(getSlackClient, logger24) {
|
|
|
888
888
|
});
|
|
889
889
|
allChannels = [...allChannels, ...privateChannels.channels || []];
|
|
890
890
|
}
|
|
891
|
-
|
|
891
|
+
logger23.info("get-slack-channels result", {
|
|
892
892
|
channelCount: allChannels.length,
|
|
893
893
|
includePrivate: include_private
|
|
894
894
|
});
|
|
@@ -903,7 +903,7 @@ function createGetSlackChannelsTool(getSlackClient, logger24) {
|
|
|
903
903
|
};
|
|
904
904
|
}).build();
|
|
905
905
|
}
|
|
906
|
-
function createGetSlackMessagesTool(getSlackClient,
|
|
906
|
+
function createGetSlackMessagesTool(getSlackClient, logger23) {
|
|
907
907
|
return toolBuilder().name("get-slack-messages").description("Retrieve message history from a Slack channel to read recent conversations").category(ToolCategory.WEB).tags(["slack", "messages", "history", "read"]).usageNotes(
|
|
908
908
|
"Use this to read recent messages from a channel. Use get-slack-channels first if you need to find the channel ID. Returns messages in reverse chronological order (newest first)."
|
|
909
909
|
).suggests(["get-slack-channels"]).schema(
|
|
@@ -912,7 +912,7 @@ function createGetSlackMessagesTool(getSlackClient, logger24) {
|
|
|
912
912
|
limit: z.number().int().min(1).max(100).optional().describe("Number of messages to retrieve (default: 20, max: 100)")
|
|
913
913
|
})
|
|
914
914
|
).implementSafe(async ({ channel, limit = 20 }) => {
|
|
915
|
-
|
|
915
|
+
logger23.info("get-slack-messages called", { channel, limit });
|
|
916
916
|
try {
|
|
917
917
|
const { client: slack } = getSlackClient();
|
|
918
918
|
let channelId = channel;
|
|
@@ -923,7 +923,7 @@ function createGetSlackMessagesTool(getSlackClient, logger24) {
|
|
|
923
923
|
});
|
|
924
924
|
const found = channels.channels?.find((c) => c.name === channel);
|
|
925
925
|
if (!found) {
|
|
926
|
-
|
|
926
|
+
logger23.error("get-slack-messages: channel not found", { channel });
|
|
927
927
|
throw new Error(
|
|
928
928
|
`Channel '${channel}' not found. Use get-slack-channels to see available channels.`
|
|
929
929
|
);
|
|
@@ -935,7 +935,7 @@ function createGetSlackMessagesTool(getSlackClient, logger24) {
|
|
|
935
935
|
limit: Math.min(limit, 100)
|
|
936
936
|
// Cap at 100 for performance
|
|
937
937
|
});
|
|
938
|
-
|
|
938
|
+
logger23.info("get-slack-messages result", {
|
|
939
939
|
channel: channelId,
|
|
940
940
|
messageCount: result.messages?.length || 0,
|
|
941
941
|
limit
|
|
@@ -953,7 +953,7 @@ function createGetSlackMessagesTool(getSlackClient, logger24) {
|
|
|
953
953
|
})) || []
|
|
954
954
|
};
|
|
955
955
|
} catch (error) {
|
|
956
|
-
|
|
956
|
+
logger23.error("get-slack-messages failed", {
|
|
957
957
|
channel,
|
|
958
958
|
error: error.message,
|
|
959
959
|
data: error.data
|
|
@@ -1034,12 +1034,12 @@ function getAuthHeader() {
|
|
|
1034
1034
|
const auth2 = Buffer.from(`${ATLASSIAN_EMAIL}:${ATLASSIAN_API_KEY}`).toString("base64");
|
|
1035
1035
|
return `Basic ${auth2}`;
|
|
1036
1036
|
}
|
|
1037
|
-
function createSearchConfluenceTool(getAuth, getAuthHeader2,
|
|
1037
|
+
function createSearchConfluenceTool(getAuth, getAuthHeader2, logger23) {
|
|
1038
1038
|
return toolBuilder().name("search-confluence").description("Search for pages in Confluence using keywords or CQL (Confluence Query Language). Returns matching pages with titles, IDs, and excerpts.").category(ToolCategory.WEB).tag("confluence").tag("search").tag("knowledge-base").usageNotes("Use this to find relevant documentation, policies, or information in Confluence. You can search by keywords or use CQL for advanced queries (e.g., 'space=AI AND type=page'). Use get-confluence-page to retrieve full content of specific pages.").suggests(["get-confluence-page"]).schema(z.object({
|
|
1039
1039
|
query: z.string().describe("Search query or CQL expression (e.g., 'payment processing' or 'space=BL3 AND title~payment')"),
|
|
1040
1040
|
limit: z.number().optional().describe("Maximum number of results to return (default: 10, max: 25)")
|
|
1041
1041
|
})).implement(async ({ query, limit = 10 }) => {
|
|
1042
|
-
|
|
1042
|
+
logger23.info("search-confluence called", { query, limit });
|
|
1043
1043
|
try {
|
|
1044
1044
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1045
1045
|
const response = await axios16.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/search`, {
|
|
@@ -1064,13 +1064,13 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1064
1064
|
lastModified: page.version?.when || ""
|
|
1065
1065
|
}));
|
|
1066
1066
|
if (results.length === 0) {
|
|
1067
|
-
|
|
1067
|
+
logger23.warn("search-confluence returned NO RESULTS - this is a valid outcome, agent should not retry", {
|
|
1068
1068
|
query,
|
|
1069
1069
|
limit,
|
|
1070
1070
|
totalSize: response.data.totalSize
|
|
1071
1071
|
});
|
|
1072
1072
|
} else {
|
|
1073
|
-
|
|
1073
|
+
logger23.info("search-confluence result", {
|
|
1074
1074
|
query,
|
|
1075
1075
|
resultCount: results.length,
|
|
1076
1076
|
totalSize: response.data.totalSize,
|
|
@@ -1085,7 +1085,7 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1085
1085
|
results
|
|
1086
1086
|
});
|
|
1087
1087
|
} catch (error) {
|
|
1088
|
-
|
|
1088
|
+
logger23.error("search-confluence error", {
|
|
1089
1089
|
query,
|
|
1090
1090
|
error: error.response?.data?.message || error.message,
|
|
1091
1091
|
status: error.response?.status
|
|
@@ -1097,11 +1097,11 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1097
1097
|
}
|
|
1098
1098
|
}).build();
|
|
1099
1099
|
}
|
|
1100
|
-
function createGetConfluencePageTool(getAuth, getAuthHeader2,
|
|
1100
|
+
function createGetConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
1101
1101
|
return toolBuilder().name("get-confluence-page").description("Get the full content of a specific Confluence page by its ID. Returns the page title, content (in storage format), space, and metadata.").category(ToolCategory.WEB).tag("confluence").tag("page").tag("content").usageNotes("Use this after search-confluence to retrieve the full content of a specific page. The page ID can be found in search results.").requires(["search-confluence"]).schema(z.object({
|
|
1102
1102
|
page_id: z.string().describe("The Confluence page ID (from search results)")
|
|
1103
1103
|
})).implement(async ({ page_id }) => {
|
|
1104
|
-
|
|
1104
|
+
logger23.info("get-confluence-page called", { page_id });
|
|
1105
1105
|
try {
|
|
1106
1106
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1107
1107
|
const response = await axios16.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`, {
|
|
@@ -1114,7 +1114,7 @@ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1114
1114
|
}
|
|
1115
1115
|
});
|
|
1116
1116
|
const page = response.data;
|
|
1117
|
-
|
|
1117
|
+
logger23.info("get-confluence-page result", {
|
|
1118
1118
|
page_id,
|
|
1119
1119
|
title: page.title,
|
|
1120
1120
|
space: page.space?.name,
|
|
@@ -1136,7 +1136,7 @@ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1136
1136
|
}
|
|
1137
1137
|
});
|
|
1138
1138
|
} catch (error) {
|
|
1139
|
-
|
|
1139
|
+
logger23.error("get-confluence-page error", {
|
|
1140
1140
|
page_id,
|
|
1141
1141
|
error: error.response?.data?.message || error.message,
|
|
1142
1142
|
status: error.response?.status
|
|
@@ -1148,11 +1148,11 @@ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1148
1148
|
}
|
|
1149
1149
|
}).build();
|
|
1150
1150
|
}
|
|
1151
|
-
function createListConfluenceSpacesTool(getAuth, getAuthHeader2,
|
|
1151
|
+
function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger23) {
|
|
1152
1152
|
return toolBuilder().name("list-confluence-spaces").description("List all available Confluence spaces. Returns space names, keys, types, and descriptions to help identify where to search for information.").category(ToolCategory.WEB).tag("confluence").tag("spaces").tag("list").usageNotes("Use this first to discover available spaces before searching. Helps narrow down searches to specific areas (e.g., 'AI', 'BL3', 'Finance').").follows(["search-confluence"]).schema(z.object({
|
|
1153
1153
|
limit: z.number().optional().describe("Maximum number of spaces to return (default: 25)")
|
|
1154
1154
|
})).implement(async ({ limit = 25 }) => {
|
|
1155
|
-
|
|
1155
|
+
logger23.info("list-confluence-spaces called", { limit });
|
|
1156
1156
|
try {
|
|
1157
1157
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1158
1158
|
const response = await axios16.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/space`, {
|
|
@@ -1171,7 +1171,7 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1171
1171
|
description: space.description?.plain?.value || "",
|
|
1172
1172
|
url: `${ATLASSIAN_SITE_URL}/wiki${space._links.webui}`
|
|
1173
1173
|
}));
|
|
1174
|
-
|
|
1174
|
+
logger23.info("list-confluence-spaces result", {
|
|
1175
1175
|
spaceCount: spaces.length,
|
|
1176
1176
|
spaceKeys: spaces.map((s) => s.key).slice(0, 5)
|
|
1177
1177
|
// Log first 5 space keys
|
|
@@ -1182,7 +1182,7 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1182
1182
|
spaces
|
|
1183
1183
|
});
|
|
1184
1184
|
} catch (error) {
|
|
1185
|
-
|
|
1185
|
+
logger23.error("list-confluence-spaces error", {
|
|
1186
1186
|
error: error.response?.data?.message || error.message,
|
|
1187
1187
|
status: error.response?.status
|
|
1188
1188
|
});
|
|
@@ -1193,12 +1193,12 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1193
1193
|
}
|
|
1194
1194
|
}).build();
|
|
1195
1195
|
}
|
|
1196
|
-
function createGetSpacePagesTool(getAuth, getAuthHeader2,
|
|
1196
|
+
function createGetSpacePagesTool(getAuth, getAuthHeader2, logger23) {
|
|
1197
1197
|
return toolBuilder().name("get-space-pages").description("Get all pages from a specific Confluence space by space key. Useful for browsing content in a particular area.").category(ToolCategory.WEB).tag("confluence").tag("space").tag("pages").usageNotes("Use this to explore all pages in a specific space. Get the space key from list-confluence-spaces first.").requires(["list-confluence-spaces"]).schema(z.object({
|
|
1198
1198
|
space_key: z.string().describe("The space key (e.g., 'AI', 'BL3', 'FIN')"),
|
|
1199
1199
|
limit: z.number().optional().describe("Maximum number of pages to return (default: 25)")
|
|
1200
1200
|
})).implement(async ({ space_key, limit = 25 }) => {
|
|
1201
|
-
|
|
1201
|
+
logger23.info("get-space-pages called", { space_key, limit });
|
|
1202
1202
|
try {
|
|
1203
1203
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1204
1204
|
const response = await axios16.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content`, {
|
|
@@ -1220,12 +1220,12 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1220
1220
|
lastModified: page.version?.when || ""
|
|
1221
1221
|
}));
|
|
1222
1222
|
if (pages.length === 0) {
|
|
1223
|
-
|
|
1223
|
+
logger23.warn("get-space-pages returned NO PAGES - this is a valid outcome, agent should not retry", {
|
|
1224
1224
|
space_key,
|
|
1225
1225
|
limit
|
|
1226
1226
|
});
|
|
1227
1227
|
} else {
|
|
1228
|
-
|
|
1228
|
+
logger23.info("get-space-pages result", {
|
|
1229
1229
|
space_key,
|
|
1230
1230
|
pageCount: pages.length,
|
|
1231
1231
|
titles: pages.map((p) => p.title).slice(0, 3)
|
|
@@ -1239,7 +1239,7 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1239
1239
|
pages
|
|
1240
1240
|
});
|
|
1241
1241
|
} catch (error) {
|
|
1242
|
-
|
|
1242
|
+
logger23.error("get-space-pages error", {
|
|
1243
1243
|
space_key,
|
|
1244
1244
|
error: error.response?.data?.message || error.message,
|
|
1245
1245
|
status: error.response?.status
|
|
@@ -1251,14 +1251,14 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1251
1251
|
}
|
|
1252
1252
|
}).build();
|
|
1253
1253
|
}
|
|
1254
|
-
function createCreateConfluencePageTool(getAuth, getAuthHeader2,
|
|
1254
|
+
function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
1255
1255
|
return toolBuilder().name("create-confluence-page").description("Create a new page in a Confluence space. Requires space key, page title, and content (in HTML storage format).").category(ToolCategory.WEB).tag("confluence").tag("create").tag("write").usageNotes("Use this to create new documentation pages. Content should be in Confluence storage format (HTML). Get the space key from list-confluence-spaces first. Be mindful of creating duplicate pages.").requires(["list-confluence-spaces"]).schema(z.object({
|
|
1256
1256
|
space_key: z.string().describe("The space key where the page will be created (e.g., 'AI', 'BL3')"),
|
|
1257
1257
|
title: z.string().describe("The title of the new page"),
|
|
1258
1258
|
content: z.string().describe("The page content in HTML format (Confluence storage format)"),
|
|
1259
1259
|
parent_page_id: z.string().optional().describe("Optional parent page ID to create this as a child page")
|
|
1260
1260
|
})).implement(async ({ space_key, title, content, parent_page_id }) => {
|
|
1261
|
-
|
|
1261
|
+
logger23.info("create-confluence-page called", { space_key, title, hasParent: !!parent_page_id });
|
|
1262
1262
|
try {
|
|
1263
1263
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1264
1264
|
const pageData = {
|
|
@@ -1285,7 +1285,7 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1285
1285
|
}
|
|
1286
1286
|
}
|
|
1287
1287
|
);
|
|
1288
|
-
|
|
1288
|
+
logger23.info("create-confluence-page result", {
|
|
1289
1289
|
page_id: response.data.id,
|
|
1290
1290
|
title: response.data.title,
|
|
1291
1291
|
space: space_key
|
|
@@ -1301,7 +1301,7 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1301
1301
|
}
|
|
1302
1302
|
});
|
|
1303
1303
|
} catch (error) {
|
|
1304
|
-
|
|
1304
|
+
logger23.error("create-confluence-page error", {
|
|
1305
1305
|
space_key,
|
|
1306
1306
|
title,
|
|
1307
1307
|
error: error.response?.data?.message || error.message,
|
|
@@ -1314,13 +1314,13 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1314
1314
|
}
|
|
1315
1315
|
}).build();
|
|
1316
1316
|
}
|
|
1317
|
-
function createUpdateConfluencePageTool(getAuth, getAuthHeader2,
|
|
1317
|
+
function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
1318
1318
|
return toolBuilder().name("update-confluence-page").description("Update an existing Confluence page's content. Requires page ID, new title, and new content.").category(ToolCategory.WEB).tag("confluence").tag("update").tag("write").usageNotes("Use this to update existing documentation. You must provide the page ID (from search results). The tool will automatically handle version incrementing. Always get the current page content first to avoid overwriting important information.").requires(["get-confluence-page"]).schema(z.object({
|
|
1319
1319
|
page_id: z.string().describe("The ID of the page to update"),
|
|
1320
1320
|
title: z.string().describe("The new title for the page"),
|
|
1321
1321
|
content: z.string().describe("The new content in HTML format (Confluence storage format)")
|
|
1322
1322
|
})).implement(async ({ page_id, title, content }) => {
|
|
1323
|
-
|
|
1323
|
+
logger23.info("update-confluence-page called", { page_id, title });
|
|
1324
1324
|
try {
|
|
1325
1325
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1326
1326
|
const getResponse = await axios16.get(
|
|
@@ -1353,7 +1353,7 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1353
1353
|
}
|
|
1354
1354
|
}
|
|
1355
1355
|
);
|
|
1356
|
-
|
|
1356
|
+
logger23.info("update-confluence-page result", {
|
|
1357
1357
|
page_id,
|
|
1358
1358
|
title: updateResponse.data.title,
|
|
1359
1359
|
previousVersion: currentVersion,
|
|
@@ -1370,7 +1370,7 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1370
1370
|
}
|
|
1371
1371
|
});
|
|
1372
1372
|
} catch (error) {
|
|
1373
|
-
|
|
1373
|
+
logger23.error("update-confluence-page error", {
|
|
1374
1374
|
page_id,
|
|
1375
1375
|
title,
|
|
1376
1376
|
error: error.response?.data?.message || error.message,
|
|
@@ -1383,12 +1383,12 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1383
1383
|
}
|
|
1384
1384
|
}).build();
|
|
1385
1385
|
}
|
|
1386
|
-
function createArchiveConfluencePageTool(getAuth, getAuthHeader2,
|
|
1386
|
+
function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
1387
1387
|
return toolBuilder().name("archive-confluence-page").description("Archive a Confluence page by moving it to trash. The page can be restored by space admins. Note: UI may require a note explaining why the page was archived.").category(ToolCategory.WEB).tag("confluence").tag("archive").tag("delete").usageNotes("Use this to archive outdated or obsolete documentation. The page is moved to trash, not permanently deleted. Space admins can restore it if needed. Be very careful - only archive pages that are truly obsolete.").conflicts(["create-confluence-page"]).schema(z.object({
|
|
1388
1388
|
page_id: z.string().describe("The ID of the page to archive"),
|
|
1389
1389
|
reason: z.string().optional().describe("Optional reason for archiving (for audit trail)")
|
|
1390
1390
|
})).implement(async ({ page_id, reason }) => {
|
|
1391
|
-
|
|
1391
|
+
logger23.info("archive-confluence-page called", {
|
|
1392
1392
|
page_id,
|
|
1393
1393
|
...reason ? { reason } : {}
|
|
1394
1394
|
});
|
|
@@ -1422,7 +1422,7 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1422
1422
|
}
|
|
1423
1423
|
}
|
|
1424
1424
|
);
|
|
1425
|
-
|
|
1425
|
+
logger23.info("archive-confluence-page result", {
|
|
1426
1426
|
page_id,
|
|
1427
1427
|
title: pageData.title,
|
|
1428
1428
|
previousVersion: currentVersion,
|
|
@@ -1440,7 +1440,7 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger24) {
|
|
|
1440
1440
|
}
|
|
1441
1441
|
});
|
|
1442
1442
|
} catch (error) {
|
|
1443
|
-
|
|
1443
|
+
logger23.error("archive-confluence-page error", {
|
|
1444
1444
|
page_id,
|
|
1445
1445
|
error: error.response?.data?.message || error.message,
|
|
1446
1446
|
status: error.response?.status
|
|
@@ -2367,7 +2367,7 @@ function sleep2(ms) {
|
|
|
2367
2367
|
}
|
|
2368
2368
|
async function retryWithBackoff2(fn, config = DEFAULT_RETRY_CONFIG2) {
|
|
2369
2369
|
let lastError;
|
|
2370
|
-
let
|
|
2370
|
+
let delay = config.initialDelay;
|
|
2371
2371
|
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
|
2372
2372
|
try {
|
|
2373
2373
|
return await fn();
|
|
@@ -2379,8 +2379,8 @@ async function retryWithBackoff2(fn, config = DEFAULT_RETRY_CONFIG2) {
|
|
|
2379
2379
|
if (attempt === config.maxRetries) {
|
|
2380
2380
|
break;
|
|
2381
2381
|
}
|
|
2382
|
-
await sleep2(
|
|
2383
|
-
|
|
2382
|
+
await sleep2(delay);
|
|
2383
|
+
delay = Math.min(delay * config.backoffMultiplier, config.maxDelay);
|
|
2384
2384
|
}
|
|
2385
2385
|
}
|
|
2386
2386
|
throw lastError;
|
|
@@ -4121,19 +4121,19 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
|
4121
4121
|
ConnectionState2["ERROR"] = "error";
|
|
4122
4122
|
return ConnectionState2;
|
|
4123
4123
|
})(ConnectionState || {});
|
|
4124
|
-
function cancelPendingReconnection(timer,
|
|
4124
|
+
function cancelPendingReconnection(timer, logger23, vendor, message) {
|
|
4125
4125
|
if (!timer) {
|
|
4126
4126
|
return null;
|
|
4127
4127
|
}
|
|
4128
|
-
|
|
4128
|
+
logger23.debug(message, { vendor });
|
|
4129
4129
|
clearTimeout(timer);
|
|
4130
4130
|
return null;
|
|
4131
4131
|
}
|
|
4132
|
-
async function waitForInFlightConnection(promise,
|
|
4132
|
+
async function waitForInFlightConnection(promise, logger23, vendor, phase) {
|
|
4133
4133
|
if (!promise) {
|
|
4134
4134
|
return null;
|
|
4135
4135
|
}
|
|
4136
|
-
|
|
4136
|
+
logger23.debug(`Waiting for in-flight connection attempt to complete before ${phase}`, {
|
|
4137
4137
|
vendor
|
|
4138
4138
|
});
|
|
4139
4139
|
try {
|
|
@@ -4150,37 +4150,37 @@ function shutdownClient(vendor, client) {
|
|
|
4150
4150
|
client.close();
|
|
4151
4151
|
}
|
|
4152
4152
|
}
|
|
4153
|
-
function scheduleReconnection(context,
|
|
4153
|
+
function scheduleReconnection(context, logger23) {
|
|
4154
4154
|
if (context.reconnectionConfig.maxAttempts > 0 && context.reconnectionAttempts >= context.reconnectionConfig.maxAttempts) {
|
|
4155
|
-
|
|
4155
|
+
logger23.error("Max reconnection attempts reached", {
|
|
4156
4156
|
vendor: context.vendor,
|
|
4157
4157
|
attempts: context.reconnectionAttempts,
|
|
4158
4158
|
maxAttempts: context.reconnectionConfig.maxAttempts
|
|
4159
4159
|
});
|
|
4160
4160
|
return;
|
|
4161
4161
|
}
|
|
4162
|
-
const
|
|
4162
|
+
const delay = Math.min(
|
|
4163
4163
|
context.reconnectionConfig.baseDelayMs * Math.pow(2, context.reconnectionAttempts),
|
|
4164
4164
|
context.reconnectionConfig.maxDelayMs
|
|
4165
4165
|
);
|
|
4166
4166
|
const nextAttempt = context.reconnectionAttempts + 1;
|
|
4167
4167
|
context.setReconnectionAttempts(nextAttempt);
|
|
4168
4168
|
context.setState("reconnecting" /* RECONNECTING */);
|
|
4169
|
-
|
|
4169
|
+
logger23.info("Scheduling reconnection attempt", {
|
|
4170
4170
|
vendor: context.vendor,
|
|
4171
4171
|
attempt: nextAttempt,
|
|
4172
4172
|
maxAttempts: context.reconnectionConfig.maxAttempts,
|
|
4173
|
-
delayMs:
|
|
4173
|
+
delayMs: delay
|
|
4174
4174
|
});
|
|
4175
4175
|
context.emitReconnecting({
|
|
4176
4176
|
attempt: nextAttempt,
|
|
4177
4177
|
maxAttempts: context.reconnectionConfig.maxAttempts,
|
|
4178
|
-
delayMs:
|
|
4178
|
+
delayMs: delay
|
|
4179
4179
|
});
|
|
4180
4180
|
const timer = setTimeout(async () => {
|
|
4181
4181
|
context.setReconnectionTimer(null);
|
|
4182
4182
|
try {
|
|
4183
|
-
|
|
4183
|
+
logger23.info("Attempting reconnection", {
|
|
4184
4184
|
vendor: context.vendor,
|
|
4185
4185
|
attempt: nextAttempt
|
|
4186
4186
|
});
|
|
@@ -4190,28 +4190,28 @@ function scheduleReconnection(context, logger24) {
|
|
|
4190
4190
|
context.setConnectPromise(promise);
|
|
4191
4191
|
await promise;
|
|
4192
4192
|
} catch (error) {
|
|
4193
|
-
|
|
4193
|
+
logger23.error("Reconnection attempt failed", {
|
|
4194
4194
|
vendor: context.vendor,
|
|
4195
4195
|
attempt: nextAttempt,
|
|
4196
4196
|
error: error instanceof Error ? error.message : String(error)
|
|
4197
4197
|
});
|
|
4198
4198
|
}
|
|
4199
|
-
},
|
|
4199
|
+
}, delay);
|
|
4200
4200
|
context.setReconnectionTimer(timer);
|
|
4201
4201
|
}
|
|
4202
4202
|
|
|
4203
4203
|
// src/data/relational/connection/connection-cleanup.ts
|
|
4204
|
-
async function cleanupConnectionResources(vendor, client, clearConnection,
|
|
4204
|
+
async function cleanupConnectionResources(vendor, client, clearConnection, logger23) {
|
|
4205
4205
|
if (!client) {
|
|
4206
4206
|
return;
|
|
4207
4207
|
}
|
|
4208
|
-
|
|
4208
|
+
logger23.debug("Cleaning up cancelled connection", {
|
|
4209
4209
|
vendor
|
|
4210
4210
|
});
|
|
4211
4211
|
try {
|
|
4212
4212
|
await shutdownClient(vendor, client);
|
|
4213
4213
|
} catch (error) {
|
|
4214
|
-
|
|
4214
|
+
logger23.debug("Error during cancelled connection cleanup", {
|
|
4215
4215
|
vendor,
|
|
4216
4216
|
error: error instanceof Error ? error.message : String(error)
|
|
4217
4217
|
});
|
|
@@ -4219,10 +4219,10 @@ async function cleanupConnectionResources(vendor, client, clearConnection, logge
|
|
|
4219
4219
|
clearConnection();
|
|
4220
4220
|
}
|
|
4221
4221
|
}
|
|
4222
|
-
async function closeManagedConnection(runtime,
|
|
4222
|
+
async function closeManagedConnection(runtime, logger23) {
|
|
4223
4223
|
const client = runtime.getClient();
|
|
4224
4224
|
if (client) {
|
|
4225
|
-
|
|
4225
|
+
logger23.info("Closing database connection", {
|
|
4226
4226
|
vendor: runtime.vendor,
|
|
4227
4227
|
state: runtime.getState()
|
|
4228
4228
|
});
|
|
@@ -4230,12 +4230,12 @@ async function closeManagedConnection(runtime, logger24) {
|
|
|
4230
4230
|
await shutdownClient(runtime.vendor, client);
|
|
4231
4231
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4232
4232
|
runtime.emitDisconnected();
|
|
4233
|
-
|
|
4233
|
+
logger23.debug("Database connection closed successfully", {
|
|
4234
4234
|
vendor: runtime.vendor,
|
|
4235
4235
|
state: runtime.getState()
|
|
4236
4236
|
});
|
|
4237
4237
|
} catch (error) {
|
|
4238
|
-
|
|
4238
|
+
logger23.error("Error closing database connection", {
|
|
4239
4239
|
vendor: runtime.vendor,
|
|
4240
4240
|
error: error instanceof Error ? error.message : String(error),
|
|
4241
4241
|
state: runtime.getState()
|
|
@@ -4408,11 +4408,11 @@ async function initializeSQLiteConnection(connection) {
|
|
|
4408
4408
|
}
|
|
4409
4409
|
|
|
4410
4410
|
// src/data/relational/connection/connection-initialization.ts
|
|
4411
|
-
async function initializeManagedConnection(runtime,
|
|
4411
|
+
async function initializeManagedConnection(runtime, logger23) {
|
|
4412
4412
|
const startTime = Date.now();
|
|
4413
4413
|
const currentGeneration = runtime.getConnectionGeneration();
|
|
4414
4414
|
if (runtime.getState() === "connected" /* CONNECTED */ && runtime.getClient()) {
|
|
4415
|
-
|
|
4415
|
+
logger23.warn("Re-initializing an already connected manager; emitting disconnected before cleanup", {
|
|
4416
4416
|
vendor: runtime.vendor
|
|
4417
4417
|
});
|
|
4418
4418
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
@@ -4424,11 +4424,11 @@ async function initializeManagedConnection(runtime, logger24) {
|
|
|
4424
4424
|
runtime.setClient(null);
|
|
4425
4425
|
runtime.setDb(null);
|
|
4426
4426
|
},
|
|
4427
|
-
|
|
4427
|
+
logger23
|
|
4428
4428
|
);
|
|
4429
4429
|
}
|
|
4430
4430
|
runtime.setState("connecting" /* CONNECTING */);
|
|
4431
|
-
|
|
4431
|
+
logger23.info("Initializing database connection", {
|
|
4432
4432
|
vendor: runtime.vendor,
|
|
4433
4433
|
connectionType: typeof runtime.config.connection,
|
|
4434
4434
|
state: runtime.getState()
|
|
@@ -4438,7 +4438,7 @@ async function initializeManagedConnection(runtime, logger24) {
|
|
|
4438
4438
|
runtime.setClient(initialized.client);
|
|
4439
4439
|
runtime.setDb(initialized.db);
|
|
4440
4440
|
if (currentGeneration !== runtime.getConnectionGeneration()) {
|
|
4441
|
-
|
|
4441
|
+
logger23.debug("Connection cancelled during initialization", {
|
|
4442
4442
|
vendor: runtime.vendor,
|
|
4443
4443
|
currentGeneration,
|
|
4444
4444
|
newGeneration: runtime.getConnectionGeneration()
|
|
@@ -4450,18 +4450,18 @@ async function initializeManagedConnection(runtime, logger24) {
|
|
|
4450
4450
|
runtime.setClient(null);
|
|
4451
4451
|
runtime.setDb(null);
|
|
4452
4452
|
},
|
|
4453
|
-
|
|
4453
|
+
logger23
|
|
4454
4454
|
);
|
|
4455
4455
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4456
4456
|
throw new Error("Connection cancelled during initialization");
|
|
4457
4457
|
}
|
|
4458
|
-
|
|
4458
|
+
logger23.debug("Validating connection health", { vendor: runtime.vendor });
|
|
4459
4459
|
const healthy = await runtime.isHealthy();
|
|
4460
4460
|
if (!healthy) {
|
|
4461
4461
|
throw new Error(`Failed to establish healthy connection to ${runtime.vendor} database`);
|
|
4462
4462
|
}
|
|
4463
4463
|
if (currentGeneration !== runtime.getConnectionGeneration()) {
|
|
4464
|
-
|
|
4464
|
+
logger23.debug("Connection cancelled during health check", {
|
|
4465
4465
|
vendor: runtime.vendor,
|
|
4466
4466
|
currentGeneration,
|
|
4467
4467
|
newGeneration: runtime.getConnectionGeneration()
|
|
@@ -4473,7 +4473,7 @@ async function initializeManagedConnection(runtime, logger24) {
|
|
|
4473
4473
|
runtime.setClient(null);
|
|
4474
4474
|
runtime.setDb(null);
|
|
4475
4475
|
},
|
|
4476
|
-
|
|
4476
|
+
logger23
|
|
4477
4477
|
);
|
|
4478
4478
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4479
4479
|
throw new Error("Connection cancelled during health check");
|
|
@@ -4481,7 +4481,7 @@ async function initializeManagedConnection(runtime, logger24) {
|
|
|
4481
4481
|
runtime.setState("connected" /* CONNECTED */);
|
|
4482
4482
|
runtime.emitConnected();
|
|
4483
4483
|
runtime.resetReconnectionAttempts();
|
|
4484
|
-
|
|
4484
|
+
logger23.info("Database connection initialized successfully", {
|
|
4485
4485
|
vendor: runtime.vendor,
|
|
4486
4486
|
duration: Date.now() - startTime,
|
|
4487
4487
|
state: runtime.getState()
|
|
@@ -4502,7 +4502,7 @@ async function initializeManagedConnection(runtime, logger24) {
|
|
|
4502
4502
|
if (runtime.errorListenerCount() > 0) {
|
|
4503
4503
|
runtime.emitError(normalizedError);
|
|
4504
4504
|
}
|
|
4505
|
-
|
|
4505
|
+
logger23.error(errorMessage, {
|
|
4506
4506
|
vendor: runtime.vendor,
|
|
4507
4507
|
error: normalizedError.message,
|
|
4508
4508
|
duration: Date.now() - startTime,
|
|
@@ -4515,13 +4515,13 @@ async function initializeManagedConnection(runtime, logger24) {
|
|
|
4515
4515
|
runtime.setClient(null);
|
|
4516
4516
|
runtime.setDb(null);
|
|
4517
4517
|
},
|
|
4518
|
-
|
|
4518
|
+
logger23
|
|
4519
4519
|
);
|
|
4520
4520
|
if (runtime.getReconnectionConfig().enabled && currentGeneration === runtime.getConnectionGeneration()) {
|
|
4521
4521
|
runtime.scheduleReconnection();
|
|
4522
4522
|
}
|
|
4523
4523
|
} else {
|
|
4524
|
-
|
|
4524
|
+
logger23.debug("Connection initialization cancelled", {
|
|
4525
4525
|
vendor: runtime.vendor,
|
|
4526
4526
|
duration: Date.now() - startTime,
|
|
4527
4527
|
state: runtime.getState()
|
|
@@ -4539,17 +4539,17 @@ function isSqliteNonQueryError(error) {
|
|
|
4539
4539
|
const hasNonQueryMessage = error.message.includes("does not return data");
|
|
4540
4540
|
return isSqliteOrTypeError && hasNonQueryMessage;
|
|
4541
4541
|
}
|
|
4542
|
-
async function checkConnectionHealth(args,
|
|
4542
|
+
async function checkConnectionHealth(args, logger23) {
|
|
4543
4543
|
if (!args.db || !args.client) {
|
|
4544
|
-
|
|
4544
|
+
logger23.debug("Health check failed: connection not initialized", { vendor: args.vendor });
|
|
4545
4545
|
return false;
|
|
4546
4546
|
}
|
|
4547
4547
|
try {
|
|
4548
4548
|
await args.execute(sql`SELECT 1`);
|
|
4549
|
-
|
|
4549
|
+
logger23.debug("Health check passed", { vendor: args.vendor });
|
|
4550
4550
|
return true;
|
|
4551
4551
|
} catch (error) {
|
|
4552
|
-
|
|
4552
|
+
logger23.debug("Health check failed", {
|
|
4553
4553
|
vendor: args.vendor,
|
|
4554
4554
|
error: error instanceof Error ? error.message : String(error)
|
|
4555
4555
|
});
|
|
@@ -4592,8 +4592,8 @@ function getConnectionPoolMetrics(vendor, client) {
|
|
|
4592
4592
|
}
|
|
4593
4593
|
|
|
4594
4594
|
// src/data/relational/connection/query-execution.ts
|
|
4595
|
-
async function executeQuery(context, query,
|
|
4596
|
-
|
|
4595
|
+
async function executeQuery(context, query, logger23) {
|
|
4596
|
+
logger23.debug("Executing SQL query", {
|
|
4597
4597
|
vendor: context.vendor
|
|
4598
4598
|
});
|
|
4599
4599
|
if (context.vendor === "sqlite") {
|
|
@@ -5362,7 +5362,8 @@ function buildSelectQuery(input) {
|
|
|
5362
5362
|
}
|
|
5363
5363
|
return query;
|
|
5364
5364
|
}
|
|
5365
|
-
|
|
5365
|
+
|
|
5366
|
+
// src/data/relational/query/batch-executor-options.ts
|
|
5366
5367
|
var DEFAULT_BATCH_SIZE = 100;
|
|
5367
5368
|
var MAX_BATCH_SIZE = 5e3;
|
|
5368
5369
|
var MAX_RETRY_ATTEMPTS = 5;
|
|
@@ -5376,7 +5377,7 @@ function normalizePositiveInt(value, fieldName, min, max, fallback) {
|
|
|
5376
5377
|
}
|
|
5377
5378
|
return value;
|
|
5378
5379
|
}
|
|
5379
|
-
function
|
|
5380
|
+
function resolveBatchExecutionOptions(options) {
|
|
5380
5381
|
return {
|
|
5381
5382
|
batchSize: normalizePositiveInt(options.batchSize, "batchSize", 1, MAX_BATCH_SIZE, DEFAULT_BATCH_SIZE),
|
|
5382
5383
|
continueOnError: options.continueOnError ?? true,
|
|
@@ -5385,7 +5386,7 @@ function resolveOptions(options) {
|
|
|
5385
5386
|
onProgress: options.onProgress
|
|
5386
5387
|
};
|
|
5387
5388
|
}
|
|
5388
|
-
function
|
|
5389
|
+
function chunkBatchItems(items, chunkSize) {
|
|
5389
5390
|
if (items.length === 0) {
|
|
5390
5391
|
return [];
|
|
5391
5392
|
}
|
|
@@ -5395,25 +5396,77 @@ function chunkItems(items, chunkSize) {
|
|
|
5395
5396
|
}
|
|
5396
5397
|
return chunks;
|
|
5397
5398
|
}
|
|
5398
|
-
|
|
5399
|
+
var batchExecutionLogger = createLogger("agentforge:tools:data:relational:batch");
|
|
5400
|
+
function toBatchErrorMessage(error) {
|
|
5399
5401
|
return error instanceof Error ? error.message : String(error);
|
|
5400
5402
|
}
|
|
5401
|
-
function
|
|
5403
|
+
function delayBatchRetry(ms) {
|
|
5402
5404
|
return new Promise((resolve2) => {
|
|
5403
5405
|
setTimeout(resolve2, ms);
|
|
5404
5406
|
});
|
|
5405
5407
|
}
|
|
5408
|
+
|
|
5409
|
+
// src/data/relational/query/batch-executor-benchmark.ts
|
|
5410
|
+
function resolveBenchmarkBatchSize(options) {
|
|
5411
|
+
return resolveBatchExecutionOptions({
|
|
5412
|
+
...options,
|
|
5413
|
+
continueOnError: true,
|
|
5414
|
+
maxRetries: 0,
|
|
5415
|
+
retryDelayMs: 0,
|
|
5416
|
+
batchSize: options.batchSize ?? DEFAULT_BATCH_SIZE
|
|
5417
|
+
}).batchSize;
|
|
5418
|
+
}
|
|
5419
|
+
async function benchmarkBatchExecution(params) {
|
|
5420
|
+
const batchSize = resolveBenchmarkBatchSize({
|
|
5421
|
+
batchSize: params.batchSize ?? DEFAULT_BATCH_SIZE
|
|
5422
|
+
});
|
|
5423
|
+
const batches = chunkBatchItems(params.items, Math.min(batchSize, MAX_BATCH_SIZE));
|
|
5424
|
+
const individualStart = Date.now();
|
|
5425
|
+
for (const [index, item] of params.items.entries()) {
|
|
5426
|
+
await params.runIndividual(item, index);
|
|
5427
|
+
}
|
|
5428
|
+
const individualExecutionTime = Date.now() - individualStart;
|
|
5429
|
+
const batchStart = Date.now();
|
|
5430
|
+
for (const [batchIndex, batchItems] of batches.entries()) {
|
|
5431
|
+
await params.runBatch(batchItems, batchIndex);
|
|
5432
|
+
}
|
|
5433
|
+
const batchedExecutionTime = Date.now() - batchStart;
|
|
5434
|
+
const timeSavedMs = Math.max(individualExecutionTime - batchedExecutionTime, 0);
|
|
5435
|
+
const speedupRatio = batchedExecutionTime > 0 ? individualExecutionTime / batchedExecutionTime : 0;
|
|
5436
|
+
const speedupPercent = individualExecutionTime > 0 ? timeSavedMs / individualExecutionTime * 100 : 0;
|
|
5437
|
+
batchExecutionLogger.debug("Batch benchmark completed", {
|
|
5438
|
+
itemCount: params.items.length,
|
|
5439
|
+
batchCount: batches.length,
|
|
5440
|
+
batchSize,
|
|
5441
|
+
individualExecutionTime,
|
|
5442
|
+
batchedExecutionTime,
|
|
5443
|
+
timeSavedMs,
|
|
5444
|
+
speedupPercent
|
|
5445
|
+
});
|
|
5446
|
+
return {
|
|
5447
|
+
itemCount: params.items.length,
|
|
5448
|
+
batchSize,
|
|
5449
|
+
batchCount: batches.length,
|
|
5450
|
+
individualExecutionTime,
|
|
5451
|
+
batchedExecutionTime,
|
|
5452
|
+
timeSavedMs,
|
|
5453
|
+
speedupRatio,
|
|
5454
|
+
speedupPercent
|
|
5455
|
+
};
|
|
5456
|
+
}
|
|
5457
|
+
|
|
5458
|
+
// src/data/relational/query/batch-executor-execution.ts
|
|
5406
5459
|
async function executeBatchedTask(task, options = {}) {
|
|
5407
5460
|
const startTime = Date.now();
|
|
5408
|
-
const resolved =
|
|
5409
|
-
const batches =
|
|
5461
|
+
const resolved = resolveBatchExecutionOptions(options);
|
|
5462
|
+
const batches = chunkBatchItems(task.items, resolved.batchSize);
|
|
5410
5463
|
const results = [];
|
|
5411
5464
|
const failures = [];
|
|
5412
5465
|
let processedItems = 0;
|
|
5413
5466
|
let successfulItems = 0;
|
|
5414
5467
|
let failedItems = 0;
|
|
5415
5468
|
let retries = 0;
|
|
5416
|
-
|
|
5469
|
+
batchExecutionLogger.debug("Starting batched execution", {
|
|
5417
5470
|
operation: task.operation,
|
|
5418
5471
|
totalItems: task.items.length,
|
|
5419
5472
|
totalBatches: batches.length,
|
|
@@ -5452,15 +5505,15 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5452
5505
|
lastError = error;
|
|
5453
5506
|
if (attempts <= resolved.maxRetries) {
|
|
5454
5507
|
retries += 1;
|
|
5455
|
-
|
|
5508
|
+
batchExecutionLogger.warn("Batch execution failed, retrying", {
|
|
5456
5509
|
operation: task.operation,
|
|
5457
5510
|
batchIndex,
|
|
5458
5511
|
attempts,
|
|
5459
5512
|
maxRetries: resolved.maxRetries,
|
|
5460
|
-
error:
|
|
5513
|
+
error: toBatchErrorMessage(error)
|
|
5461
5514
|
});
|
|
5462
5515
|
if (resolved.retryDelayMs > 0) {
|
|
5463
|
-
await
|
|
5516
|
+
await delayBatchRetry(resolved.retryDelayMs);
|
|
5464
5517
|
}
|
|
5465
5518
|
continue;
|
|
5466
5519
|
}
|
|
@@ -5469,7 +5522,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5469
5522
|
batchIndex,
|
|
5470
5523
|
batchSize: batchItems.length,
|
|
5471
5524
|
attempts,
|
|
5472
|
-
error:
|
|
5525
|
+
error: toBatchErrorMessage(error)
|
|
5473
5526
|
};
|
|
5474
5527
|
failures.push(failure);
|
|
5475
5528
|
processedItems += batchItems.length;
|
|
@@ -5491,7 +5544,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5491
5544
|
{ cause: lastError }
|
|
5492
5545
|
);
|
|
5493
5546
|
}
|
|
5494
|
-
|
|
5547
|
+
batchExecutionLogger.warn("Batch execution failed and was recorded for partial success", {
|
|
5495
5548
|
operation: task.operation,
|
|
5496
5549
|
batchIndex,
|
|
5497
5550
|
attempts,
|
|
@@ -5503,7 +5556,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5503
5556
|
}
|
|
5504
5557
|
const executionTime = Date.now() - startTime;
|
|
5505
5558
|
const partialSuccess = successfulItems > 0 && failedItems > 0;
|
|
5506
|
-
|
|
5559
|
+
batchExecutionLogger.debug("Batched execution completed", {
|
|
5507
5560
|
operation: task.operation,
|
|
5508
5561
|
totalItems: task.items.length,
|
|
5509
5562
|
successfulItems,
|
|
@@ -5525,49 +5578,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5525
5578
|
failures
|
|
5526
5579
|
};
|
|
5527
5580
|
}
|
|
5528
|
-
|
|
5529
|
-
const batchSize = normalizePositiveInt(
|
|
5530
|
-
params.batchSize,
|
|
5531
|
-
"batchSize",
|
|
5532
|
-
1,
|
|
5533
|
-
MAX_BATCH_SIZE,
|
|
5534
|
-
DEFAULT_BATCH_SIZE
|
|
5535
|
-
);
|
|
5536
|
-
const batches = chunkItems(params.items, batchSize);
|
|
5537
|
-
const individualStart = Date.now();
|
|
5538
|
-
for (const [index, item] of params.items.entries()) {
|
|
5539
|
-
await params.runIndividual(item, index);
|
|
5540
|
-
}
|
|
5541
|
-
const individualExecutionTime = Date.now() - individualStart;
|
|
5542
|
-
const batchStart = Date.now();
|
|
5543
|
-
for (const [batchIndex, batchItems] of batches.entries()) {
|
|
5544
|
-
await params.runBatch(batchItems, batchIndex);
|
|
5545
|
-
}
|
|
5546
|
-
const batchedExecutionTime = Date.now() - batchStart;
|
|
5547
|
-
const timeSavedMs = Math.max(individualExecutionTime - batchedExecutionTime, 0);
|
|
5548
|
-
const speedupRatio = batchedExecutionTime > 0 ? individualExecutionTime / batchedExecutionTime : 0;
|
|
5549
|
-
const speedupPercent = individualExecutionTime > 0 ? timeSavedMs / individualExecutionTime * 100 : 0;
|
|
5550
|
-
logger10.debug("Batch benchmark completed", {
|
|
5551
|
-
itemCount: params.items.length,
|
|
5552
|
-
batchCount: batches.length,
|
|
5553
|
-
batchSize,
|
|
5554
|
-
individualExecutionTime,
|
|
5555
|
-
batchedExecutionTime,
|
|
5556
|
-
timeSavedMs,
|
|
5557
|
-
speedupPercent
|
|
5558
|
-
});
|
|
5559
|
-
return {
|
|
5560
|
-
itemCount: params.items.length,
|
|
5561
|
-
batchSize,
|
|
5562
|
-
batchCount: batches.length,
|
|
5563
|
-
individualExecutionTime,
|
|
5564
|
-
batchedExecutionTime,
|
|
5565
|
-
timeSavedMs,
|
|
5566
|
-
speedupRatio,
|
|
5567
|
-
speedupPercent
|
|
5568
|
-
};
|
|
5569
|
-
}
|
|
5570
|
-
var logger11 = createLogger("agentforge:tools:data:relational:stream");
|
|
5581
|
+
var logger10 = createLogger("agentforge:tools:data:relational:stream");
|
|
5571
5582
|
var DEFAULT_CHUNK_SIZE = 100;
|
|
5572
5583
|
var MAX_CHUNK_SIZE = 5e3;
|
|
5573
5584
|
var DEFAULT_SAMPLE_SIZE = 50;
|
|
@@ -5700,7 +5711,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5700
5711
|
const endHeapUsed = process.memoryUsage().heapUsed;
|
|
5701
5712
|
peakHeapUsed = Math.max(peakHeapUsed, endHeapUsed);
|
|
5702
5713
|
const executionTime = Date.now() - startTime;
|
|
5703
|
-
|
|
5714
|
+
logger10.debug("Streaming SELECT execution completed", {
|
|
5704
5715
|
table: input.table,
|
|
5705
5716
|
vendor: input.vendor,
|
|
5706
5717
|
chunkCount,
|
|
@@ -5724,7 +5735,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5724
5735
|
};
|
|
5725
5736
|
}
|
|
5726
5737
|
async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
5727
|
-
|
|
5738
|
+
logger10.warn("Running streaming benchmark will execute the SELECT query twice (regular + streaming).", {
|
|
5728
5739
|
table: input.table,
|
|
5729
5740
|
vendor: input.vendor
|
|
5730
5741
|
});
|
|
@@ -5744,7 +5755,7 @@ async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
|
5744
5755
|
0
|
|
5745
5756
|
);
|
|
5746
5757
|
const memorySavedPercent = nonStreamingPeakHeapUsed > 0 ? memorySavedBytes / nonStreamingPeakHeapUsed * 100 : 0;
|
|
5747
|
-
|
|
5758
|
+
logger10.debug("Streaming benchmark completed", {
|
|
5748
5759
|
table: input.table,
|
|
5749
5760
|
vendor: input.vendor,
|
|
5750
5761
|
nonStreamingRows: nonStreamingRows.length,
|
|
@@ -5816,7 +5827,7 @@ function withTransactionTimeout(operation, timeoutMs, onTimeout) {
|
|
|
5816
5827
|
}
|
|
5817
5828
|
|
|
5818
5829
|
// src/data/relational/query/transaction-managed.ts
|
|
5819
|
-
var
|
|
5830
|
+
var logger11 = createLogger("agentforge:tools:data:relational:transaction");
|
|
5820
5831
|
var SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
5821
5832
|
var ManagedTransaction = class {
|
|
5822
5833
|
id;
|
|
@@ -5924,7 +5935,7 @@ var ManagedTransaction = class {
|
|
|
5924
5935
|
await this.executeQuery(sql.raw("PRAGMA read_uncommitted = 1"));
|
|
5925
5936
|
this.shouldRestoreSqliteReadUncommitted = true;
|
|
5926
5937
|
} else {
|
|
5927
|
-
|
|
5938
|
+
logger11.debug("Ignoring SQLite isolation level override", {
|
|
5928
5939
|
transactionId: this.id,
|
|
5929
5940
|
isolationLevel: this.options.isolationLevel
|
|
5930
5941
|
});
|
|
@@ -5949,7 +5960,7 @@ var ManagedTransaction = class {
|
|
|
5949
5960
|
const targetValue = this.sqliteReadUncommittedOriginal ?? 0;
|
|
5950
5961
|
await this.executeQuery(sql.raw(`PRAGMA read_uncommitted = ${targetValue}`));
|
|
5951
5962
|
} catch (error) {
|
|
5952
|
-
|
|
5963
|
+
logger11.warn("Failed to restore SQLite read_uncommitted pragma", {
|
|
5953
5964
|
transactionId: this.id,
|
|
5954
5965
|
error: error instanceof Error ? error.message : String(error)
|
|
5955
5966
|
});
|
|
@@ -5975,14 +5986,14 @@ var ManagedTransaction = class {
|
|
|
5975
5986
|
};
|
|
5976
5987
|
|
|
5977
5988
|
// src/data/relational/query/transaction-runner.ts
|
|
5978
|
-
var
|
|
5989
|
+
var logger12 = createLogger("agentforge:tools:data:relational:transaction");
|
|
5979
5990
|
var transactionSequence = 0;
|
|
5980
5991
|
async function withTransaction(manager, operation, options) {
|
|
5981
5992
|
const startTime = Date.now();
|
|
5982
5993
|
const resolvedOptions = resolveTransactionOptions(options);
|
|
5983
5994
|
const transactionId = `tx-${++transactionSequence}`;
|
|
5984
5995
|
const vendor = manager.getVendor();
|
|
5985
|
-
|
|
5996
|
+
logger12.debug("Starting transaction", {
|
|
5986
5997
|
transactionId,
|
|
5987
5998
|
vendor,
|
|
5988
5999
|
...resolvedOptions.isolationLevel ? { isolationLevel: resolvedOptions.isolationLevel } : {},
|
|
@@ -6009,7 +6020,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
6009
6020
|
if (transaction.isActive()) {
|
|
6010
6021
|
await transaction.commit();
|
|
6011
6022
|
}
|
|
6012
|
-
|
|
6023
|
+
logger12.debug("Transaction committed", {
|
|
6013
6024
|
transactionId,
|
|
6014
6025
|
vendor,
|
|
6015
6026
|
duration: Date.now() - startTime
|
|
@@ -6020,14 +6031,14 @@ async function withTransaction(manager, operation, options) {
|
|
|
6020
6031
|
try {
|
|
6021
6032
|
await transaction.rollback();
|
|
6022
6033
|
} catch (rollbackError) {
|
|
6023
|
-
|
|
6034
|
+
logger12.error("Transaction rollback failed", {
|
|
6024
6035
|
transactionId,
|
|
6025
6036
|
vendor,
|
|
6026
6037
|
error: rollbackError instanceof Error ? rollbackError.message : String(rollbackError)
|
|
6027
6038
|
});
|
|
6028
6039
|
}
|
|
6029
6040
|
}
|
|
6030
|
-
|
|
6041
|
+
logger12.error("Transaction failed", {
|
|
6031
6042
|
transactionId,
|
|
6032
6043
|
vendor,
|
|
6033
6044
|
duration: Date.now() - startTime,
|
|
@@ -6518,7 +6529,7 @@ async function inspectSQLite(runQueryRows) {
|
|
|
6518
6529
|
}
|
|
6519
6530
|
|
|
6520
6531
|
// src/data/relational/schema/schema-inspector.ts
|
|
6521
|
-
var
|
|
6532
|
+
var logger13 = createLogger("agentforge:tools:data:relational:schema-inspector");
|
|
6522
6533
|
var DEFAULT_CACHE_TTL_MS = 6e4;
|
|
6523
6534
|
var schemaCache = /* @__PURE__ */ new Map();
|
|
6524
6535
|
var SchemaInspector = class _SchemaInspector {
|
|
@@ -6546,7 +6557,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6546
6557
|
if (!bypassCache && this.cacheKey) {
|
|
6547
6558
|
const cached = schemaCache.get(this.cacheKey);
|
|
6548
6559
|
if (cached && cached.expiresAt > Date.now()) {
|
|
6549
|
-
|
|
6560
|
+
logger13.debug("Schema cache hit", { vendor: this.vendor });
|
|
6550
6561
|
return filterSchemaTables(cloneSchema(cached.schema), tableFilters);
|
|
6551
6562
|
}
|
|
6552
6563
|
}
|
|
@@ -6591,7 +6602,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6591
6602
|
return result.rows;
|
|
6592
6603
|
}
|
|
6593
6604
|
};
|
|
6594
|
-
var
|
|
6605
|
+
var logger14 = createLogger("agentforge:tools:data:relational:schema-validator");
|
|
6595
6606
|
function validateTableExists(schema, tableName) {
|
|
6596
6607
|
const errors = [];
|
|
6597
6608
|
if (!tableName || typeof tableName !== "string") {
|
|
@@ -6605,7 +6616,7 @@ function validateTableExists(schema, tableName) {
|
|
|
6605
6616
|
`Table "${tableName}" does not exist. Available tables: ${available || "(none)"}`
|
|
6606
6617
|
);
|
|
6607
6618
|
}
|
|
6608
|
-
|
|
6619
|
+
logger14.debug("Table existence validation", { tableName, valid: errors.length === 0 });
|
|
6609
6620
|
return { valid: errors.length === 0, errors };
|
|
6610
6621
|
}
|
|
6611
6622
|
function validateColumnsExist(schema, tableName, columnNames) {
|
|
@@ -6628,7 +6639,7 @@ function validateColumnsExist(schema, tableName, columnNames) {
|
|
|
6628
6639
|
);
|
|
6629
6640
|
}
|
|
6630
6641
|
}
|
|
6631
|
-
|
|
6642
|
+
logger14.debug("Column existence validation", {
|
|
6632
6643
|
tableName,
|
|
6633
6644
|
columnCount: columnNames.length,
|
|
6634
6645
|
valid: errors.length === 0
|
|
@@ -6664,7 +6675,7 @@ function validateColumnTypes(schema, tableName, expectedTypes) {
|
|
|
6664
6675
|
);
|
|
6665
6676
|
}
|
|
6666
6677
|
}
|
|
6667
|
-
|
|
6678
|
+
logger14.debug("Column type validation", {
|
|
6668
6679
|
tableName,
|
|
6669
6680
|
typeChecks: Object.keys(expectedTypes).length,
|
|
6670
6681
|
valid: errors.length === 0
|
|
@@ -6684,7 +6695,7 @@ function findTable(schema, tableName) {
|
|
|
6684
6695
|
function formatTableName(table) {
|
|
6685
6696
|
return table.schema ? `${table.schema}.${table.name}` : table.name;
|
|
6686
6697
|
}
|
|
6687
|
-
var
|
|
6698
|
+
var logger15 = createLogger("agentforge:tools:data:relational:type-mapper");
|
|
6688
6699
|
var POSTGRES_TYPE_MAP = {
|
|
6689
6700
|
// Numeric
|
|
6690
6701
|
smallint: "number",
|
|
@@ -6850,7 +6861,7 @@ function mapColumnType(vendor, dbType, nullable = false) {
|
|
|
6850
6861
|
const result = { tsType, nullable, dbType };
|
|
6851
6862
|
if (tsType === "unknown" && normalised !== "json" && normalised !== "jsonb") {
|
|
6852
6863
|
result.notes = `No explicit mapping for "${dbType}"; defaulting to unknown`;
|
|
6853
|
-
|
|
6864
|
+
logger15.debug("Unmapped database type", { vendor, dbType, normalised });
|
|
6854
6865
|
}
|
|
6855
6866
|
if ((normalised === "bigint" || normalised === "int8" || normalised === "bigserial") && (vendor === "postgresql" || vendor === "mysql")) {
|
|
6856
6867
|
result.notes = "Mapped to string to avoid JavaScript number precision loss for 64-bit integers";
|
|
@@ -6865,7 +6876,7 @@ function mapSchemaTypes(vendor, columns) {
|
|
|
6865
6876
|
}
|
|
6866
6877
|
result.get(col.table).set(col.name, mapColumnType(vendor, col.type, col.nullable));
|
|
6867
6878
|
}
|
|
6868
|
-
|
|
6879
|
+
logger15.debug("Schema type mapping complete", {
|
|
6869
6880
|
vendor,
|
|
6870
6881
|
tables: result.size,
|
|
6871
6882
|
columns: columns.length
|
|
@@ -6882,7 +6893,7 @@ function normaliseDbType(raw) {
|
|
|
6882
6893
|
type = type.replace(/\s+unsigned$/, "");
|
|
6883
6894
|
return type.trim();
|
|
6884
6895
|
}
|
|
6885
|
-
var
|
|
6896
|
+
var logger16 = createLogger("agentforge:tools:data:relational:schema-diff");
|
|
6886
6897
|
function diffSchemas(before, after) {
|
|
6887
6898
|
const tableDiffs = [];
|
|
6888
6899
|
let columnsAdded = 0;
|
|
@@ -6922,7 +6933,7 @@ function diffSchemas(before, after) {
|
|
|
6922
6933
|
const tablesRemoved = tableDiffs.filter((d) => d.type === "removed").length;
|
|
6923
6934
|
const tablesChanged = tableDiffs.filter((d) => d.type === "changed").length;
|
|
6924
6935
|
const identical = tableDiffs.length === 0;
|
|
6925
|
-
|
|
6936
|
+
logger16.debug("Schema diff computed", {
|
|
6926
6937
|
identical,
|
|
6927
6938
|
tablesAdded,
|
|
6928
6939
|
tablesRemoved,
|
|
@@ -6966,7 +6977,7 @@ function importSchemaFromJson(json) {
|
|
|
6966
6977
|
throw new Error(`Invalid schema JSON: table "${table.name}" missing "primaryKey" array`);
|
|
6967
6978
|
}
|
|
6968
6979
|
}
|
|
6969
|
-
|
|
6980
|
+
logger16.debug("Schema imported from JSON", {
|
|
6970
6981
|
vendor: obj.vendor,
|
|
6971
6982
|
tableCount: obj.tables.length
|
|
6972
6983
|
});
|
|
@@ -7263,7 +7274,7 @@ function isSafeValidationError(error) {
|
|
|
7263
7274
|
}
|
|
7264
7275
|
|
|
7265
7276
|
// src/data/relational/tools/relational-select/executor.ts
|
|
7266
|
-
var
|
|
7277
|
+
var logger17 = createLogger("agentforge:tools:data:relational:select");
|
|
7267
7278
|
function toSelectQueryInput(input) {
|
|
7268
7279
|
return {
|
|
7269
7280
|
table: input.table,
|
|
@@ -7277,7 +7288,7 @@ function toSelectQueryInput(input) {
|
|
|
7277
7288
|
}
|
|
7278
7289
|
async function executeSelect(manager, input, context) {
|
|
7279
7290
|
const startTime = Date.now();
|
|
7280
|
-
|
|
7291
|
+
logger17.debug("Building SELECT query", {
|
|
7281
7292
|
vendor: input.vendor,
|
|
7282
7293
|
table: input.table,
|
|
7283
7294
|
hasWhere: !!input.where,
|
|
@@ -7295,7 +7306,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7295
7306
|
};
|
|
7296
7307
|
const streamInput = toSelectQueryInput(input);
|
|
7297
7308
|
if (input.streaming.benchmark) {
|
|
7298
|
-
|
|
7309
|
+
logger17.warn("Streaming benchmark enabled; SELECT will execute up to three times (result + benchmark regular + benchmark streaming).", {
|
|
7299
7310
|
vendor: input.vendor,
|
|
7300
7311
|
table: input.table,
|
|
7301
7312
|
chunkSize: streamOptions.chunkSize ?? DEFAULT_CHUNK_SIZE,
|
|
@@ -7306,7 +7317,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7306
7317
|
const streamResult = await executeStreamingSelect(executor, streamInput, streamOptions);
|
|
7307
7318
|
const benchmark = input.streaming.benchmark ? await benchmarkStreamingSelectMemory(executor, streamInput, streamOptions) : void 0;
|
|
7308
7319
|
const executionTime2 = Date.now() - startTime;
|
|
7309
|
-
|
|
7320
|
+
logger17.debug("Streaming SELECT query executed successfully", {
|
|
7310
7321
|
vendor: input.vendor,
|
|
7311
7322
|
table: input.table,
|
|
7312
7323
|
rowCount: streamResult.rowCount,
|
|
@@ -7335,7 +7346,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7335
7346
|
const executionTime = Date.now() - startTime;
|
|
7336
7347
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
7337
7348
|
const rowCount = rows.length;
|
|
7338
|
-
|
|
7349
|
+
logger17.debug("SELECT query executed successfully", {
|
|
7339
7350
|
vendor: input.vendor,
|
|
7340
7351
|
table: input.table,
|
|
7341
7352
|
rowCount,
|
|
@@ -7348,7 +7359,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7348
7359
|
};
|
|
7349
7360
|
} catch (error) {
|
|
7350
7361
|
const executionTime = Date.now() - startTime;
|
|
7351
|
-
|
|
7362
|
+
logger17.error("SELECT query execution failed", {
|
|
7352
7363
|
vendor: input.vendor,
|
|
7353
7364
|
table: input.table,
|
|
7354
7365
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -7524,7 +7535,7 @@ function isSafeInsertError(error) {
|
|
|
7524
7535
|
}
|
|
7525
7536
|
|
|
7526
7537
|
// src/data/relational/tools/relational-insert/executor.ts
|
|
7527
|
-
var
|
|
7538
|
+
var logger18 = createLogger("agentforge:tools:data:relational:insert");
|
|
7528
7539
|
function toNumber(value) {
|
|
7529
7540
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7530
7541
|
}
|
|
@@ -7673,7 +7684,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7673
7684
|
maxRetries: options.maxRetries,
|
|
7674
7685
|
retryDelayMs: options.retryDelayMs,
|
|
7675
7686
|
onProgress: (progress) => {
|
|
7676
|
-
|
|
7687
|
+
logger18.debug("INSERT batch progress", {
|
|
7677
7688
|
vendor: input.vendor,
|
|
7678
7689
|
table: input.table,
|
|
7679
7690
|
...progress
|
|
@@ -7686,7 +7697,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7686
7697
|
const insertedIds = batchResult.results.flatMap((result) => result.insertedIds);
|
|
7687
7698
|
let benchmark;
|
|
7688
7699
|
if (options.benchmark) {
|
|
7689
|
-
|
|
7700
|
+
logger18.warn("INSERT batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
7690
7701
|
vendor: input.vendor,
|
|
7691
7702
|
table: input.table,
|
|
7692
7703
|
totalRows: input.data.length,
|
|
@@ -7723,7 +7734,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7723
7734
|
}
|
|
7724
7735
|
async function executeInsert(manager, input, context) {
|
|
7725
7736
|
const startTime = Date.now();
|
|
7726
|
-
|
|
7737
|
+
logger18.debug("Building INSERT query", {
|
|
7727
7738
|
vendor: input.vendor,
|
|
7728
7739
|
table: input.table,
|
|
7729
7740
|
isBatch: Array.isArray(input.data),
|
|
@@ -7739,7 +7750,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7739
7750
|
batchOptions
|
|
7740
7751
|
) : await executeInsertOnce(manager, input, context);
|
|
7741
7752
|
const executionTime = Date.now() - startTime;
|
|
7742
|
-
|
|
7753
|
+
logger18.debug("INSERT query executed successfully", {
|
|
7743
7754
|
vendor: input.vendor,
|
|
7744
7755
|
table: input.table,
|
|
7745
7756
|
rowCount: result.rowCount,
|
|
@@ -7755,7 +7766,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7755
7766
|
};
|
|
7756
7767
|
} catch (error) {
|
|
7757
7768
|
const executionTime = Date.now() - startTime;
|
|
7758
|
-
|
|
7769
|
+
logger18.error("INSERT query execution failed", {
|
|
7759
7770
|
vendor: input.vendor,
|
|
7760
7771
|
table: input.table,
|
|
7761
7772
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8085,7 +8096,7 @@ function isSafeUpdateError(error) {
|
|
|
8085
8096
|
}
|
|
8086
8097
|
|
|
8087
8098
|
// src/data/relational/tools/relational-update/executor.ts
|
|
8088
|
-
var
|
|
8099
|
+
var logger19 = createLogger("agentforge:tools:data:relational:update");
|
|
8089
8100
|
function toNumber2(value) {
|
|
8090
8101
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8091
8102
|
}
|
|
@@ -8106,7 +8117,7 @@ function normalizeAffectedRows(result) {
|
|
|
8106
8117
|
}
|
|
8107
8118
|
return 0;
|
|
8108
8119
|
}
|
|
8109
|
-
function
|
|
8120
|
+
function toErrorMessage(error) {
|
|
8110
8121
|
return error instanceof Error ? error.message : String(error);
|
|
8111
8122
|
}
|
|
8112
8123
|
function resolveBatchOptions2(batch) {
|
|
@@ -8188,7 +8199,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8188
8199
|
batchIndex,
|
|
8189
8200
|
batchSize: operations.length,
|
|
8190
8201
|
attempts: 1,
|
|
8191
|
-
error:
|
|
8202
|
+
error: toErrorMessage(error)
|
|
8192
8203
|
});
|
|
8193
8204
|
}
|
|
8194
8205
|
}
|
|
@@ -8207,7 +8218,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8207
8218
|
maxRetries: options.maxRetries,
|
|
8208
8219
|
retryDelayMs: options.retryDelayMs,
|
|
8209
8220
|
onProgress: (progress) => {
|
|
8210
|
-
|
|
8221
|
+
logger19.debug("UPDATE batch progress", {
|
|
8211
8222
|
vendor: input.vendor,
|
|
8212
8223
|
table: input.table,
|
|
8213
8224
|
...progress
|
|
@@ -8219,7 +8230,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8219
8230
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8220
8231
|
let benchmark;
|
|
8221
8232
|
if (options.benchmark) {
|
|
8222
|
-
|
|
8233
|
+
logger19.warn("UPDATE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8223
8234
|
vendor: input.vendor,
|
|
8224
8235
|
table: input.table,
|
|
8225
8236
|
operationCount: input.operations.length,
|
|
@@ -8254,7 +8265,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8254
8265
|
}
|
|
8255
8266
|
async function executeUpdate(manager, input, context) {
|
|
8256
8267
|
const startTime = Date.now();
|
|
8257
|
-
|
|
8268
|
+
logger19.debug("Building UPDATE query", {
|
|
8258
8269
|
vendor: input.vendor,
|
|
8259
8270
|
table: input.table,
|
|
8260
8271
|
hasWhere: !!input.where?.length,
|
|
@@ -8272,7 +8283,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8272
8283
|
batchOptions
|
|
8273
8284
|
) : await executeSingleUpdate(manager, input, toSingleUpdateOperation(input), context);
|
|
8274
8285
|
const executionTime = Date.now() - startTime;
|
|
8275
|
-
|
|
8286
|
+
logger19.debug("UPDATE query executed successfully", {
|
|
8276
8287
|
vendor: input.vendor,
|
|
8277
8288
|
table: input.table,
|
|
8278
8289
|
rowCount: result.rowCount,
|
|
@@ -8286,7 +8297,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8286
8297
|
};
|
|
8287
8298
|
} catch (error) {
|
|
8288
8299
|
const executionTime = Date.now() - startTime;
|
|
8289
|
-
|
|
8300
|
+
logger19.error("UPDATE query execution failed", {
|
|
8290
8301
|
vendor: input.vendor,
|
|
8291
8302
|
table: input.table,
|
|
8292
8303
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8590,7 +8601,7 @@ function isSafeDeleteError(error) {
|
|
|
8590
8601
|
}
|
|
8591
8602
|
|
|
8592
8603
|
// src/data/relational/tools/relational-delete/executor.ts
|
|
8593
|
-
var
|
|
8604
|
+
var logger20 = createLogger("agentforge:tools:data:relational:delete");
|
|
8594
8605
|
function toNumber3(value) {
|
|
8595
8606
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8596
8607
|
}
|
|
@@ -8611,7 +8622,7 @@ function normalizeAffectedRows2(result) {
|
|
|
8611
8622
|
}
|
|
8612
8623
|
return 0;
|
|
8613
8624
|
}
|
|
8614
|
-
function
|
|
8625
|
+
function toErrorMessage2(error) {
|
|
8615
8626
|
return error instanceof Error ? error.message : String(error);
|
|
8616
8627
|
}
|
|
8617
8628
|
function resolveBatchOptions3(batch) {
|
|
@@ -8691,7 +8702,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8691
8702
|
batchIndex,
|
|
8692
8703
|
batchSize: operations.length,
|
|
8693
8704
|
attempts: 1,
|
|
8694
|
-
error:
|
|
8705
|
+
error: toErrorMessage2(error)
|
|
8695
8706
|
});
|
|
8696
8707
|
}
|
|
8697
8708
|
}
|
|
@@ -8711,7 +8722,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8711
8722
|
maxRetries: options.maxRetries,
|
|
8712
8723
|
retryDelayMs: options.retryDelayMs,
|
|
8713
8724
|
onProgress: (progress) => {
|
|
8714
|
-
|
|
8725
|
+
logger20.debug("DELETE batch progress", {
|
|
8715
8726
|
vendor: input.vendor,
|
|
8716
8727
|
table: input.table,
|
|
8717
8728
|
...progress
|
|
@@ -8724,7 +8735,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8724
8735
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8725
8736
|
let benchmark;
|
|
8726
8737
|
if (options.benchmark) {
|
|
8727
|
-
|
|
8738
|
+
logger20.warn("DELETE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8728
8739
|
vendor: input.vendor,
|
|
8729
8740
|
table: input.table,
|
|
8730
8741
|
operationCount: input.operations.length,
|
|
@@ -8760,7 +8771,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8760
8771
|
}
|
|
8761
8772
|
async function executeDelete(manager, input, context) {
|
|
8762
8773
|
const startTime = Date.now();
|
|
8763
|
-
|
|
8774
|
+
logger20.debug("Building DELETE query", {
|
|
8764
8775
|
vendor: input.vendor,
|
|
8765
8776
|
table: input.table,
|
|
8766
8777
|
hasWhere: !!input.where?.length,
|
|
@@ -8779,7 +8790,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8779
8790
|
batchOptions
|
|
8780
8791
|
) : await executeSingleDelete(manager, input, toSingleDeleteOperation(input), context);
|
|
8781
8792
|
const executionTime = Date.now() - startTime;
|
|
8782
|
-
|
|
8793
|
+
logger20.debug("DELETE query executed successfully", {
|
|
8783
8794
|
vendor: input.vendor,
|
|
8784
8795
|
table: input.table,
|
|
8785
8796
|
rowCount: result.rowCount,
|
|
@@ -8795,7 +8806,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8795
8806
|
};
|
|
8796
8807
|
} catch (error) {
|
|
8797
8808
|
const executionTime = Date.now() - startTime;
|
|
8798
|
-
|
|
8809
|
+
logger20.error("DELETE query execution failed", {
|
|
8799
8810
|
vendor: input.vendor,
|
|
8800
8811
|
table: input.table,
|
|
8801
8812
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8900,7 +8911,7 @@ function isSafeGetSchemaValidationError(error) {
|
|
|
8900
8911
|
}
|
|
8901
8912
|
|
|
8902
8913
|
// src/data/relational/tools/relational-get-schema.ts
|
|
8903
|
-
var
|
|
8914
|
+
var logger21 = createLogger("agentforge:tools:data:relational:get-schema");
|
|
8904
8915
|
function buildSchemaCacheKey(vendor, connectionString, database) {
|
|
8905
8916
|
const databaseScope = database ?? "default";
|
|
8906
8917
|
const connectionHash = createHash("sha256").update(connectionString).digest("hex");
|
|
@@ -8972,7 +8983,7 @@ var relationalGetSchema = toolBuilder().name("relational-get-schema").displayNam
|
|
|
8972
8983
|
summary
|
|
8973
8984
|
};
|
|
8974
8985
|
} catch (error) {
|
|
8975
|
-
|
|
8986
|
+
logger21.error("Schema introspection failed", {
|
|
8976
8987
|
vendor: input.vendor,
|
|
8977
8988
|
hasTablesFilter: Array.isArray(input.tables),
|
|
8978
8989
|
tablesFilterCount: input.tables?.length ?? 0,
|
|
@@ -10138,7 +10149,7 @@ var AskHumanInputSchema = z.object({
|
|
|
10138
10149
|
suggestions: z.array(z.string()).optional().describe("Suggested responses for the human")
|
|
10139
10150
|
});
|
|
10140
10151
|
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
|
|
10141
|
-
var
|
|
10152
|
+
var logger22 = createLogger("agentforge:tools:agent:ask-human", { level: logLevel3 });
|
|
10142
10153
|
function isRecord2(value) {
|
|
10143
10154
|
return typeof value === "object" && value !== null;
|
|
10144
10155
|
}
|
|
@@ -10203,7 +10214,7 @@ function createAskHumanTool() {
|
|
|
10203
10214
|
suggestions: validatedInput.suggestions,
|
|
10204
10215
|
status: "pending"
|
|
10205
10216
|
};
|
|
10206
|
-
|
|
10217
|
+
logger22.debug("About to call interrupt()", {
|
|
10207
10218
|
humanRequest: {
|
|
10208
10219
|
id: humanRequest.id,
|
|
10209
10220
|
question: humanRequest.question,
|
|
@@ -10219,13 +10230,13 @@ function createAskHumanTool() {
|
|
|
10219
10230
|
let response;
|
|
10220
10231
|
try {
|
|
10221
10232
|
response = interrupt(humanRequest);
|
|
10222
|
-
|
|
10233
|
+
logger22.debug("interrupt() returned successfully", {
|
|
10223
10234
|
responseType: typeof response,
|
|
10224
10235
|
hasResponse: response != null,
|
|
10225
10236
|
...typeof response === "string" ? { responseLength: response.length } : {}
|
|
10226
10237
|
});
|
|
10227
10238
|
} catch (error) {
|
|
10228
|
-
|
|
10239
|
+
logger22.debug("interrupt() threw error (expected for GraphInterrupt)", {
|
|
10229
10240
|
...error && typeof error === "object" && "constructor" in error ? { errorType: error.constructor?.name } : {},
|
|
10230
10241
|
error: error instanceof Error ? error.message : String(error)
|
|
10231
10242
|
});
|