@agentforge/tools 0.16.13 → 0.16.15
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 +409 -341
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -38
- package/dist/index.d.ts +15 -38
- package/dist/index.js +409 -341
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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, logger22) {
|
|
|
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
|
|
@@ -4017,7 +4017,8 @@ function quoteQualifiedIdentifier(qualifiedName, vendor) {
|
|
|
4017
4017
|
const parts = qualifiedName.split(".");
|
|
4018
4018
|
return parts.map((part) => quoteIdentifier(part, vendor)).join(".");
|
|
4019
4019
|
}
|
|
4020
|
-
|
|
4020
|
+
|
|
4021
|
+
// src/data/relational/connection/lifecycle.ts
|
|
4021
4022
|
var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
4022
4023
|
ConnectionState2["DISCONNECTED"] = "disconnected";
|
|
4023
4024
|
ConnectionState2["CONNECTING"] = "connecting";
|
|
@@ -4026,6 +4027,92 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
|
4026
4027
|
ConnectionState2["ERROR"] = "error";
|
|
4027
4028
|
return ConnectionState2;
|
|
4028
4029
|
})(ConnectionState || {});
|
|
4030
|
+
function cancelPendingReconnection(timer, logger23, vendor, message) {
|
|
4031
|
+
if (!timer) {
|
|
4032
|
+
return null;
|
|
4033
|
+
}
|
|
4034
|
+
logger23.debug(message, { vendor });
|
|
4035
|
+
clearTimeout(timer);
|
|
4036
|
+
return null;
|
|
4037
|
+
}
|
|
4038
|
+
async function waitForInFlightConnection(promise, logger23, vendor, phase) {
|
|
4039
|
+
if (!promise) {
|
|
4040
|
+
return null;
|
|
4041
|
+
}
|
|
4042
|
+
logger23.debug(`Waiting for in-flight connection attempt to complete before ${phase}`, {
|
|
4043
|
+
vendor
|
|
4044
|
+
});
|
|
4045
|
+
try {
|
|
4046
|
+
await promise;
|
|
4047
|
+
} catch {
|
|
4048
|
+
}
|
|
4049
|
+
return null;
|
|
4050
|
+
}
|
|
4051
|
+
function shutdownClient(vendor, client) {
|
|
4052
|
+
if (vendor === "postgresql" || vendor === "mysql") {
|
|
4053
|
+
return client.end();
|
|
4054
|
+
}
|
|
4055
|
+
if (vendor === "sqlite") {
|
|
4056
|
+
client.close();
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
function scheduleReconnection(context, logger23) {
|
|
4060
|
+
if (context.reconnectionConfig.maxAttempts > 0 && context.reconnectionAttempts >= context.reconnectionConfig.maxAttempts) {
|
|
4061
|
+
logger23.error("Max reconnection attempts reached", {
|
|
4062
|
+
vendor: context.vendor,
|
|
4063
|
+
attempts: context.reconnectionAttempts,
|
|
4064
|
+
maxAttempts: context.reconnectionConfig.maxAttempts
|
|
4065
|
+
});
|
|
4066
|
+
return;
|
|
4067
|
+
}
|
|
4068
|
+
const delay2 = Math.min(
|
|
4069
|
+
context.reconnectionConfig.baseDelayMs * Math.pow(2, context.reconnectionAttempts),
|
|
4070
|
+
context.reconnectionConfig.maxDelayMs
|
|
4071
|
+
);
|
|
4072
|
+
const nextAttempt = context.reconnectionAttempts + 1;
|
|
4073
|
+
context.setReconnectionAttempts(nextAttempt);
|
|
4074
|
+
context.setState("reconnecting" /* RECONNECTING */);
|
|
4075
|
+
logger23.info("Scheduling reconnection attempt", {
|
|
4076
|
+
vendor: context.vendor,
|
|
4077
|
+
attempt: nextAttempt,
|
|
4078
|
+
maxAttempts: context.reconnectionConfig.maxAttempts,
|
|
4079
|
+
delayMs: delay2
|
|
4080
|
+
});
|
|
4081
|
+
context.emitReconnecting({
|
|
4082
|
+
attempt: nextAttempt,
|
|
4083
|
+
maxAttempts: context.reconnectionConfig.maxAttempts,
|
|
4084
|
+
delayMs: delay2
|
|
4085
|
+
});
|
|
4086
|
+
const timer = setTimeout(async () => {
|
|
4087
|
+
context.setReconnectionTimer(null);
|
|
4088
|
+
try {
|
|
4089
|
+
logger23.info("Attempting reconnection", {
|
|
4090
|
+
vendor: context.vendor,
|
|
4091
|
+
attempt: nextAttempt
|
|
4092
|
+
});
|
|
4093
|
+
const promise = context.initialize().finally(() => {
|
|
4094
|
+
context.setConnectPromise(null);
|
|
4095
|
+
});
|
|
4096
|
+
context.setConnectPromise(promise);
|
|
4097
|
+
await promise;
|
|
4098
|
+
} catch (error) {
|
|
4099
|
+
logger23.error("Reconnection attempt failed", {
|
|
4100
|
+
vendor: context.vendor,
|
|
4101
|
+
attempt: nextAttempt,
|
|
4102
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4103
|
+
});
|
|
4104
|
+
}
|
|
4105
|
+
}, delay2);
|
|
4106
|
+
context.setReconnectionTimer(timer);
|
|
4107
|
+
}
|
|
4108
|
+
var logger7 = createLogger("agentforge:tools:data:relational:connection:vendor-init");
|
|
4109
|
+
var SAFE_INITIALIZATION_PATTERNS = [
|
|
4110
|
+
"Pool max connections must be",
|
|
4111
|
+
"Pool acquire timeout must be",
|
|
4112
|
+
"Pool idle timeout must be",
|
|
4113
|
+
"SQLite connection requires a url property",
|
|
4114
|
+
"Unsupported database vendor"
|
|
4115
|
+
];
|
|
4029
4116
|
function validatePoolConfig(poolConfig) {
|
|
4030
4117
|
if (poolConfig.max !== void 0 && poolConfig.max < 1) {
|
|
4031
4118
|
throw new Error("Pool max connections must be >= 1");
|
|
@@ -4037,13 +4124,142 @@ function validatePoolConfig(poolConfig) {
|
|
|
4037
4124
|
throw new Error("Pool idle timeout must be >= 0");
|
|
4038
4125
|
}
|
|
4039
4126
|
}
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4127
|
+
function pickConfiguredPoolFields(fields) {
|
|
4128
|
+
const configuredEntries = Object.entries(fields).filter(
|
|
4129
|
+
(entry) => entry[1] !== void 0
|
|
4130
|
+
);
|
|
4131
|
+
return Object.fromEntries(configuredEntries);
|
|
4132
|
+
}
|
|
4133
|
+
function normalizePostgreSQLConfig(connection) {
|
|
4134
|
+
const { pool: poolConfig, ...baseConfig } = typeof connection === "string" ? { connectionString: connection } : connection;
|
|
4135
|
+
if (poolConfig) {
|
|
4136
|
+
validatePoolConfig(poolConfig);
|
|
4137
|
+
}
|
|
4138
|
+
return {
|
|
4139
|
+
poolConfig,
|
|
4140
|
+
connectionConfig: {
|
|
4141
|
+
...baseConfig,
|
|
4142
|
+
...poolConfig?.max !== void 0 && { max: poolConfig.max },
|
|
4143
|
+
...poolConfig?.idleTimeoutMillis !== void 0 && {
|
|
4144
|
+
idleTimeoutMillis: poolConfig.idleTimeoutMillis
|
|
4145
|
+
},
|
|
4146
|
+
...poolConfig?.acquireTimeoutMillis !== void 0 && {
|
|
4147
|
+
connectionTimeoutMillis: poolConfig.acquireTimeoutMillis
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
};
|
|
4151
|
+
}
|
|
4152
|
+
function normalizeMySQLConfig(connection) {
|
|
4153
|
+
if (typeof connection === "string") {
|
|
4154
|
+
logger7.debug("Creating MySQL connection pool from connection string", {
|
|
4155
|
+
vendor: "mysql"
|
|
4156
|
+
});
|
|
4157
|
+
return connection;
|
|
4158
|
+
}
|
|
4159
|
+
const { pool: poolConfig, ...baseConfig } = connection;
|
|
4160
|
+
if (poolConfig) {
|
|
4161
|
+
validatePoolConfig(poolConfig);
|
|
4162
|
+
}
|
|
4163
|
+
return {
|
|
4164
|
+
...baseConfig,
|
|
4165
|
+
...poolConfig?.max !== void 0 && { connectionLimit: poolConfig.max },
|
|
4166
|
+
...poolConfig?.acquireTimeoutMillis !== void 0 && {
|
|
4167
|
+
acquireTimeout: poolConfig.acquireTimeoutMillis
|
|
4168
|
+
},
|
|
4169
|
+
...poolConfig?.idleTimeoutMillis !== void 0 && {
|
|
4170
|
+
idleTimeout: poolConfig.idleTimeoutMillis
|
|
4171
|
+
}
|
|
4172
|
+
};
|
|
4173
|
+
}
|
|
4174
|
+
function resolveSqliteUrl(connection) {
|
|
4175
|
+
if (typeof connection === "string") {
|
|
4176
|
+
return { url: connection };
|
|
4177
|
+
}
|
|
4178
|
+
const { url, pool } = connection;
|
|
4179
|
+
if (!url) {
|
|
4180
|
+
throw new Error("SQLite connection requires a url property");
|
|
4181
|
+
}
|
|
4182
|
+
if (pool) {
|
|
4183
|
+
validatePoolConfig(pool);
|
|
4184
|
+
}
|
|
4185
|
+
return { url, poolConfig: pool };
|
|
4186
|
+
}
|
|
4187
|
+
async function initializeVendorConnection(config) {
|
|
4188
|
+
switch (config.vendor) {
|
|
4189
|
+
case "postgresql":
|
|
4190
|
+
return initializePostgreSQLConnection(config.connection);
|
|
4191
|
+
case "mysql":
|
|
4192
|
+
return initializeMySQLConnection(config.connection);
|
|
4193
|
+
case "sqlite":
|
|
4194
|
+
return initializeSQLiteConnection(config.connection);
|
|
4195
|
+
default:
|
|
4196
|
+
throw new Error(`Unsupported database vendor: ${config.vendor}`);
|
|
4197
|
+
}
|
|
4198
|
+
}
|
|
4199
|
+
async function initializePostgreSQLConnection(connection) {
|
|
4200
|
+
const { drizzle } = await import('drizzle-orm/node-postgres');
|
|
4201
|
+
const { Pool } = await import('pg');
|
|
4202
|
+
const { connectionConfig } = normalizePostgreSQLConfig(connection);
|
|
4203
|
+
logger7.debug("Creating PostgreSQL connection pool", {
|
|
4204
|
+
vendor: "postgresql",
|
|
4205
|
+
poolConfig: pickConfiguredPoolFields({
|
|
4206
|
+
max: connectionConfig.max,
|
|
4207
|
+
idleTimeoutMillis: connectionConfig.idleTimeoutMillis,
|
|
4208
|
+
connectionTimeoutMillis: connectionConfig.connectionTimeoutMillis
|
|
4209
|
+
})
|
|
4210
|
+
});
|
|
4211
|
+
const client = new Pool(connectionConfig);
|
|
4212
|
+
const db = drizzle({ client });
|
|
4213
|
+
return { client, db };
|
|
4214
|
+
}
|
|
4215
|
+
async function initializeMySQLConnection(connection) {
|
|
4216
|
+
const { drizzle } = await import('drizzle-orm/mysql2');
|
|
4217
|
+
const mysql = await import('mysql2/promise');
|
|
4218
|
+
const connectionConfig = normalizeMySQLConfig(connection);
|
|
4219
|
+
if (typeof connectionConfig !== "string") {
|
|
4220
|
+
logger7.debug("Creating MySQL connection pool", {
|
|
4221
|
+
vendor: "mysql",
|
|
4222
|
+
poolConfig: pickConfiguredPoolFields({
|
|
4223
|
+
connectionLimit: connectionConfig.connectionLimit,
|
|
4224
|
+
acquireTimeout: connectionConfig.acquireTimeout,
|
|
4225
|
+
idleTimeout: connectionConfig.idleTimeout
|
|
4226
|
+
})
|
|
4227
|
+
});
|
|
4228
|
+
}
|
|
4229
|
+
let client;
|
|
4230
|
+
if (typeof connectionConfig === "string") {
|
|
4231
|
+
client = mysql.createPool(connectionConfig);
|
|
4232
|
+
} else {
|
|
4233
|
+
client = mysql.createPool(connectionConfig);
|
|
4234
|
+
}
|
|
4235
|
+
const db = drizzle({ client });
|
|
4236
|
+
return { client, db };
|
|
4237
|
+
}
|
|
4238
|
+
async function initializeSQLiteConnection(connection) {
|
|
4239
|
+
const { drizzle } = await import('drizzle-orm/better-sqlite3');
|
|
4240
|
+
const DatabaseModule = await import('better-sqlite3');
|
|
4241
|
+
const Database = DatabaseModule.default;
|
|
4242
|
+
const { url, poolConfig } = resolveSqliteUrl(connection);
|
|
4243
|
+
if (poolConfig) {
|
|
4244
|
+
logger7.debug("SQLite pool configuration provided but not applied (SQLite uses single connection)", {
|
|
4245
|
+
vendor: "sqlite",
|
|
4246
|
+
poolConfig: pickConfiguredPoolFields({
|
|
4247
|
+
max: poolConfig.max,
|
|
4248
|
+
idleTimeoutMillis: poolConfig.idleTimeoutMillis,
|
|
4249
|
+
acquireTimeoutMillis: poolConfig.acquireTimeoutMillis
|
|
4250
|
+
})
|
|
4251
|
+
});
|
|
4252
|
+
}
|
|
4253
|
+
logger7.debug("Creating SQLite connection", {
|
|
4254
|
+
vendor: "sqlite",
|
|
4255
|
+
url: url === ":memory:" ? ":memory:" : "file"
|
|
4256
|
+
});
|
|
4257
|
+
const client = new Database(url);
|
|
4258
|
+
client.pragma("foreign_keys = ON");
|
|
4259
|
+
const db = drizzle({ client });
|
|
4260
|
+
return { client, db };
|
|
4261
|
+
}
|
|
4262
|
+
var logger8 = createLogger("agentforge:tools:data:relational:connection");
|
|
4047
4263
|
var ConnectionManager = class extends EventEmitter {
|
|
4048
4264
|
vendor;
|
|
4049
4265
|
db;
|
|
@@ -4083,23 +4299,22 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4083
4299
|
*/
|
|
4084
4300
|
async connect() {
|
|
4085
4301
|
if (this.state === "connected" /* CONNECTED */) {
|
|
4086
|
-
|
|
4302
|
+
logger8.debug("Already connected", { vendor: this.vendor });
|
|
4087
4303
|
return;
|
|
4088
4304
|
}
|
|
4089
4305
|
if (this.connectPromise) {
|
|
4090
|
-
|
|
4306
|
+
logger8.debug("Connection already in progress, waiting for completion", {
|
|
4091
4307
|
vendor: this.vendor,
|
|
4092
4308
|
state: this.state
|
|
4093
4309
|
});
|
|
4094
4310
|
return this.connectPromise;
|
|
4095
4311
|
}
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
}
|
|
4312
|
+
this.reconnectionTimer = cancelPendingReconnection(
|
|
4313
|
+
this.reconnectionTimer,
|
|
4314
|
+
logger8,
|
|
4315
|
+
this.vendor,
|
|
4316
|
+
"Clearing pending reconnection timer before manual connect"
|
|
4317
|
+
);
|
|
4103
4318
|
this.connectPromise = this.initialize().finally(() => {
|
|
4104
4319
|
this.connectPromise = null;
|
|
4105
4320
|
});
|
|
@@ -4114,21 +4329,19 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4114
4329
|
*/
|
|
4115
4330
|
async disconnect() {
|
|
4116
4331
|
this.connectionGeneration++;
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4332
|
+
this.reconnectionTimer = cancelPendingReconnection(
|
|
4333
|
+
this.reconnectionTimer,
|
|
4334
|
+
logger8,
|
|
4335
|
+
this.vendor,
|
|
4336
|
+
"Clearing pending reconnection timer before disconnect"
|
|
4337
|
+
);
|
|
4121
4338
|
this.reconnectionAttempts = 0;
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
} catch {
|
|
4129
|
-
}
|
|
4130
|
-
this.connectPromise = null;
|
|
4131
|
-
}
|
|
4339
|
+
this.connectPromise = await waitForInFlightConnection(
|
|
4340
|
+
this.connectPromise,
|
|
4341
|
+
logger8,
|
|
4342
|
+
this.vendor,
|
|
4343
|
+
"disconnect"
|
|
4344
|
+
);
|
|
4132
4345
|
await this.close();
|
|
4133
4346
|
}
|
|
4134
4347
|
/**
|
|
@@ -4173,7 +4386,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4173
4386
|
const startTime = Date.now();
|
|
4174
4387
|
const currentGeneration = this.connectionGeneration;
|
|
4175
4388
|
if (this.state === "connected" /* CONNECTED */ && this.client) {
|
|
4176
|
-
|
|
4389
|
+
logger8.warn("Re-initializing an already connected manager; emitting disconnected before cleanup", {
|
|
4177
4390
|
vendor: this.vendor
|
|
4178
4391
|
});
|
|
4179
4392
|
this.setState("disconnected" /* DISCONNECTED */);
|
|
@@ -4181,27 +4394,17 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4181
4394
|
await this.cleanupCancelledConnection();
|
|
4182
4395
|
}
|
|
4183
4396
|
this.setState("connecting" /* CONNECTING */);
|
|
4184
|
-
|
|
4397
|
+
logger8.info("Initializing database connection", {
|
|
4185
4398
|
vendor: this.vendor,
|
|
4186
4399
|
connectionType: typeof this.config.connection,
|
|
4187
4400
|
state: this.state
|
|
4188
4401
|
});
|
|
4189
4402
|
try {
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
break;
|
|
4194
|
-
case "mysql":
|
|
4195
|
-
await this.initializeMySQL();
|
|
4196
|
-
break;
|
|
4197
|
-
case "sqlite":
|
|
4198
|
-
await this.initializeSQLite();
|
|
4199
|
-
break;
|
|
4200
|
-
default:
|
|
4201
|
-
throw new Error(`Unsupported database vendor: ${this.vendor}`);
|
|
4202
|
-
}
|
|
4403
|
+
const initialized = await initializeVendorConnection(this.config);
|
|
4404
|
+
this.client = initialized.client;
|
|
4405
|
+
this.db = initialized.db;
|
|
4203
4406
|
if (currentGeneration !== this.connectionGeneration) {
|
|
4204
|
-
|
|
4407
|
+
logger8.debug("Connection cancelled during initialization", {
|
|
4205
4408
|
vendor: this.vendor,
|
|
4206
4409
|
currentGeneration,
|
|
4207
4410
|
newGeneration: this.connectionGeneration
|
|
@@ -4210,13 +4413,13 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4210
4413
|
this.setState("disconnected" /* DISCONNECTED */);
|
|
4211
4414
|
throw new Error("Connection cancelled during initialization");
|
|
4212
4415
|
}
|
|
4213
|
-
|
|
4416
|
+
logger8.debug("Validating connection health", { vendor: this.vendor });
|
|
4214
4417
|
const healthy = await this.isHealthy();
|
|
4215
4418
|
if (!healthy) {
|
|
4216
4419
|
throw new Error(`Failed to establish healthy connection to ${this.vendor} database`);
|
|
4217
4420
|
}
|
|
4218
4421
|
if (currentGeneration !== this.connectionGeneration) {
|
|
4219
|
-
|
|
4422
|
+
logger8.debug("Connection cancelled during health check", {
|
|
4220
4423
|
vendor: this.vendor,
|
|
4221
4424
|
currentGeneration,
|
|
4222
4425
|
newGeneration: this.connectionGeneration
|
|
@@ -4228,7 +4431,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4228
4431
|
this.setState("connected" /* CONNECTED */);
|
|
4229
4432
|
this.emit("connected");
|
|
4230
4433
|
this.reconnectionAttempts = 0;
|
|
4231
|
-
|
|
4434
|
+
logger8.info("Database connection initialized successfully", {
|
|
4232
4435
|
vendor: this.vendor,
|
|
4233
4436
|
duration: Date.now() - startTime,
|
|
4234
4437
|
state: this.state
|
|
@@ -4249,7 +4452,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4249
4452
|
if (this.listenerCount("error") > 0) {
|
|
4250
4453
|
this.emit("error", normalizedError);
|
|
4251
4454
|
}
|
|
4252
|
-
|
|
4455
|
+
logger8.error(errorMessage, {
|
|
4253
4456
|
vendor: this.vendor,
|
|
4254
4457
|
error: normalizedError.message,
|
|
4255
4458
|
duration: Date.now() - startTime,
|
|
@@ -4260,7 +4463,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4260
4463
|
this.scheduleReconnection();
|
|
4261
4464
|
}
|
|
4262
4465
|
} else {
|
|
4263
|
-
|
|
4466
|
+
logger8.debug("Connection initialization cancelled", {
|
|
4264
4467
|
vendor: this.vendor,
|
|
4265
4468
|
duration: Date.now() - startTime,
|
|
4266
4469
|
state: this.state
|
|
@@ -4281,7 +4484,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4281
4484
|
const oldState = this.state;
|
|
4282
4485
|
this.state = newState;
|
|
4283
4486
|
if (oldState !== newState) {
|
|
4284
|
-
|
|
4487
|
+
logger8.debug("Connection state changed", {
|
|
4285
4488
|
vendor: this.vendor,
|
|
4286
4489
|
oldState,
|
|
4287
4490
|
newState
|
|
@@ -4293,152 +4496,30 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4293
4496
|
* @private
|
|
4294
4497
|
*/
|
|
4295
4498
|
scheduleReconnection() {
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
vendor: this.vendor,
|
|
4299
|
-
attempts: this.reconnectionAttempts,
|
|
4300
|
-
maxAttempts: this.reconnectionConfig.maxAttempts
|
|
4301
|
-
});
|
|
4302
|
-
return;
|
|
4303
|
-
}
|
|
4304
|
-
const delay2 = Math.min(
|
|
4305
|
-
this.reconnectionConfig.baseDelayMs * Math.pow(2, this.reconnectionAttempts),
|
|
4306
|
-
this.reconnectionConfig.maxDelayMs
|
|
4307
|
-
);
|
|
4308
|
-
this.reconnectionAttempts++;
|
|
4309
|
-
this.setState("reconnecting" /* RECONNECTING */);
|
|
4310
|
-
logger7.info("Scheduling reconnection attempt", {
|
|
4311
|
-
vendor: this.vendor,
|
|
4312
|
-
attempt: this.reconnectionAttempts,
|
|
4313
|
-
maxAttempts: this.reconnectionConfig.maxAttempts,
|
|
4314
|
-
delayMs: delay2
|
|
4315
|
-
});
|
|
4316
|
-
this.emit("reconnecting", {
|
|
4317
|
-
attempt: this.reconnectionAttempts,
|
|
4318
|
-
maxAttempts: this.reconnectionConfig.maxAttempts,
|
|
4319
|
-
delayMs: delay2
|
|
4320
|
-
});
|
|
4321
|
-
this.reconnectionTimer = setTimeout(async () => {
|
|
4322
|
-
this.reconnectionTimer = null;
|
|
4323
|
-
try {
|
|
4324
|
-
logger7.info("Attempting reconnection", {
|
|
4325
|
-
vendor: this.vendor,
|
|
4326
|
-
attempt: this.reconnectionAttempts
|
|
4327
|
-
});
|
|
4328
|
-
this.connectPromise = this.initialize().finally(() => {
|
|
4329
|
-
this.connectPromise = null;
|
|
4330
|
-
});
|
|
4331
|
-
await this.connectPromise;
|
|
4332
|
-
} catch (error) {
|
|
4333
|
-
logger7.error("Reconnection attempt failed", {
|
|
4334
|
-
vendor: this.vendor,
|
|
4335
|
-
attempt: this.reconnectionAttempts,
|
|
4336
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4337
|
-
});
|
|
4338
|
-
}
|
|
4339
|
-
}, delay2);
|
|
4340
|
-
}
|
|
4341
|
-
/**
|
|
4342
|
-
* Initialize PostgreSQL connection using Drizzle ORM with node-postgres
|
|
4343
|
-
*
|
|
4344
|
-
* Applies pool configuration options to pg.Pool for connection management.
|
|
4345
|
-
*/
|
|
4346
|
-
async initializePostgreSQL() {
|
|
4347
|
-
const { drizzle } = await import('drizzle-orm/node-postgres');
|
|
4348
|
-
const { Pool } = await import('pg');
|
|
4349
|
-
const { pool: poolConfig, ...baseConfig } = typeof this.config.connection === "string" ? { connectionString: this.config.connection } : this.config.connection;
|
|
4350
|
-
if (poolConfig) {
|
|
4351
|
-
validatePoolConfig(poolConfig);
|
|
4352
|
-
}
|
|
4353
|
-
const connectionConfig = {
|
|
4354
|
-
...baseConfig,
|
|
4355
|
-
// Map our PoolConfig to pg.Pool options
|
|
4356
|
-
// Note: pg.Pool does not support a `min` option
|
|
4357
|
-
...poolConfig?.max !== void 0 && { max: poolConfig.max },
|
|
4358
|
-
...poolConfig?.idleTimeoutMillis !== void 0 && { idleTimeoutMillis: poolConfig.idleTimeoutMillis },
|
|
4359
|
-
...poolConfig?.acquireTimeoutMillis !== void 0 && { connectionTimeoutMillis: poolConfig.acquireTimeoutMillis }
|
|
4360
|
-
};
|
|
4361
|
-
logger7.debug("Creating PostgreSQL connection pool", {
|
|
4362
|
-
vendor: this.vendor,
|
|
4363
|
-
poolConfig: {
|
|
4364
|
-
...connectionConfig.max !== void 0 ? { max: connectionConfig.max } : {},
|
|
4365
|
-
...connectionConfig.idleTimeoutMillis !== void 0 ? { idleTimeoutMillis: connectionConfig.idleTimeoutMillis } : {},
|
|
4366
|
-
...connectionConfig.connectionTimeoutMillis !== void 0 ? { connectionTimeoutMillis: connectionConfig.connectionTimeoutMillis } : {}
|
|
4367
|
-
}
|
|
4368
|
-
});
|
|
4369
|
-
this.client = new Pool(connectionConfig);
|
|
4370
|
-
this.db = drizzle({ client: this.client });
|
|
4371
|
-
}
|
|
4372
|
-
/**
|
|
4373
|
-
* Initialize MySQL connection using Drizzle ORM with mysql2
|
|
4374
|
-
*
|
|
4375
|
-
* Applies pool configuration options to mysql2.createPool for connection management.
|
|
4376
|
-
*/
|
|
4377
|
-
async initializeMySQL() {
|
|
4378
|
-
const { drizzle } = await import('drizzle-orm/mysql2');
|
|
4379
|
-
const mysql = await import('mysql2/promise');
|
|
4380
|
-
let connectionConfig;
|
|
4381
|
-
if (typeof this.config.connection === "string") {
|
|
4382
|
-
connectionConfig = this.config.connection;
|
|
4383
|
-
logger7.debug("Creating MySQL connection pool from connection string", {
|
|
4384
|
-
vendor: this.vendor
|
|
4385
|
-
});
|
|
4386
|
-
} else {
|
|
4387
|
-
const { pool: poolConfig, ...baseConfig } = this.config.connection;
|
|
4388
|
-
if (poolConfig) {
|
|
4389
|
-
validatePoolConfig(poolConfig);
|
|
4390
|
-
}
|
|
4391
|
-
connectionConfig = {
|
|
4392
|
-
...baseConfig,
|
|
4393
|
-
// Map our PoolConfig to mysql2 pool options
|
|
4394
|
-
...poolConfig?.max !== void 0 && { connectionLimit: poolConfig.max },
|
|
4395
|
-
...poolConfig?.acquireTimeoutMillis !== void 0 && { acquireTimeout: poolConfig.acquireTimeoutMillis },
|
|
4396
|
-
...poolConfig?.idleTimeoutMillis !== void 0 && { idleTimeout: poolConfig.idleTimeoutMillis }
|
|
4397
|
-
};
|
|
4398
|
-
logger7.debug("Creating MySQL connection pool", {
|
|
4399
|
-
vendor: this.vendor,
|
|
4400
|
-
poolConfig: {
|
|
4401
|
-
...connectionConfig.connectionLimit !== void 0 ? { connectionLimit: connectionConfig.connectionLimit } : {},
|
|
4402
|
-
...connectionConfig.acquireTimeout !== void 0 ? { acquireTimeout: connectionConfig.acquireTimeout } : {},
|
|
4403
|
-
...connectionConfig.idleTimeout !== void 0 ? { idleTimeout: connectionConfig.idleTimeout } : {}
|
|
4404
|
-
}
|
|
4405
|
-
});
|
|
4406
|
-
}
|
|
4407
|
-
this.client = mysql.createPool(connectionConfig);
|
|
4408
|
-
this.db = drizzle({ client: this.client });
|
|
4409
|
-
}
|
|
4410
|
-
/**
|
|
4411
|
-
* Initialize SQLite connection using Drizzle ORM with better-sqlite3
|
|
4412
|
-
*
|
|
4413
|
-
* Note: SQLite uses a single connection. Pool configuration is logged but not applied
|
|
4414
|
-
* as SQLite handles concurrent access through its internal locking mechanism.
|
|
4415
|
-
*/
|
|
4416
|
-
async initializeSQLite() {
|
|
4417
|
-
const { drizzle } = await import('drizzle-orm/better-sqlite3');
|
|
4418
|
-
const DatabaseModule = await import('better-sqlite3');
|
|
4419
|
-
const Database = DatabaseModule.default;
|
|
4420
|
-
const url = typeof this.config.connection === "string" ? this.config.connection : this.config.connection.url;
|
|
4421
|
-
if (!url) {
|
|
4422
|
-
throw new Error("SQLite connection requires a url property");
|
|
4423
|
-
}
|
|
4424
|
-
if (typeof this.config.connection === "object" && this.config.connection.pool) {
|
|
4425
|
-
validatePoolConfig(this.config.connection.pool);
|
|
4426
|
-
logger7.debug("SQLite pool configuration provided but not applied (SQLite uses single connection)", {
|
|
4499
|
+
scheduleReconnection(
|
|
4500
|
+
{
|
|
4427
4501
|
vendor: this.vendor,
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4502
|
+
reconnectionConfig: this.reconnectionConfig,
|
|
4503
|
+
reconnectionAttempts: this.reconnectionAttempts,
|
|
4504
|
+
setReconnectionAttempts: (attempts) => {
|
|
4505
|
+
this.reconnectionAttempts = attempts;
|
|
4506
|
+
},
|
|
4507
|
+
setState: (state) => {
|
|
4508
|
+
this.setState(state);
|
|
4509
|
+
},
|
|
4510
|
+
emitReconnecting: (payload) => {
|
|
4511
|
+
this.emit("reconnecting", payload);
|
|
4512
|
+
},
|
|
4513
|
+
initialize: () => this.initialize(),
|
|
4514
|
+
setConnectPromise: (promise) => {
|
|
4515
|
+
this.connectPromise = promise;
|
|
4516
|
+
},
|
|
4517
|
+
setReconnectionTimer: (timer) => {
|
|
4518
|
+
this.reconnectionTimer = timer;
|
|
4432
4519
|
}
|
|
4433
|
-
}
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
vendor: this.vendor,
|
|
4437
|
-
url: url === ":memory:" ? ":memory:" : "file"
|
|
4438
|
-
});
|
|
4439
|
-
this.client = new Database(url);
|
|
4440
|
-
this.client.pragma("foreign_keys = ON");
|
|
4441
|
-
this.db = drizzle({ client: this.client });
|
|
4520
|
+
},
|
|
4521
|
+
logger8
|
|
4522
|
+
);
|
|
4442
4523
|
}
|
|
4443
4524
|
/**
|
|
4444
4525
|
* Determine whether an error thrown by drizzle-orm's better-sqlite3 adapter
|
|
@@ -4478,7 +4559,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4478
4559
|
if (!this.db) {
|
|
4479
4560
|
throw new Error("Database not initialized. Call initialize() first.");
|
|
4480
4561
|
}
|
|
4481
|
-
|
|
4562
|
+
logger8.debug("Executing SQL query", {
|
|
4482
4563
|
vendor: this.vendor
|
|
4483
4564
|
});
|
|
4484
4565
|
if (this.vendor === "sqlite") {
|
|
@@ -4608,42 +4689,33 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4608
4689
|
*/
|
|
4609
4690
|
async close() {
|
|
4610
4691
|
this.connectionGeneration++;
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
await this.connectPromise;
|
|
4624
|
-
} catch {
|
|
4625
|
-
}
|
|
4626
|
-
this.connectPromise = null;
|
|
4627
|
-
}
|
|
4692
|
+
this.reconnectionTimer = cancelPendingReconnection(
|
|
4693
|
+
this.reconnectionTimer,
|
|
4694
|
+
logger8,
|
|
4695
|
+
this.vendor,
|
|
4696
|
+
"Canceling pending reconnection timer during close"
|
|
4697
|
+
);
|
|
4698
|
+
this.connectPromise = await waitForInFlightConnection(
|
|
4699
|
+
this.connectPromise,
|
|
4700
|
+
logger8,
|
|
4701
|
+
this.vendor,
|
|
4702
|
+
"close"
|
|
4703
|
+
);
|
|
4628
4704
|
if (this.client) {
|
|
4629
|
-
|
|
4705
|
+
logger8.info("Closing database connection", {
|
|
4630
4706
|
vendor: this.vendor,
|
|
4631
4707
|
state: this.state
|
|
4632
4708
|
});
|
|
4633
4709
|
try {
|
|
4634
|
-
|
|
4635
|
-
await this.client.end();
|
|
4636
|
-
} else if (this.vendor === "sqlite") {
|
|
4637
|
-
this.client.close();
|
|
4638
|
-
}
|
|
4710
|
+
await shutdownClient(this.vendor, this.client);
|
|
4639
4711
|
this.setState("disconnected" /* DISCONNECTED */);
|
|
4640
4712
|
this.emit("disconnected");
|
|
4641
|
-
|
|
4713
|
+
logger8.debug("Database connection closed successfully", {
|
|
4642
4714
|
vendor: this.vendor,
|
|
4643
4715
|
state: this.state
|
|
4644
4716
|
});
|
|
4645
4717
|
} catch (error) {
|
|
4646
|
-
|
|
4718
|
+
logger8.error("Error closing database connection", {
|
|
4647
4719
|
vendor: this.vendor,
|
|
4648
4720
|
error: error instanceof Error ? error.message : String(error),
|
|
4649
4721
|
state: this.state
|
|
@@ -4668,17 +4740,13 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4668
4740
|
if (!this.client) {
|
|
4669
4741
|
return;
|
|
4670
4742
|
}
|
|
4671
|
-
|
|
4743
|
+
logger8.debug("Cleaning up cancelled connection", {
|
|
4672
4744
|
vendor: this.vendor
|
|
4673
4745
|
});
|
|
4674
4746
|
try {
|
|
4675
|
-
|
|
4676
|
-
await this.client.end();
|
|
4677
|
-
} else if (this.vendor === "sqlite") {
|
|
4678
|
-
this.client.close();
|
|
4679
|
-
}
|
|
4747
|
+
await shutdownClient(this.vendor, this.client);
|
|
4680
4748
|
} catch (error) {
|
|
4681
|
-
|
|
4749
|
+
logger8.debug("Error during cancelled connection cleanup", {
|
|
4682
4750
|
vendor: this.vendor,
|
|
4683
4751
|
error: error instanceof Error ? error.message : String(error)
|
|
4684
4752
|
});
|
|
@@ -4693,15 +4761,15 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4693
4761
|
*/
|
|
4694
4762
|
async isHealthy() {
|
|
4695
4763
|
if (!this.db || !this.client) {
|
|
4696
|
-
|
|
4764
|
+
logger8.debug("Health check failed: connection not initialized", { vendor: this.vendor });
|
|
4697
4765
|
return false;
|
|
4698
4766
|
}
|
|
4699
4767
|
try {
|
|
4700
4768
|
await this.execute(sql`SELECT 1`);
|
|
4701
|
-
|
|
4769
|
+
logger8.debug("Health check passed", { vendor: this.vendor });
|
|
4702
4770
|
return true;
|
|
4703
4771
|
} catch (error) {
|
|
4704
|
-
|
|
4772
|
+
logger8.debug("Health check failed", {
|
|
4705
4773
|
vendor: this.vendor,
|
|
4706
4774
|
error: error instanceof Error ? error.message : String(error)
|
|
4707
4775
|
});
|
|
@@ -4709,7 +4777,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4709
4777
|
}
|
|
4710
4778
|
}
|
|
4711
4779
|
};
|
|
4712
|
-
var
|
|
4780
|
+
var logger9 = createLogger("agentforge:tools:data:relational:query");
|
|
4713
4781
|
function buildParameterizedQuery(sqlString, params) {
|
|
4714
4782
|
if (!params) {
|
|
4715
4783
|
return sql.raw(sqlString);
|
|
@@ -4784,7 +4852,7 @@ function buildParameterizedQuery(sqlString, params) {
|
|
|
4784
4852
|
}
|
|
4785
4853
|
async function executeQuery(manager, input, context) {
|
|
4786
4854
|
const startTime = Date.now();
|
|
4787
|
-
|
|
4855
|
+
logger9.debug("Executing query", {
|
|
4788
4856
|
vendor: input.vendor,
|
|
4789
4857
|
hasParams: !!input.params,
|
|
4790
4858
|
paramCount: input.params ? Array.isArray(input.params) ? input.params.length : Object.keys(input.params).length : 0
|
|
@@ -4798,7 +4866,7 @@ async function executeQuery(manager, input, context) {
|
|
|
4798
4866
|
const executionTime = Date.now() - startTime;
|
|
4799
4867
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
4800
4868
|
const rowCount = result.rowCount || result.affectedRows || rows.length;
|
|
4801
|
-
|
|
4869
|
+
logger9.debug("Query executed successfully", {
|
|
4802
4870
|
vendor: input.vendor,
|
|
4803
4871
|
rowCount,
|
|
4804
4872
|
executionTime
|
|
@@ -4810,7 +4878,7 @@ async function executeQuery(manager, input, context) {
|
|
|
4810
4878
|
};
|
|
4811
4879
|
} catch (error) {
|
|
4812
4880
|
const executionTime = Date.now() - startTime;
|
|
4813
|
-
|
|
4881
|
+
logger9.error("Query execution failed", {
|
|
4814
4882
|
vendor: input.vendor,
|
|
4815
4883
|
error: error instanceof Error ? error.message : String(error),
|
|
4816
4884
|
executionTime
|
|
@@ -5234,7 +5302,7 @@ function buildSelectQuery(input) {
|
|
|
5234
5302
|
}
|
|
5235
5303
|
return query;
|
|
5236
5304
|
}
|
|
5237
|
-
var
|
|
5305
|
+
var logger10 = createLogger("agentforge:tools:data:relational:batch");
|
|
5238
5306
|
var DEFAULT_BATCH_SIZE = 100;
|
|
5239
5307
|
var MAX_BATCH_SIZE = 5e3;
|
|
5240
5308
|
var MAX_RETRY_ATTEMPTS = 5;
|
|
@@ -5285,7 +5353,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5285
5353
|
let successfulItems = 0;
|
|
5286
5354
|
let failedItems = 0;
|
|
5287
5355
|
let retries = 0;
|
|
5288
|
-
|
|
5356
|
+
logger10.debug("Starting batched execution", {
|
|
5289
5357
|
operation: task.operation,
|
|
5290
5358
|
totalItems: task.items.length,
|
|
5291
5359
|
totalBatches: batches.length,
|
|
@@ -5324,7 +5392,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5324
5392
|
lastError = error;
|
|
5325
5393
|
if (attempts <= resolved.maxRetries) {
|
|
5326
5394
|
retries += 1;
|
|
5327
|
-
|
|
5395
|
+
logger10.warn("Batch execution failed, retrying", {
|
|
5328
5396
|
operation: task.operation,
|
|
5329
5397
|
batchIndex,
|
|
5330
5398
|
attempts,
|
|
@@ -5363,7 +5431,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5363
5431
|
{ cause: lastError }
|
|
5364
5432
|
);
|
|
5365
5433
|
}
|
|
5366
|
-
|
|
5434
|
+
logger10.warn("Batch execution failed and was recorded for partial success", {
|
|
5367
5435
|
operation: task.operation,
|
|
5368
5436
|
batchIndex,
|
|
5369
5437
|
attempts,
|
|
@@ -5375,7 +5443,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5375
5443
|
}
|
|
5376
5444
|
const executionTime = Date.now() - startTime;
|
|
5377
5445
|
const partialSuccess = successfulItems > 0 && failedItems > 0;
|
|
5378
|
-
|
|
5446
|
+
logger10.debug("Batched execution completed", {
|
|
5379
5447
|
operation: task.operation,
|
|
5380
5448
|
totalItems: task.items.length,
|
|
5381
5449
|
successfulItems,
|
|
@@ -5419,7 +5487,7 @@ async function benchmarkBatchExecution(params) {
|
|
|
5419
5487
|
const timeSavedMs = Math.max(individualExecutionTime - batchedExecutionTime, 0);
|
|
5420
5488
|
const speedupRatio = batchedExecutionTime > 0 ? individualExecutionTime / batchedExecutionTime : 0;
|
|
5421
5489
|
const speedupPercent = individualExecutionTime > 0 ? timeSavedMs / individualExecutionTime * 100 : 0;
|
|
5422
|
-
|
|
5490
|
+
logger10.debug("Batch benchmark completed", {
|
|
5423
5491
|
itemCount: params.items.length,
|
|
5424
5492
|
batchCount: batches.length,
|
|
5425
5493
|
batchSize,
|
|
@@ -5439,7 +5507,7 @@ async function benchmarkBatchExecution(params) {
|
|
|
5439
5507
|
speedupPercent
|
|
5440
5508
|
};
|
|
5441
5509
|
}
|
|
5442
|
-
var
|
|
5510
|
+
var logger11 = createLogger("agentforge:tools:data:relational:stream");
|
|
5443
5511
|
var DEFAULT_CHUNK_SIZE = 100;
|
|
5444
5512
|
var MAX_CHUNK_SIZE = 5e3;
|
|
5445
5513
|
var DEFAULT_SAMPLE_SIZE = 50;
|
|
@@ -5572,7 +5640,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5572
5640
|
const endHeapUsed = process.memoryUsage().heapUsed;
|
|
5573
5641
|
peakHeapUsed = Math.max(peakHeapUsed, endHeapUsed);
|
|
5574
5642
|
const executionTime = Date.now() - startTime;
|
|
5575
|
-
|
|
5643
|
+
logger11.debug("Streaming SELECT execution completed", {
|
|
5576
5644
|
table: input.table,
|
|
5577
5645
|
vendor: input.vendor,
|
|
5578
5646
|
chunkCount,
|
|
@@ -5596,7 +5664,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5596
5664
|
};
|
|
5597
5665
|
}
|
|
5598
5666
|
async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
5599
|
-
|
|
5667
|
+
logger11.warn("Running streaming benchmark will execute the SELECT query twice (regular + streaming).", {
|
|
5600
5668
|
table: input.table,
|
|
5601
5669
|
vendor: input.vendor
|
|
5602
5670
|
});
|
|
@@ -5616,7 +5684,7 @@ async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
|
5616
5684
|
0
|
|
5617
5685
|
);
|
|
5618
5686
|
const memorySavedPercent = nonStreamingPeakHeapUsed > 0 ? memorySavedBytes / nonStreamingPeakHeapUsed * 100 : 0;
|
|
5619
|
-
|
|
5687
|
+
logger11.debug("Streaming benchmark completed", {
|
|
5620
5688
|
table: input.table,
|
|
5621
5689
|
vendor: input.vendor,
|
|
5622
5690
|
nonStreamingRows: nonStreamingRows.length,
|
|
@@ -5634,7 +5702,7 @@ async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
|
5634
5702
|
memorySavedPercent
|
|
5635
5703
|
};
|
|
5636
5704
|
}
|
|
5637
|
-
var
|
|
5705
|
+
var logger12 = createLogger("agentforge:tools:data:relational:transaction");
|
|
5638
5706
|
var transactionSequence = 0;
|
|
5639
5707
|
var SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
5640
5708
|
function toSqlIsolationLevel(level) {
|
|
@@ -5793,7 +5861,7 @@ var ManagedTransaction = class {
|
|
|
5793
5861
|
await this.executeQuery(sql.raw("PRAGMA read_uncommitted = 1"));
|
|
5794
5862
|
this.shouldRestoreSqliteReadUncommitted = true;
|
|
5795
5863
|
} else {
|
|
5796
|
-
|
|
5864
|
+
logger12.debug("Ignoring SQLite isolation level override", {
|
|
5797
5865
|
transactionId: this.id,
|
|
5798
5866
|
isolationLevel: this.options.isolationLevel
|
|
5799
5867
|
});
|
|
@@ -5818,7 +5886,7 @@ var ManagedTransaction = class {
|
|
|
5818
5886
|
const targetValue = this.sqliteReadUncommittedOriginal ?? 0;
|
|
5819
5887
|
await this.executeQuery(sql.raw(`PRAGMA read_uncommitted = ${targetValue}`));
|
|
5820
5888
|
} catch (error) {
|
|
5821
|
-
|
|
5889
|
+
logger12.warn("Failed to restore SQLite read_uncommitted pragma", {
|
|
5822
5890
|
transactionId: this.id,
|
|
5823
5891
|
error: error instanceof Error ? error.message : String(error)
|
|
5824
5892
|
});
|
|
@@ -5847,7 +5915,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
5847
5915
|
const resolvedOptions = resolveOptions2(options);
|
|
5848
5916
|
const transactionId = `tx-${++transactionSequence}`;
|
|
5849
5917
|
const vendor = manager.getVendor();
|
|
5850
|
-
|
|
5918
|
+
logger12.debug("Starting transaction", {
|
|
5851
5919
|
transactionId,
|
|
5852
5920
|
vendor,
|
|
5853
5921
|
...resolvedOptions.isolationLevel ? { isolationLevel: resolvedOptions.isolationLevel } : {},
|
|
@@ -5874,7 +5942,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
5874
5942
|
if (transaction.isActive()) {
|
|
5875
5943
|
await transaction.commit();
|
|
5876
5944
|
}
|
|
5877
|
-
|
|
5945
|
+
logger12.debug("Transaction committed", {
|
|
5878
5946
|
transactionId,
|
|
5879
5947
|
vendor,
|
|
5880
5948
|
duration: Date.now() - startTime
|
|
@@ -5885,14 +5953,14 @@ async function withTransaction(manager, operation, options) {
|
|
|
5885
5953
|
try {
|
|
5886
5954
|
await transaction.rollback();
|
|
5887
5955
|
} catch (rollbackError) {
|
|
5888
|
-
|
|
5956
|
+
logger12.error("Transaction rollback failed", {
|
|
5889
5957
|
transactionId,
|
|
5890
5958
|
vendor,
|
|
5891
5959
|
error: rollbackError instanceof Error ? rollbackError.message : String(rollbackError)
|
|
5892
5960
|
});
|
|
5893
5961
|
}
|
|
5894
5962
|
}
|
|
5895
|
-
|
|
5963
|
+
logger12.error("Transaction failed", {
|
|
5896
5964
|
transactionId,
|
|
5897
5965
|
vendor,
|
|
5898
5966
|
duration: Date.now() - startTime,
|
|
@@ -5907,7 +5975,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
5907
5975
|
var VALID_TABLE_FILTER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)?$/;
|
|
5908
5976
|
|
|
5909
5977
|
// src/data/relational/schema/schema-inspector.ts
|
|
5910
|
-
var
|
|
5978
|
+
var logger13 = createLogger("agentforge:tools:data:relational:schema-inspector");
|
|
5911
5979
|
var DEFAULT_CACHE_TTL_MS = 6e4;
|
|
5912
5980
|
var schemaCache = /* @__PURE__ */ new Map();
|
|
5913
5981
|
var POSTGRES_TABLES_QUERY = `
|
|
@@ -6197,7 +6265,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6197
6265
|
if (!bypassCache && this.cacheKey) {
|
|
6198
6266
|
const cached = schemaCache.get(this.cacheKey);
|
|
6199
6267
|
if (cached && cached.expiresAt > Date.now()) {
|
|
6200
|
-
|
|
6268
|
+
logger13.debug("Schema cache hit", { vendor: this.vendor });
|
|
6201
6269
|
return filterSchemaTables(cloneSchema(cached.schema), tableFilters);
|
|
6202
6270
|
}
|
|
6203
6271
|
}
|
|
@@ -6464,7 +6532,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6464
6532
|
}
|
|
6465
6533
|
}
|
|
6466
6534
|
};
|
|
6467
|
-
var
|
|
6535
|
+
var logger14 = createLogger("agentforge:tools:data:relational:schema-validator");
|
|
6468
6536
|
function validateTableExists(schema, tableName) {
|
|
6469
6537
|
const errors = [];
|
|
6470
6538
|
if (!tableName || typeof tableName !== "string") {
|
|
@@ -6478,7 +6546,7 @@ function validateTableExists(schema, tableName) {
|
|
|
6478
6546
|
`Table "${tableName}" does not exist. Available tables: ${available || "(none)"}`
|
|
6479
6547
|
);
|
|
6480
6548
|
}
|
|
6481
|
-
|
|
6549
|
+
logger14.debug("Table existence validation", { tableName, valid: errors.length === 0 });
|
|
6482
6550
|
return { valid: errors.length === 0, errors };
|
|
6483
6551
|
}
|
|
6484
6552
|
function validateColumnsExist(schema, tableName, columnNames) {
|
|
@@ -6501,7 +6569,7 @@ function validateColumnsExist(schema, tableName, columnNames) {
|
|
|
6501
6569
|
);
|
|
6502
6570
|
}
|
|
6503
6571
|
}
|
|
6504
|
-
|
|
6572
|
+
logger14.debug("Column existence validation", {
|
|
6505
6573
|
tableName,
|
|
6506
6574
|
columnCount: columnNames.length,
|
|
6507
6575
|
valid: errors.length === 0
|
|
@@ -6537,7 +6605,7 @@ function validateColumnTypes(schema, tableName, expectedTypes) {
|
|
|
6537
6605
|
);
|
|
6538
6606
|
}
|
|
6539
6607
|
}
|
|
6540
|
-
|
|
6608
|
+
logger14.debug("Column type validation", {
|
|
6541
6609
|
tableName,
|
|
6542
6610
|
typeChecks: Object.keys(expectedTypes).length,
|
|
6543
6611
|
valid: errors.length === 0
|
|
@@ -6557,7 +6625,7 @@ function findTable(schema, tableName) {
|
|
|
6557
6625
|
function formatTableName(table) {
|
|
6558
6626
|
return table.schema ? `${table.schema}.${table.name}` : table.name;
|
|
6559
6627
|
}
|
|
6560
|
-
var
|
|
6628
|
+
var logger15 = createLogger("agentforge:tools:data:relational:type-mapper");
|
|
6561
6629
|
var POSTGRES_TYPE_MAP = {
|
|
6562
6630
|
// Numeric
|
|
6563
6631
|
smallint: "number",
|
|
@@ -6723,7 +6791,7 @@ function mapColumnType(vendor, dbType, nullable = false) {
|
|
|
6723
6791
|
const result = { tsType, nullable, dbType };
|
|
6724
6792
|
if (tsType === "unknown" && normalised !== "json" && normalised !== "jsonb") {
|
|
6725
6793
|
result.notes = `No explicit mapping for "${dbType}"; defaulting to unknown`;
|
|
6726
|
-
|
|
6794
|
+
logger15.debug("Unmapped database type", { vendor, dbType, normalised });
|
|
6727
6795
|
}
|
|
6728
6796
|
if ((normalised === "bigint" || normalised === "int8" || normalised === "bigserial") && (vendor === "postgresql" || vendor === "mysql")) {
|
|
6729
6797
|
result.notes = "Mapped to string to avoid JavaScript number precision loss for 64-bit integers";
|
|
@@ -6738,7 +6806,7 @@ function mapSchemaTypes(vendor, columns) {
|
|
|
6738
6806
|
}
|
|
6739
6807
|
result.get(col.table).set(col.name, mapColumnType(vendor, col.type, col.nullable));
|
|
6740
6808
|
}
|
|
6741
|
-
|
|
6809
|
+
logger15.debug("Schema type mapping complete", {
|
|
6742
6810
|
vendor,
|
|
6743
6811
|
tables: result.size,
|
|
6744
6812
|
columns: columns.length
|
|
@@ -6755,7 +6823,7 @@ function normaliseDbType(raw) {
|
|
|
6755
6823
|
type = type.replace(/\s+unsigned$/, "");
|
|
6756
6824
|
return type.trim();
|
|
6757
6825
|
}
|
|
6758
|
-
var
|
|
6826
|
+
var logger16 = createLogger("agentforge:tools:data:relational:schema-diff");
|
|
6759
6827
|
function diffSchemas(before, after) {
|
|
6760
6828
|
const tableDiffs = [];
|
|
6761
6829
|
let columnsAdded = 0;
|
|
@@ -6795,7 +6863,7 @@ function diffSchemas(before, after) {
|
|
|
6795
6863
|
const tablesRemoved = tableDiffs.filter((d) => d.type === "removed").length;
|
|
6796
6864
|
const tablesChanged = tableDiffs.filter((d) => d.type === "changed").length;
|
|
6797
6865
|
const identical = tableDiffs.length === 0;
|
|
6798
|
-
|
|
6866
|
+
logger16.debug("Schema diff computed", {
|
|
6799
6867
|
identical,
|
|
6800
6868
|
tablesAdded,
|
|
6801
6869
|
tablesRemoved,
|
|
@@ -6839,7 +6907,7 @@ function importSchemaFromJson(json) {
|
|
|
6839
6907
|
throw new Error(`Invalid schema JSON: table "${table.name}" missing "primaryKey" array`);
|
|
6840
6908
|
}
|
|
6841
6909
|
}
|
|
6842
|
-
|
|
6910
|
+
logger16.debug("Schema imported from JSON", {
|
|
6843
6911
|
vendor: obj.vendor,
|
|
6844
6912
|
tableCount: obj.tables.length
|
|
6845
6913
|
});
|
|
@@ -7136,7 +7204,7 @@ function isSafeValidationError(error) {
|
|
|
7136
7204
|
}
|
|
7137
7205
|
|
|
7138
7206
|
// src/data/relational/tools/relational-select/executor.ts
|
|
7139
|
-
var
|
|
7207
|
+
var logger17 = createLogger("agentforge:tools:data:relational:select");
|
|
7140
7208
|
function toSelectQueryInput(input) {
|
|
7141
7209
|
return {
|
|
7142
7210
|
table: input.table,
|
|
@@ -7150,7 +7218,7 @@ function toSelectQueryInput(input) {
|
|
|
7150
7218
|
}
|
|
7151
7219
|
async function executeSelect(manager, input, context) {
|
|
7152
7220
|
const startTime = Date.now();
|
|
7153
|
-
|
|
7221
|
+
logger17.debug("Building SELECT query", {
|
|
7154
7222
|
vendor: input.vendor,
|
|
7155
7223
|
table: input.table,
|
|
7156
7224
|
hasWhere: !!input.where,
|
|
@@ -7168,7 +7236,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7168
7236
|
};
|
|
7169
7237
|
const streamInput = toSelectQueryInput(input);
|
|
7170
7238
|
if (input.streaming.benchmark) {
|
|
7171
|
-
|
|
7239
|
+
logger17.warn("Streaming benchmark enabled; SELECT will execute up to three times (result + benchmark regular + benchmark streaming).", {
|
|
7172
7240
|
vendor: input.vendor,
|
|
7173
7241
|
table: input.table,
|
|
7174
7242
|
chunkSize: streamOptions.chunkSize ?? DEFAULT_CHUNK_SIZE,
|
|
@@ -7179,7 +7247,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7179
7247
|
const streamResult = await executeStreamingSelect(executor, streamInput, streamOptions);
|
|
7180
7248
|
const benchmark = input.streaming.benchmark ? await benchmarkStreamingSelectMemory(executor, streamInput, streamOptions) : void 0;
|
|
7181
7249
|
const executionTime2 = Date.now() - startTime;
|
|
7182
|
-
|
|
7250
|
+
logger17.debug("Streaming SELECT query executed successfully", {
|
|
7183
7251
|
vendor: input.vendor,
|
|
7184
7252
|
table: input.table,
|
|
7185
7253
|
rowCount: streamResult.rowCount,
|
|
@@ -7208,7 +7276,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7208
7276
|
const executionTime = Date.now() - startTime;
|
|
7209
7277
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
7210
7278
|
const rowCount = rows.length;
|
|
7211
|
-
|
|
7279
|
+
logger17.debug("SELECT query executed successfully", {
|
|
7212
7280
|
vendor: input.vendor,
|
|
7213
7281
|
table: input.table,
|
|
7214
7282
|
rowCount,
|
|
@@ -7221,7 +7289,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7221
7289
|
};
|
|
7222
7290
|
} catch (error) {
|
|
7223
7291
|
const executionTime = Date.now() - startTime;
|
|
7224
|
-
|
|
7292
|
+
logger17.error("SELECT query execution failed", {
|
|
7225
7293
|
vendor: input.vendor,
|
|
7226
7294
|
table: input.table,
|
|
7227
7295
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -7397,7 +7465,7 @@ function isSafeInsertError(error) {
|
|
|
7397
7465
|
}
|
|
7398
7466
|
|
|
7399
7467
|
// src/data/relational/tools/relational-insert/executor.ts
|
|
7400
|
-
var
|
|
7468
|
+
var logger18 = createLogger("agentforge:tools:data:relational:insert");
|
|
7401
7469
|
function toNumber(value) {
|
|
7402
7470
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7403
7471
|
}
|
|
@@ -7546,7 +7614,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7546
7614
|
maxRetries: options.maxRetries,
|
|
7547
7615
|
retryDelayMs: options.retryDelayMs,
|
|
7548
7616
|
onProgress: (progress) => {
|
|
7549
|
-
|
|
7617
|
+
logger18.debug("INSERT batch progress", {
|
|
7550
7618
|
vendor: input.vendor,
|
|
7551
7619
|
table: input.table,
|
|
7552
7620
|
...progress
|
|
@@ -7559,7 +7627,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7559
7627
|
const insertedIds = batchResult.results.flatMap((result) => result.insertedIds);
|
|
7560
7628
|
let benchmark;
|
|
7561
7629
|
if (options.benchmark) {
|
|
7562
|
-
|
|
7630
|
+
logger18.warn("INSERT batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
7563
7631
|
vendor: input.vendor,
|
|
7564
7632
|
table: input.table,
|
|
7565
7633
|
totalRows: input.data.length,
|
|
@@ -7596,7 +7664,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7596
7664
|
}
|
|
7597
7665
|
async function executeInsert(manager, input, context) {
|
|
7598
7666
|
const startTime = Date.now();
|
|
7599
|
-
|
|
7667
|
+
logger18.debug("Building INSERT query", {
|
|
7600
7668
|
vendor: input.vendor,
|
|
7601
7669
|
table: input.table,
|
|
7602
7670
|
isBatch: Array.isArray(input.data),
|
|
@@ -7612,7 +7680,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7612
7680
|
batchOptions
|
|
7613
7681
|
) : await executeInsertOnce(manager, input, context);
|
|
7614
7682
|
const executionTime = Date.now() - startTime;
|
|
7615
|
-
|
|
7683
|
+
logger18.debug("INSERT query executed successfully", {
|
|
7616
7684
|
vendor: input.vendor,
|
|
7617
7685
|
table: input.table,
|
|
7618
7686
|
rowCount: result.rowCount,
|
|
@@ -7628,7 +7696,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7628
7696
|
};
|
|
7629
7697
|
} catch (error) {
|
|
7630
7698
|
const executionTime = Date.now() - startTime;
|
|
7631
|
-
|
|
7699
|
+
logger18.error("INSERT query execution failed", {
|
|
7632
7700
|
vendor: input.vendor,
|
|
7633
7701
|
table: input.table,
|
|
7634
7702
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -7958,7 +8026,7 @@ function isSafeUpdateError(error) {
|
|
|
7958
8026
|
}
|
|
7959
8027
|
|
|
7960
8028
|
// src/data/relational/tools/relational-update/executor.ts
|
|
7961
|
-
var
|
|
8029
|
+
var logger19 = createLogger("agentforge:tools:data:relational:update");
|
|
7962
8030
|
function toNumber2(value) {
|
|
7963
8031
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7964
8032
|
}
|
|
@@ -8080,7 +8148,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8080
8148
|
maxRetries: options.maxRetries,
|
|
8081
8149
|
retryDelayMs: options.retryDelayMs,
|
|
8082
8150
|
onProgress: (progress) => {
|
|
8083
|
-
|
|
8151
|
+
logger19.debug("UPDATE batch progress", {
|
|
8084
8152
|
vendor: input.vendor,
|
|
8085
8153
|
table: input.table,
|
|
8086
8154
|
...progress
|
|
@@ -8092,7 +8160,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8092
8160
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8093
8161
|
let benchmark;
|
|
8094
8162
|
if (options.benchmark) {
|
|
8095
|
-
|
|
8163
|
+
logger19.warn("UPDATE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8096
8164
|
vendor: input.vendor,
|
|
8097
8165
|
table: input.table,
|
|
8098
8166
|
operationCount: input.operations.length,
|
|
@@ -8127,7 +8195,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8127
8195
|
}
|
|
8128
8196
|
async function executeUpdate(manager, input, context) {
|
|
8129
8197
|
const startTime = Date.now();
|
|
8130
|
-
|
|
8198
|
+
logger19.debug("Building UPDATE query", {
|
|
8131
8199
|
vendor: input.vendor,
|
|
8132
8200
|
table: input.table,
|
|
8133
8201
|
hasWhere: !!input.where?.length,
|
|
@@ -8145,7 +8213,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8145
8213
|
batchOptions
|
|
8146
8214
|
) : await executeSingleUpdate(manager, input, toSingleUpdateOperation(input), context);
|
|
8147
8215
|
const executionTime = Date.now() - startTime;
|
|
8148
|
-
|
|
8216
|
+
logger19.debug("UPDATE query executed successfully", {
|
|
8149
8217
|
vendor: input.vendor,
|
|
8150
8218
|
table: input.table,
|
|
8151
8219
|
rowCount: result.rowCount,
|
|
@@ -8159,7 +8227,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8159
8227
|
};
|
|
8160
8228
|
} catch (error) {
|
|
8161
8229
|
const executionTime = Date.now() - startTime;
|
|
8162
|
-
|
|
8230
|
+
logger19.error("UPDATE query execution failed", {
|
|
8163
8231
|
vendor: input.vendor,
|
|
8164
8232
|
table: input.table,
|
|
8165
8233
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8463,7 +8531,7 @@ function isSafeDeleteError(error) {
|
|
|
8463
8531
|
}
|
|
8464
8532
|
|
|
8465
8533
|
// src/data/relational/tools/relational-delete/executor.ts
|
|
8466
|
-
var
|
|
8534
|
+
var logger20 = createLogger("agentforge:tools:data:relational:delete");
|
|
8467
8535
|
function toNumber3(value) {
|
|
8468
8536
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8469
8537
|
}
|
|
@@ -8584,7 +8652,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8584
8652
|
maxRetries: options.maxRetries,
|
|
8585
8653
|
retryDelayMs: options.retryDelayMs,
|
|
8586
8654
|
onProgress: (progress) => {
|
|
8587
|
-
|
|
8655
|
+
logger20.debug("DELETE batch progress", {
|
|
8588
8656
|
vendor: input.vendor,
|
|
8589
8657
|
table: input.table,
|
|
8590
8658
|
...progress
|
|
@@ -8597,7 +8665,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8597
8665
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8598
8666
|
let benchmark;
|
|
8599
8667
|
if (options.benchmark) {
|
|
8600
|
-
|
|
8668
|
+
logger20.warn("DELETE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8601
8669
|
vendor: input.vendor,
|
|
8602
8670
|
table: input.table,
|
|
8603
8671
|
operationCount: input.operations.length,
|
|
@@ -8633,7 +8701,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8633
8701
|
}
|
|
8634
8702
|
async function executeDelete(manager, input, context) {
|
|
8635
8703
|
const startTime = Date.now();
|
|
8636
|
-
|
|
8704
|
+
logger20.debug("Building DELETE query", {
|
|
8637
8705
|
vendor: input.vendor,
|
|
8638
8706
|
table: input.table,
|
|
8639
8707
|
hasWhere: !!input.where?.length,
|
|
@@ -8652,7 +8720,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8652
8720
|
batchOptions
|
|
8653
8721
|
) : await executeSingleDelete(manager, input, toSingleDeleteOperation(input), context);
|
|
8654
8722
|
const executionTime = Date.now() - startTime;
|
|
8655
|
-
|
|
8723
|
+
logger20.debug("DELETE query executed successfully", {
|
|
8656
8724
|
vendor: input.vendor,
|
|
8657
8725
|
table: input.table,
|
|
8658
8726
|
rowCount: result.rowCount,
|
|
@@ -8668,7 +8736,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8668
8736
|
};
|
|
8669
8737
|
} catch (error) {
|
|
8670
8738
|
const executionTime = Date.now() - startTime;
|
|
8671
|
-
|
|
8739
|
+
logger20.error("DELETE query execution failed", {
|
|
8672
8740
|
vendor: input.vendor,
|
|
8673
8741
|
table: input.table,
|
|
8674
8742
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8773,7 +8841,7 @@ function isSafeGetSchemaValidationError(error) {
|
|
|
8773
8841
|
}
|
|
8774
8842
|
|
|
8775
8843
|
// src/data/relational/tools/relational-get-schema.ts
|
|
8776
|
-
var
|
|
8844
|
+
var logger21 = createLogger("agentforge:tools:data:relational:get-schema");
|
|
8777
8845
|
function buildSchemaCacheKey(vendor, connectionString, database) {
|
|
8778
8846
|
const databaseScope = database ?? "default";
|
|
8779
8847
|
const connectionHash = createHash("sha256").update(connectionString).digest("hex");
|
|
@@ -8845,7 +8913,7 @@ var relationalGetSchema = toolBuilder().name("relational-get-schema").displayNam
|
|
|
8845
8913
|
summary
|
|
8846
8914
|
};
|
|
8847
8915
|
} catch (error) {
|
|
8848
|
-
|
|
8916
|
+
logger21.error("Schema introspection failed", {
|
|
8849
8917
|
vendor: input.vendor,
|
|
8850
8918
|
hasTablesFilter: Array.isArray(input.tables),
|
|
8851
8919
|
tablesFilterCount: input.tables?.length ?? 0,
|
|
@@ -10011,7 +10079,7 @@ var AskHumanInputSchema = z.object({
|
|
|
10011
10079
|
suggestions: z.array(z.string()).optional().describe("Suggested responses for the human")
|
|
10012
10080
|
});
|
|
10013
10081
|
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
|
|
10014
|
-
var
|
|
10082
|
+
var logger22 = createLogger("agentforge:tools:agent:ask-human", { level: logLevel3 });
|
|
10015
10083
|
function isRecord(value) {
|
|
10016
10084
|
return typeof value === "object" && value !== null;
|
|
10017
10085
|
}
|
|
@@ -10076,7 +10144,7 @@ function createAskHumanTool() {
|
|
|
10076
10144
|
suggestions: validatedInput.suggestions,
|
|
10077
10145
|
status: "pending"
|
|
10078
10146
|
};
|
|
10079
|
-
|
|
10147
|
+
logger22.debug("About to call interrupt()", {
|
|
10080
10148
|
humanRequest: {
|
|
10081
10149
|
id: humanRequest.id,
|
|
10082
10150
|
question: humanRequest.question,
|
|
@@ -10092,13 +10160,13 @@ function createAskHumanTool() {
|
|
|
10092
10160
|
let response;
|
|
10093
10161
|
try {
|
|
10094
10162
|
response = interrupt(humanRequest);
|
|
10095
|
-
|
|
10163
|
+
logger22.debug("interrupt() returned successfully", {
|
|
10096
10164
|
responseType: typeof response,
|
|
10097
10165
|
hasResponse: response != null,
|
|
10098
10166
|
...typeof response === "string" ? { responseLength: response.length } : {}
|
|
10099
10167
|
});
|
|
10100
10168
|
} catch (error) {
|
|
10101
|
-
|
|
10169
|
+
logger22.debug("interrupt() threw error (expected for GraphInterrupt)", {
|
|
10102
10170
|
...error && typeof error === "object" && "constructor" in error ? { errorType: error.constructor?.name } : {},
|
|
10103
10171
|
error: error instanceof Error ? error.message : String(error)
|
|
10104
10172
|
});
|