@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.cjs
CHANGED
|
@@ -815,7 +815,7 @@ function getDefaultSlackClient() {
|
|
|
815
815
|
}
|
|
816
816
|
};
|
|
817
817
|
}
|
|
818
|
-
function createSendSlackMessageTool(getSlackClient,
|
|
818
|
+
function createSendSlackMessageTool(getSlackClient, logger23) {
|
|
819
819
|
return core.toolBuilder().name("send-slack-message").description("Send a message to a Slack channel for team communication and notifications").category(core.ToolCategory.WEB).tags(["slack", "messaging", "communication"]).usageNotes(
|
|
820
820
|
"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."
|
|
821
821
|
).suggests(["get-slack-channels"]).schema(
|
|
@@ -824,7 +824,7 @@ function createSendSlackMessageTool(getSlackClient, logger22) {
|
|
|
824
824
|
message: zod.z.string().describe("Message content to send")
|
|
825
825
|
})
|
|
826
826
|
).implementSafe(async ({ channel, message }) => {
|
|
827
|
-
|
|
827
|
+
logger23.info("send-slack-message called", { channel, messageLength: message.length });
|
|
828
828
|
try {
|
|
829
829
|
const { client: slack, config } = getSlackClient();
|
|
830
830
|
const result = await slack.chat.postMessage({
|
|
@@ -833,7 +833,7 @@ function createSendSlackMessageTool(getSlackClient, logger22) {
|
|
|
833
833
|
username: config.botName,
|
|
834
834
|
icon_emoji: config.botIcon
|
|
835
835
|
});
|
|
836
|
-
|
|
836
|
+
logger23.info("send-slack-message result", {
|
|
837
837
|
...result.channel ? { channel: result.channel } : {},
|
|
838
838
|
...result.ts ? { timestamp: result.ts } : {},
|
|
839
839
|
messageLength: message.length,
|
|
@@ -846,7 +846,7 @@ function createSendSlackMessageTool(getSlackClient, logger22) {
|
|
|
846
846
|
message_id: result.ts
|
|
847
847
|
};
|
|
848
848
|
} catch (error) {
|
|
849
|
-
|
|
849
|
+
logger23.error("send-slack-message failed", {
|
|
850
850
|
channel,
|
|
851
851
|
error: error.message,
|
|
852
852
|
data: error.data
|
|
@@ -855,7 +855,7 @@ function createSendSlackMessageTool(getSlackClient, logger22) {
|
|
|
855
855
|
}
|
|
856
856
|
}).build();
|
|
857
857
|
}
|
|
858
|
-
function createNotifySlackTool(getSlackClient,
|
|
858
|
+
function createNotifySlackTool(getSlackClient, logger23) {
|
|
859
859
|
return core.toolBuilder().name("notify-slack").description("Send a notification to a Slack channel with optional @mentions for urgent alerts").category(core.ToolCategory.WEB).tags(["slack", "notification", "alert"]).usageNotes(
|
|
860
860
|
"Use this for urgent notifications that require @mentions. For general messages without mentions, use send-slack-message instead."
|
|
861
861
|
).suggests(["get-slack-channels"]).schema(
|
|
@@ -865,7 +865,7 @@ function createNotifySlackTool(getSlackClient, logger22) {
|
|
|
865
865
|
mentions: zod.z.array(zod.z.string()).optional().describe("List of usernames to mention (without @)")
|
|
866
866
|
})
|
|
867
867
|
).implementSafe(async ({ channel, message, mentions = [] }) => {
|
|
868
|
-
|
|
868
|
+
logger23.info("notify-slack called", {
|
|
869
869
|
channel,
|
|
870
870
|
messageLength: message.length,
|
|
871
871
|
mentionCount: mentions.length
|
|
@@ -879,7 +879,7 @@ function createNotifySlackTool(getSlackClient, logger22) {
|
|
|
879
879
|
username: config.botName,
|
|
880
880
|
icon_emoji: config.botIcon
|
|
881
881
|
});
|
|
882
|
-
|
|
882
|
+
logger23.info("notify-slack result", {
|
|
883
883
|
...result.channel ? { channel: result.channel } : {},
|
|
884
884
|
...result.ts ? { timestamp: result.ts } : {},
|
|
885
885
|
mentions: mentions.length
|
|
@@ -893,7 +893,7 @@ function createNotifySlackTool(getSlackClient, logger22) {
|
|
|
893
893
|
};
|
|
894
894
|
}).build();
|
|
895
895
|
}
|
|
896
|
-
function createGetSlackChannelsTool(getSlackClient,
|
|
896
|
+
function createGetSlackChannelsTool(getSlackClient, logger23) {
|
|
897
897
|
return core.toolBuilder().name("get-slack-channels").description("Get a list of available Slack channels to find the right channel for messaging").category(core.ToolCategory.WEB).tags(["slack", "channels", "list"]).usageNotes(
|
|
898
898
|
"Use this first to discover available channels before sending messages. Helps ensure you are sending to the correct channel."
|
|
899
899
|
).follows(["send-slack-message", "notify-slack"]).schema(
|
|
@@ -901,7 +901,7 @@ function createGetSlackChannelsTool(getSlackClient, logger22) {
|
|
|
901
901
|
include_private: zod.z.boolean().optional().describe("Include private channels (default: false)")
|
|
902
902
|
})
|
|
903
903
|
).implementSafe(async ({ include_private = false }) => {
|
|
904
|
-
|
|
904
|
+
logger23.info("get-slack-channels called", { include_private });
|
|
905
905
|
const { client: slack } = getSlackClient();
|
|
906
906
|
const publicChannels = await slack.conversations.list({
|
|
907
907
|
types: "public_channel",
|
|
@@ -915,7 +915,7 @@ function createGetSlackChannelsTool(getSlackClient, logger22) {
|
|
|
915
915
|
});
|
|
916
916
|
allChannels = [...allChannels, ...privateChannels.channels || []];
|
|
917
917
|
}
|
|
918
|
-
|
|
918
|
+
logger23.info("get-slack-channels result", {
|
|
919
919
|
channelCount: allChannels.length,
|
|
920
920
|
includePrivate: include_private
|
|
921
921
|
});
|
|
@@ -930,7 +930,7 @@ function createGetSlackChannelsTool(getSlackClient, logger22) {
|
|
|
930
930
|
};
|
|
931
931
|
}).build();
|
|
932
932
|
}
|
|
933
|
-
function createGetSlackMessagesTool(getSlackClient,
|
|
933
|
+
function createGetSlackMessagesTool(getSlackClient, logger23) {
|
|
934
934
|
return core.toolBuilder().name("get-slack-messages").description("Retrieve message history from a Slack channel to read recent conversations").category(core.ToolCategory.WEB).tags(["slack", "messages", "history", "read"]).usageNotes(
|
|
935
935
|
"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)."
|
|
936
936
|
).suggests(["get-slack-channels"]).schema(
|
|
@@ -939,7 +939,7 @@ function createGetSlackMessagesTool(getSlackClient, logger22) {
|
|
|
939
939
|
limit: zod.z.number().int().min(1).max(100).optional().describe("Number of messages to retrieve (default: 20, max: 100)")
|
|
940
940
|
})
|
|
941
941
|
).implementSafe(async ({ channel, limit = 20 }) => {
|
|
942
|
-
|
|
942
|
+
logger23.info("get-slack-messages called", { channel, limit });
|
|
943
943
|
try {
|
|
944
944
|
const { client: slack } = getSlackClient();
|
|
945
945
|
let channelId = channel;
|
|
@@ -950,7 +950,7 @@ function createGetSlackMessagesTool(getSlackClient, logger22) {
|
|
|
950
950
|
});
|
|
951
951
|
const found = channels.channels?.find((c) => c.name === channel);
|
|
952
952
|
if (!found) {
|
|
953
|
-
|
|
953
|
+
logger23.error("get-slack-messages: channel not found", { channel });
|
|
954
954
|
throw new Error(
|
|
955
955
|
`Channel '${channel}' not found. Use get-slack-channels to see available channels.`
|
|
956
956
|
);
|
|
@@ -962,7 +962,7 @@ function createGetSlackMessagesTool(getSlackClient, logger22) {
|
|
|
962
962
|
limit: Math.min(limit, 100)
|
|
963
963
|
// Cap at 100 for performance
|
|
964
964
|
});
|
|
965
|
-
|
|
965
|
+
logger23.info("get-slack-messages result", {
|
|
966
966
|
channel: channelId,
|
|
967
967
|
messageCount: result.messages?.length || 0,
|
|
968
968
|
limit
|
|
@@ -980,7 +980,7 @@ function createGetSlackMessagesTool(getSlackClient, logger22) {
|
|
|
980
980
|
})) || []
|
|
981
981
|
};
|
|
982
982
|
} catch (error) {
|
|
983
|
-
|
|
983
|
+
logger23.error("get-slack-messages failed", {
|
|
984
984
|
channel,
|
|
985
985
|
error: error.message,
|
|
986
986
|
data: error.data
|
|
@@ -1061,12 +1061,12 @@ function getAuthHeader() {
|
|
|
1061
1061
|
const auth2 = Buffer.from(`${ATLASSIAN_EMAIL}:${ATLASSIAN_API_KEY}`).toString("base64");
|
|
1062
1062
|
return `Basic ${auth2}`;
|
|
1063
1063
|
}
|
|
1064
|
-
function createSearchConfluenceTool(getAuth, getAuthHeader2,
|
|
1064
|
+
function createSearchConfluenceTool(getAuth, getAuthHeader2, logger23) {
|
|
1065
1065
|
return core.toolBuilder().name("search-confluence").description("Search for pages in Confluence using keywords or CQL (Confluence Query Language). Returns matching pages with titles, IDs, and excerpts.").category(core.ToolCategory.WEB).tag("confluence").tag("search").tag("knowledge-base").usageNotes("Use this to find relevant documentation, policies, or information in Confluence. You can search by keywords or use CQL for advanced queries (e.g., 'space=AI AND type=page'). Use get-confluence-page to retrieve full content of specific pages.").suggests(["get-confluence-page"]).schema(zod.z.object({
|
|
1066
1066
|
query: zod.z.string().describe("Search query or CQL expression (e.g., 'payment processing' or 'space=BL3 AND title~payment')"),
|
|
1067
1067
|
limit: zod.z.number().optional().describe("Maximum number of results to return (default: 10, max: 25)")
|
|
1068
1068
|
})).implement(async ({ query, limit = 10 }) => {
|
|
1069
|
-
|
|
1069
|
+
logger23.info("search-confluence called", { query, limit });
|
|
1070
1070
|
try {
|
|
1071
1071
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1072
1072
|
const response = await axios16__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/search`, {
|
|
@@ -1091,13 +1091,13 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1091
1091
|
lastModified: page.version?.when || ""
|
|
1092
1092
|
}));
|
|
1093
1093
|
if (results.length === 0) {
|
|
1094
|
-
|
|
1094
|
+
logger23.warn("search-confluence returned NO RESULTS - this is a valid outcome, agent should not retry", {
|
|
1095
1095
|
query,
|
|
1096
1096
|
limit,
|
|
1097
1097
|
totalSize: response.data.totalSize
|
|
1098
1098
|
});
|
|
1099
1099
|
} else {
|
|
1100
|
-
|
|
1100
|
+
logger23.info("search-confluence result", {
|
|
1101
1101
|
query,
|
|
1102
1102
|
resultCount: results.length,
|
|
1103
1103
|
totalSize: response.data.totalSize,
|
|
@@ -1112,7 +1112,7 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1112
1112
|
results
|
|
1113
1113
|
});
|
|
1114
1114
|
} catch (error) {
|
|
1115
|
-
|
|
1115
|
+
logger23.error("search-confluence error", {
|
|
1116
1116
|
query,
|
|
1117
1117
|
error: error.response?.data?.message || error.message,
|
|
1118
1118
|
status: error.response?.status
|
|
@@ -1124,11 +1124,11 @@ function createSearchConfluenceTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1124
1124
|
}
|
|
1125
1125
|
}).build();
|
|
1126
1126
|
}
|
|
1127
|
-
function createGetConfluencePageTool(getAuth, getAuthHeader2,
|
|
1127
|
+
function createGetConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
1128
1128
|
return core.toolBuilder().name("get-confluence-page").description("Get the full content of a specific Confluence page by its ID. Returns the page title, content (in storage format), space, and metadata.").category(core.ToolCategory.WEB).tag("confluence").tag("page").tag("content").usageNotes("Use this after search-confluence to retrieve the full content of a specific page. The page ID can be found in search results.").requires(["search-confluence"]).schema(zod.z.object({
|
|
1129
1129
|
page_id: zod.z.string().describe("The Confluence page ID (from search results)")
|
|
1130
1130
|
})).implement(async ({ page_id }) => {
|
|
1131
|
-
|
|
1131
|
+
logger23.info("get-confluence-page called", { page_id });
|
|
1132
1132
|
try {
|
|
1133
1133
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1134
1134
|
const response = await axios16__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content/${page_id}`, {
|
|
@@ -1141,7 +1141,7 @@ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1141
1141
|
}
|
|
1142
1142
|
});
|
|
1143
1143
|
const page = response.data;
|
|
1144
|
-
|
|
1144
|
+
logger23.info("get-confluence-page result", {
|
|
1145
1145
|
page_id,
|
|
1146
1146
|
title: page.title,
|
|
1147
1147
|
space: page.space?.name,
|
|
@@ -1163,7 +1163,7 @@ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1163
1163
|
}
|
|
1164
1164
|
});
|
|
1165
1165
|
} catch (error) {
|
|
1166
|
-
|
|
1166
|
+
logger23.error("get-confluence-page error", {
|
|
1167
1167
|
page_id,
|
|
1168
1168
|
error: error.response?.data?.message || error.message,
|
|
1169
1169
|
status: error.response?.status
|
|
@@ -1175,11 +1175,11 @@ function createGetConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1175
1175
|
}
|
|
1176
1176
|
}).build();
|
|
1177
1177
|
}
|
|
1178
|
-
function createListConfluenceSpacesTool(getAuth, getAuthHeader2,
|
|
1178
|
+
function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger23) {
|
|
1179
1179
|
return core.toolBuilder().name("list-confluence-spaces").description("List all available Confluence spaces. Returns space names, keys, types, and descriptions to help identify where to search for information.").category(core.ToolCategory.WEB).tag("confluence").tag("spaces").tag("list").usageNotes("Use this first to discover available spaces before searching. Helps narrow down searches to specific areas (e.g., 'AI', 'BL3', 'Finance').").follows(["search-confluence"]).schema(zod.z.object({
|
|
1180
1180
|
limit: zod.z.number().optional().describe("Maximum number of spaces to return (default: 25)")
|
|
1181
1181
|
})).implement(async ({ limit = 25 }) => {
|
|
1182
|
-
|
|
1182
|
+
logger23.info("list-confluence-spaces called", { limit });
|
|
1183
1183
|
try {
|
|
1184
1184
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1185
1185
|
const response = await axios16__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/space`, {
|
|
@@ -1198,7 +1198,7 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1198
1198
|
description: space.description?.plain?.value || "",
|
|
1199
1199
|
url: `${ATLASSIAN_SITE_URL}/wiki${space._links.webui}`
|
|
1200
1200
|
}));
|
|
1201
|
-
|
|
1201
|
+
logger23.info("list-confluence-spaces result", {
|
|
1202
1202
|
spaceCount: spaces.length,
|
|
1203
1203
|
spaceKeys: spaces.map((s) => s.key).slice(0, 5)
|
|
1204
1204
|
// Log first 5 space keys
|
|
@@ -1209,7 +1209,7 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1209
1209
|
spaces
|
|
1210
1210
|
});
|
|
1211
1211
|
} catch (error) {
|
|
1212
|
-
|
|
1212
|
+
logger23.error("list-confluence-spaces error", {
|
|
1213
1213
|
error: error.response?.data?.message || error.message,
|
|
1214
1214
|
status: error.response?.status
|
|
1215
1215
|
});
|
|
@@ -1220,12 +1220,12 @@ function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1220
1220
|
}
|
|
1221
1221
|
}).build();
|
|
1222
1222
|
}
|
|
1223
|
-
function createGetSpacePagesTool(getAuth, getAuthHeader2,
|
|
1223
|
+
function createGetSpacePagesTool(getAuth, getAuthHeader2, logger23) {
|
|
1224
1224
|
return core.toolBuilder().name("get-space-pages").description("Get all pages from a specific Confluence space by space key. Useful for browsing content in a particular area.").category(core.ToolCategory.WEB).tag("confluence").tag("space").tag("pages").usageNotes("Use this to explore all pages in a specific space. Get the space key from list-confluence-spaces first.").requires(["list-confluence-spaces"]).schema(zod.z.object({
|
|
1225
1225
|
space_key: zod.z.string().describe("The space key (e.g., 'AI', 'BL3', 'FIN')"),
|
|
1226
1226
|
limit: zod.z.number().optional().describe("Maximum number of pages to return (default: 25)")
|
|
1227
1227
|
})).implement(async ({ space_key, limit = 25 }) => {
|
|
1228
|
-
|
|
1228
|
+
logger23.info("get-space-pages called", { space_key, limit });
|
|
1229
1229
|
try {
|
|
1230
1230
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1231
1231
|
const response = await axios16__default.default.get(`${ATLASSIAN_SITE_URL}/wiki/rest/api/content`, {
|
|
@@ -1247,12 +1247,12 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1247
1247
|
lastModified: page.version?.when || ""
|
|
1248
1248
|
}));
|
|
1249
1249
|
if (pages.length === 0) {
|
|
1250
|
-
|
|
1250
|
+
logger23.warn("get-space-pages returned NO PAGES - this is a valid outcome, agent should not retry", {
|
|
1251
1251
|
space_key,
|
|
1252
1252
|
limit
|
|
1253
1253
|
});
|
|
1254
1254
|
} else {
|
|
1255
|
-
|
|
1255
|
+
logger23.info("get-space-pages result", {
|
|
1256
1256
|
space_key,
|
|
1257
1257
|
pageCount: pages.length,
|
|
1258
1258
|
titles: pages.map((p) => p.title).slice(0, 3)
|
|
@@ -1266,7 +1266,7 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1266
1266
|
pages
|
|
1267
1267
|
});
|
|
1268
1268
|
} catch (error) {
|
|
1269
|
-
|
|
1269
|
+
logger23.error("get-space-pages error", {
|
|
1270
1270
|
space_key,
|
|
1271
1271
|
error: error.response?.data?.message || error.message,
|
|
1272
1272
|
status: error.response?.status
|
|
@@ -1278,14 +1278,14 @@ function createGetSpacePagesTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1278
1278
|
}
|
|
1279
1279
|
}).build();
|
|
1280
1280
|
}
|
|
1281
|
-
function createCreateConfluencePageTool(getAuth, getAuthHeader2,
|
|
1281
|
+
function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
1282
1282
|
return core.toolBuilder().name("create-confluence-page").description("Create a new page in a Confluence space. Requires space key, page title, and content (in HTML storage format).").category(core.ToolCategory.WEB).tag("confluence").tag("create").tag("write").usageNotes("Use this to create new documentation pages. Content should be in Confluence storage format (HTML). Get the space key from list-confluence-spaces first. Be mindful of creating duplicate pages.").requires(["list-confluence-spaces"]).schema(zod.z.object({
|
|
1283
1283
|
space_key: zod.z.string().describe("The space key where the page will be created (e.g., 'AI', 'BL3')"),
|
|
1284
1284
|
title: zod.z.string().describe("The title of the new page"),
|
|
1285
1285
|
content: zod.z.string().describe("The page content in HTML format (Confluence storage format)"),
|
|
1286
1286
|
parent_page_id: zod.z.string().optional().describe("Optional parent page ID to create this as a child page")
|
|
1287
1287
|
})).implement(async ({ space_key, title, content, parent_page_id }) => {
|
|
1288
|
-
|
|
1288
|
+
logger23.info("create-confluence-page called", { space_key, title, hasParent: !!parent_page_id });
|
|
1289
1289
|
try {
|
|
1290
1290
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1291
1291
|
const pageData = {
|
|
@@ -1312,7 +1312,7 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1312
1312
|
}
|
|
1313
1313
|
}
|
|
1314
1314
|
);
|
|
1315
|
-
|
|
1315
|
+
logger23.info("create-confluence-page result", {
|
|
1316
1316
|
page_id: response.data.id,
|
|
1317
1317
|
title: response.data.title,
|
|
1318
1318
|
space: space_key
|
|
@@ -1328,7 +1328,7 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1328
1328
|
}
|
|
1329
1329
|
});
|
|
1330
1330
|
} catch (error) {
|
|
1331
|
-
|
|
1331
|
+
logger23.error("create-confluence-page error", {
|
|
1332
1332
|
space_key,
|
|
1333
1333
|
title,
|
|
1334
1334
|
error: error.response?.data?.message || error.message,
|
|
@@ -1341,13 +1341,13 @@ function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1341
1341
|
}
|
|
1342
1342
|
}).build();
|
|
1343
1343
|
}
|
|
1344
|
-
function createUpdateConfluencePageTool(getAuth, getAuthHeader2,
|
|
1344
|
+
function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
1345
1345
|
return core.toolBuilder().name("update-confluence-page").description("Update an existing Confluence page's content. Requires page ID, new title, and new content.").category(core.ToolCategory.WEB).tag("confluence").tag("update").tag("write").usageNotes("Use this to update existing documentation. You must provide the page ID (from search results). The tool will automatically handle version incrementing. Always get the current page content first to avoid overwriting important information.").requires(["get-confluence-page"]).schema(zod.z.object({
|
|
1346
1346
|
page_id: zod.z.string().describe("The ID of the page to update"),
|
|
1347
1347
|
title: zod.z.string().describe("The new title for the page"),
|
|
1348
1348
|
content: zod.z.string().describe("The new content in HTML format (Confluence storage format)")
|
|
1349
1349
|
})).implement(async ({ page_id, title, content }) => {
|
|
1350
|
-
|
|
1350
|
+
logger23.info("update-confluence-page called", { page_id, title });
|
|
1351
1351
|
try {
|
|
1352
1352
|
const { ATLASSIAN_SITE_URL } = getAuth();
|
|
1353
1353
|
const getResponse = await axios16__default.default.get(
|
|
@@ -1380,7 +1380,7 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1380
1380
|
}
|
|
1381
1381
|
}
|
|
1382
1382
|
);
|
|
1383
|
-
|
|
1383
|
+
logger23.info("update-confluence-page result", {
|
|
1384
1384
|
page_id,
|
|
1385
1385
|
title: updateResponse.data.title,
|
|
1386
1386
|
previousVersion: currentVersion,
|
|
@@ -1397,7 +1397,7 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1397
1397
|
}
|
|
1398
1398
|
});
|
|
1399
1399
|
} catch (error) {
|
|
1400
|
-
|
|
1400
|
+
logger23.error("update-confluence-page error", {
|
|
1401
1401
|
page_id,
|
|
1402
1402
|
title,
|
|
1403
1403
|
error: error.response?.data?.message || error.message,
|
|
@@ -1410,12 +1410,12 @@ function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1410
1410
|
}
|
|
1411
1411
|
}).build();
|
|
1412
1412
|
}
|
|
1413
|
-
function createArchiveConfluencePageTool(getAuth, getAuthHeader2,
|
|
1413
|
+
function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
1414
1414
|
return core.toolBuilder().name("archive-confluence-page").description("Archive a Confluence page by moving it to trash. The page can be restored by space admins. Note: UI may require a note explaining why the page was archived.").category(core.ToolCategory.WEB).tag("confluence").tag("archive").tag("delete").usageNotes("Use this to archive outdated or obsolete documentation. The page is moved to trash, not permanently deleted. Space admins can restore it if needed. Be very careful - only archive pages that are truly obsolete.").conflicts(["create-confluence-page"]).schema(zod.z.object({
|
|
1415
1415
|
page_id: zod.z.string().describe("The ID of the page to archive"),
|
|
1416
1416
|
reason: zod.z.string().optional().describe("Optional reason for archiving (for audit trail)")
|
|
1417
1417
|
})).implement(async ({ page_id, reason }) => {
|
|
1418
|
-
|
|
1418
|
+
logger23.info("archive-confluence-page called", {
|
|
1419
1419
|
page_id,
|
|
1420
1420
|
...reason ? { reason } : {}
|
|
1421
1421
|
});
|
|
@@ -1449,7 +1449,7 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1449
1449
|
}
|
|
1450
1450
|
}
|
|
1451
1451
|
);
|
|
1452
|
-
|
|
1452
|
+
logger23.info("archive-confluence-page result", {
|
|
1453
1453
|
page_id,
|
|
1454
1454
|
title: pageData.title,
|
|
1455
1455
|
previousVersion: currentVersion,
|
|
@@ -1467,7 +1467,7 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
|
1467
1467
|
}
|
|
1468
1468
|
});
|
|
1469
1469
|
} catch (error) {
|
|
1470
|
-
|
|
1470
|
+
logger23.error("archive-confluence-page error", {
|
|
1471
1471
|
page_id,
|
|
1472
1472
|
error: error.response?.data?.message || error.message,
|
|
1473
1473
|
status: error.response?.status
|
|
@@ -4044,7 +4044,8 @@ function quoteQualifiedIdentifier(qualifiedName, vendor) {
|
|
|
4044
4044
|
const parts = qualifiedName.split(".");
|
|
4045
4045
|
return parts.map((part) => quoteIdentifier(part, vendor)).join(".");
|
|
4046
4046
|
}
|
|
4047
|
-
|
|
4047
|
+
|
|
4048
|
+
// src/data/relational/connection/lifecycle.ts
|
|
4048
4049
|
var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
4049
4050
|
ConnectionState2["DISCONNECTED"] = "disconnected";
|
|
4050
4051
|
ConnectionState2["CONNECTING"] = "connecting";
|
|
@@ -4053,6 +4054,92 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
|
4053
4054
|
ConnectionState2["ERROR"] = "error";
|
|
4054
4055
|
return ConnectionState2;
|
|
4055
4056
|
})(ConnectionState || {});
|
|
4057
|
+
function cancelPendingReconnection(timer, logger23, vendor, message) {
|
|
4058
|
+
if (!timer) {
|
|
4059
|
+
return null;
|
|
4060
|
+
}
|
|
4061
|
+
logger23.debug(message, { vendor });
|
|
4062
|
+
clearTimeout(timer);
|
|
4063
|
+
return null;
|
|
4064
|
+
}
|
|
4065
|
+
async function waitForInFlightConnection(promise, logger23, vendor, phase) {
|
|
4066
|
+
if (!promise) {
|
|
4067
|
+
return null;
|
|
4068
|
+
}
|
|
4069
|
+
logger23.debug(`Waiting for in-flight connection attempt to complete before ${phase}`, {
|
|
4070
|
+
vendor
|
|
4071
|
+
});
|
|
4072
|
+
try {
|
|
4073
|
+
await promise;
|
|
4074
|
+
} catch {
|
|
4075
|
+
}
|
|
4076
|
+
return null;
|
|
4077
|
+
}
|
|
4078
|
+
function shutdownClient(vendor, client) {
|
|
4079
|
+
if (vendor === "postgresql" || vendor === "mysql") {
|
|
4080
|
+
return client.end();
|
|
4081
|
+
}
|
|
4082
|
+
if (vendor === "sqlite") {
|
|
4083
|
+
client.close();
|
|
4084
|
+
}
|
|
4085
|
+
}
|
|
4086
|
+
function scheduleReconnection(context, logger23) {
|
|
4087
|
+
if (context.reconnectionConfig.maxAttempts > 0 && context.reconnectionAttempts >= context.reconnectionConfig.maxAttempts) {
|
|
4088
|
+
logger23.error("Max reconnection attempts reached", {
|
|
4089
|
+
vendor: context.vendor,
|
|
4090
|
+
attempts: context.reconnectionAttempts,
|
|
4091
|
+
maxAttempts: context.reconnectionConfig.maxAttempts
|
|
4092
|
+
});
|
|
4093
|
+
return;
|
|
4094
|
+
}
|
|
4095
|
+
const delay2 = Math.min(
|
|
4096
|
+
context.reconnectionConfig.baseDelayMs * Math.pow(2, context.reconnectionAttempts),
|
|
4097
|
+
context.reconnectionConfig.maxDelayMs
|
|
4098
|
+
);
|
|
4099
|
+
const nextAttempt = context.reconnectionAttempts + 1;
|
|
4100
|
+
context.setReconnectionAttempts(nextAttempt);
|
|
4101
|
+
context.setState("reconnecting" /* RECONNECTING */);
|
|
4102
|
+
logger23.info("Scheduling reconnection attempt", {
|
|
4103
|
+
vendor: context.vendor,
|
|
4104
|
+
attempt: nextAttempt,
|
|
4105
|
+
maxAttempts: context.reconnectionConfig.maxAttempts,
|
|
4106
|
+
delayMs: delay2
|
|
4107
|
+
});
|
|
4108
|
+
context.emitReconnecting({
|
|
4109
|
+
attempt: nextAttempt,
|
|
4110
|
+
maxAttempts: context.reconnectionConfig.maxAttempts,
|
|
4111
|
+
delayMs: delay2
|
|
4112
|
+
});
|
|
4113
|
+
const timer = setTimeout(async () => {
|
|
4114
|
+
context.setReconnectionTimer(null);
|
|
4115
|
+
try {
|
|
4116
|
+
logger23.info("Attempting reconnection", {
|
|
4117
|
+
vendor: context.vendor,
|
|
4118
|
+
attempt: nextAttempt
|
|
4119
|
+
});
|
|
4120
|
+
const promise = context.initialize().finally(() => {
|
|
4121
|
+
context.setConnectPromise(null);
|
|
4122
|
+
});
|
|
4123
|
+
context.setConnectPromise(promise);
|
|
4124
|
+
await promise;
|
|
4125
|
+
} catch (error) {
|
|
4126
|
+
logger23.error("Reconnection attempt failed", {
|
|
4127
|
+
vendor: context.vendor,
|
|
4128
|
+
attempt: nextAttempt,
|
|
4129
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4130
|
+
});
|
|
4131
|
+
}
|
|
4132
|
+
}, delay2);
|
|
4133
|
+
context.setReconnectionTimer(timer);
|
|
4134
|
+
}
|
|
4135
|
+
var logger7 = core.createLogger("agentforge:tools:data:relational:connection:vendor-init");
|
|
4136
|
+
var SAFE_INITIALIZATION_PATTERNS = [
|
|
4137
|
+
"Pool max connections must be",
|
|
4138
|
+
"Pool acquire timeout must be",
|
|
4139
|
+
"Pool idle timeout must be",
|
|
4140
|
+
"SQLite connection requires a url property",
|
|
4141
|
+
"Unsupported database vendor"
|
|
4142
|
+
];
|
|
4056
4143
|
function validatePoolConfig(poolConfig) {
|
|
4057
4144
|
if (poolConfig.max !== void 0 && poolConfig.max < 1) {
|
|
4058
4145
|
throw new Error("Pool max connections must be >= 1");
|
|
@@ -4064,13 +4151,142 @@ function validatePoolConfig(poolConfig) {
|
|
|
4064
4151
|
throw new Error("Pool idle timeout must be >= 0");
|
|
4065
4152
|
}
|
|
4066
4153
|
}
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4154
|
+
function pickConfiguredPoolFields(fields) {
|
|
4155
|
+
const configuredEntries = Object.entries(fields).filter(
|
|
4156
|
+
(entry) => entry[1] !== void 0
|
|
4157
|
+
);
|
|
4158
|
+
return Object.fromEntries(configuredEntries);
|
|
4159
|
+
}
|
|
4160
|
+
function normalizePostgreSQLConfig(connection) {
|
|
4161
|
+
const { pool: poolConfig, ...baseConfig } = typeof connection === "string" ? { connectionString: connection } : connection;
|
|
4162
|
+
if (poolConfig) {
|
|
4163
|
+
validatePoolConfig(poolConfig);
|
|
4164
|
+
}
|
|
4165
|
+
return {
|
|
4166
|
+
poolConfig,
|
|
4167
|
+
connectionConfig: {
|
|
4168
|
+
...baseConfig,
|
|
4169
|
+
...poolConfig?.max !== void 0 && { max: poolConfig.max },
|
|
4170
|
+
...poolConfig?.idleTimeoutMillis !== void 0 && {
|
|
4171
|
+
idleTimeoutMillis: poolConfig.idleTimeoutMillis
|
|
4172
|
+
},
|
|
4173
|
+
...poolConfig?.acquireTimeoutMillis !== void 0 && {
|
|
4174
|
+
connectionTimeoutMillis: poolConfig.acquireTimeoutMillis
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
};
|
|
4178
|
+
}
|
|
4179
|
+
function normalizeMySQLConfig(connection) {
|
|
4180
|
+
if (typeof connection === "string") {
|
|
4181
|
+
logger7.debug("Creating MySQL connection pool from connection string", {
|
|
4182
|
+
vendor: "mysql"
|
|
4183
|
+
});
|
|
4184
|
+
return connection;
|
|
4185
|
+
}
|
|
4186
|
+
const { pool: poolConfig, ...baseConfig } = connection;
|
|
4187
|
+
if (poolConfig) {
|
|
4188
|
+
validatePoolConfig(poolConfig);
|
|
4189
|
+
}
|
|
4190
|
+
return {
|
|
4191
|
+
...baseConfig,
|
|
4192
|
+
...poolConfig?.max !== void 0 && { connectionLimit: poolConfig.max },
|
|
4193
|
+
...poolConfig?.acquireTimeoutMillis !== void 0 && {
|
|
4194
|
+
acquireTimeout: poolConfig.acquireTimeoutMillis
|
|
4195
|
+
},
|
|
4196
|
+
...poolConfig?.idleTimeoutMillis !== void 0 && {
|
|
4197
|
+
idleTimeout: poolConfig.idleTimeoutMillis
|
|
4198
|
+
}
|
|
4199
|
+
};
|
|
4200
|
+
}
|
|
4201
|
+
function resolveSqliteUrl(connection) {
|
|
4202
|
+
if (typeof connection === "string") {
|
|
4203
|
+
return { url: connection };
|
|
4204
|
+
}
|
|
4205
|
+
const { url, pool } = connection;
|
|
4206
|
+
if (!url) {
|
|
4207
|
+
throw new Error("SQLite connection requires a url property");
|
|
4208
|
+
}
|
|
4209
|
+
if (pool) {
|
|
4210
|
+
validatePoolConfig(pool);
|
|
4211
|
+
}
|
|
4212
|
+
return { url, poolConfig: pool };
|
|
4213
|
+
}
|
|
4214
|
+
async function initializeVendorConnection(config) {
|
|
4215
|
+
switch (config.vendor) {
|
|
4216
|
+
case "postgresql":
|
|
4217
|
+
return initializePostgreSQLConnection(config.connection);
|
|
4218
|
+
case "mysql":
|
|
4219
|
+
return initializeMySQLConnection(config.connection);
|
|
4220
|
+
case "sqlite":
|
|
4221
|
+
return initializeSQLiteConnection(config.connection);
|
|
4222
|
+
default:
|
|
4223
|
+
throw new Error(`Unsupported database vendor: ${config.vendor}`);
|
|
4224
|
+
}
|
|
4225
|
+
}
|
|
4226
|
+
async function initializePostgreSQLConnection(connection) {
|
|
4227
|
+
const { drizzle } = await import('drizzle-orm/node-postgres');
|
|
4228
|
+
const { Pool } = await import('pg');
|
|
4229
|
+
const { connectionConfig } = normalizePostgreSQLConfig(connection);
|
|
4230
|
+
logger7.debug("Creating PostgreSQL connection pool", {
|
|
4231
|
+
vendor: "postgresql",
|
|
4232
|
+
poolConfig: pickConfiguredPoolFields({
|
|
4233
|
+
max: connectionConfig.max,
|
|
4234
|
+
idleTimeoutMillis: connectionConfig.idleTimeoutMillis,
|
|
4235
|
+
connectionTimeoutMillis: connectionConfig.connectionTimeoutMillis
|
|
4236
|
+
})
|
|
4237
|
+
});
|
|
4238
|
+
const client = new Pool(connectionConfig);
|
|
4239
|
+
const db = drizzle({ client });
|
|
4240
|
+
return { client, db };
|
|
4241
|
+
}
|
|
4242
|
+
async function initializeMySQLConnection(connection) {
|
|
4243
|
+
const { drizzle } = await import('drizzle-orm/mysql2');
|
|
4244
|
+
const mysql = await import('mysql2/promise');
|
|
4245
|
+
const connectionConfig = normalizeMySQLConfig(connection);
|
|
4246
|
+
if (typeof connectionConfig !== "string") {
|
|
4247
|
+
logger7.debug("Creating MySQL connection pool", {
|
|
4248
|
+
vendor: "mysql",
|
|
4249
|
+
poolConfig: pickConfiguredPoolFields({
|
|
4250
|
+
connectionLimit: connectionConfig.connectionLimit,
|
|
4251
|
+
acquireTimeout: connectionConfig.acquireTimeout,
|
|
4252
|
+
idleTimeout: connectionConfig.idleTimeout
|
|
4253
|
+
})
|
|
4254
|
+
});
|
|
4255
|
+
}
|
|
4256
|
+
let client;
|
|
4257
|
+
if (typeof connectionConfig === "string") {
|
|
4258
|
+
client = mysql.createPool(connectionConfig);
|
|
4259
|
+
} else {
|
|
4260
|
+
client = mysql.createPool(connectionConfig);
|
|
4261
|
+
}
|
|
4262
|
+
const db = drizzle({ client });
|
|
4263
|
+
return { client, db };
|
|
4264
|
+
}
|
|
4265
|
+
async function initializeSQLiteConnection(connection) {
|
|
4266
|
+
const { drizzle } = await import('drizzle-orm/better-sqlite3');
|
|
4267
|
+
const DatabaseModule = await import('better-sqlite3');
|
|
4268
|
+
const Database = DatabaseModule.default;
|
|
4269
|
+
const { url, poolConfig } = resolveSqliteUrl(connection);
|
|
4270
|
+
if (poolConfig) {
|
|
4271
|
+
logger7.debug("SQLite pool configuration provided but not applied (SQLite uses single connection)", {
|
|
4272
|
+
vendor: "sqlite",
|
|
4273
|
+
poolConfig: pickConfiguredPoolFields({
|
|
4274
|
+
max: poolConfig.max,
|
|
4275
|
+
idleTimeoutMillis: poolConfig.idleTimeoutMillis,
|
|
4276
|
+
acquireTimeoutMillis: poolConfig.acquireTimeoutMillis
|
|
4277
|
+
})
|
|
4278
|
+
});
|
|
4279
|
+
}
|
|
4280
|
+
logger7.debug("Creating SQLite connection", {
|
|
4281
|
+
vendor: "sqlite",
|
|
4282
|
+
url: url === ":memory:" ? ":memory:" : "file"
|
|
4283
|
+
});
|
|
4284
|
+
const client = new Database(url);
|
|
4285
|
+
client.pragma("foreign_keys = ON");
|
|
4286
|
+
const db = drizzle({ client });
|
|
4287
|
+
return { client, db };
|
|
4288
|
+
}
|
|
4289
|
+
var logger8 = core.createLogger("agentforge:tools:data:relational:connection");
|
|
4074
4290
|
var ConnectionManager = class extends events.EventEmitter {
|
|
4075
4291
|
vendor;
|
|
4076
4292
|
db;
|
|
@@ -4110,23 +4326,22 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4110
4326
|
*/
|
|
4111
4327
|
async connect() {
|
|
4112
4328
|
if (this.state === "connected" /* CONNECTED */) {
|
|
4113
|
-
|
|
4329
|
+
logger8.debug("Already connected", { vendor: this.vendor });
|
|
4114
4330
|
return;
|
|
4115
4331
|
}
|
|
4116
4332
|
if (this.connectPromise) {
|
|
4117
|
-
|
|
4333
|
+
logger8.debug("Connection already in progress, waiting for completion", {
|
|
4118
4334
|
vendor: this.vendor,
|
|
4119
4335
|
state: this.state
|
|
4120
4336
|
});
|
|
4121
4337
|
return this.connectPromise;
|
|
4122
4338
|
}
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
}
|
|
4339
|
+
this.reconnectionTimer = cancelPendingReconnection(
|
|
4340
|
+
this.reconnectionTimer,
|
|
4341
|
+
logger8,
|
|
4342
|
+
this.vendor,
|
|
4343
|
+
"Clearing pending reconnection timer before manual connect"
|
|
4344
|
+
);
|
|
4130
4345
|
this.connectPromise = this.initialize().finally(() => {
|
|
4131
4346
|
this.connectPromise = null;
|
|
4132
4347
|
});
|
|
@@ -4141,21 +4356,19 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4141
4356
|
*/
|
|
4142
4357
|
async disconnect() {
|
|
4143
4358
|
this.connectionGeneration++;
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4359
|
+
this.reconnectionTimer = cancelPendingReconnection(
|
|
4360
|
+
this.reconnectionTimer,
|
|
4361
|
+
logger8,
|
|
4362
|
+
this.vendor,
|
|
4363
|
+
"Clearing pending reconnection timer before disconnect"
|
|
4364
|
+
);
|
|
4148
4365
|
this.reconnectionAttempts = 0;
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
} catch {
|
|
4156
|
-
}
|
|
4157
|
-
this.connectPromise = null;
|
|
4158
|
-
}
|
|
4366
|
+
this.connectPromise = await waitForInFlightConnection(
|
|
4367
|
+
this.connectPromise,
|
|
4368
|
+
logger8,
|
|
4369
|
+
this.vendor,
|
|
4370
|
+
"disconnect"
|
|
4371
|
+
);
|
|
4159
4372
|
await this.close();
|
|
4160
4373
|
}
|
|
4161
4374
|
/**
|
|
@@ -4200,7 +4413,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4200
4413
|
const startTime = Date.now();
|
|
4201
4414
|
const currentGeneration = this.connectionGeneration;
|
|
4202
4415
|
if (this.state === "connected" /* CONNECTED */ && this.client) {
|
|
4203
|
-
|
|
4416
|
+
logger8.warn("Re-initializing an already connected manager; emitting disconnected before cleanup", {
|
|
4204
4417
|
vendor: this.vendor
|
|
4205
4418
|
});
|
|
4206
4419
|
this.setState("disconnected" /* DISCONNECTED */);
|
|
@@ -4208,27 +4421,17 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4208
4421
|
await this.cleanupCancelledConnection();
|
|
4209
4422
|
}
|
|
4210
4423
|
this.setState("connecting" /* CONNECTING */);
|
|
4211
|
-
|
|
4424
|
+
logger8.info("Initializing database connection", {
|
|
4212
4425
|
vendor: this.vendor,
|
|
4213
4426
|
connectionType: typeof this.config.connection,
|
|
4214
4427
|
state: this.state
|
|
4215
4428
|
});
|
|
4216
4429
|
try {
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
break;
|
|
4221
|
-
case "mysql":
|
|
4222
|
-
await this.initializeMySQL();
|
|
4223
|
-
break;
|
|
4224
|
-
case "sqlite":
|
|
4225
|
-
await this.initializeSQLite();
|
|
4226
|
-
break;
|
|
4227
|
-
default:
|
|
4228
|
-
throw new Error(`Unsupported database vendor: ${this.vendor}`);
|
|
4229
|
-
}
|
|
4430
|
+
const initialized = await initializeVendorConnection(this.config);
|
|
4431
|
+
this.client = initialized.client;
|
|
4432
|
+
this.db = initialized.db;
|
|
4230
4433
|
if (currentGeneration !== this.connectionGeneration) {
|
|
4231
|
-
|
|
4434
|
+
logger8.debug("Connection cancelled during initialization", {
|
|
4232
4435
|
vendor: this.vendor,
|
|
4233
4436
|
currentGeneration,
|
|
4234
4437
|
newGeneration: this.connectionGeneration
|
|
@@ -4237,13 +4440,13 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4237
4440
|
this.setState("disconnected" /* DISCONNECTED */);
|
|
4238
4441
|
throw new Error("Connection cancelled during initialization");
|
|
4239
4442
|
}
|
|
4240
|
-
|
|
4443
|
+
logger8.debug("Validating connection health", { vendor: this.vendor });
|
|
4241
4444
|
const healthy = await this.isHealthy();
|
|
4242
4445
|
if (!healthy) {
|
|
4243
4446
|
throw new Error(`Failed to establish healthy connection to ${this.vendor} database`);
|
|
4244
4447
|
}
|
|
4245
4448
|
if (currentGeneration !== this.connectionGeneration) {
|
|
4246
|
-
|
|
4449
|
+
logger8.debug("Connection cancelled during health check", {
|
|
4247
4450
|
vendor: this.vendor,
|
|
4248
4451
|
currentGeneration,
|
|
4249
4452
|
newGeneration: this.connectionGeneration
|
|
@@ -4255,7 +4458,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4255
4458
|
this.setState("connected" /* CONNECTED */);
|
|
4256
4459
|
this.emit("connected");
|
|
4257
4460
|
this.reconnectionAttempts = 0;
|
|
4258
|
-
|
|
4461
|
+
logger8.info("Database connection initialized successfully", {
|
|
4259
4462
|
vendor: this.vendor,
|
|
4260
4463
|
duration: Date.now() - startTime,
|
|
4261
4464
|
state: this.state
|
|
@@ -4276,7 +4479,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4276
4479
|
if (this.listenerCount("error") > 0) {
|
|
4277
4480
|
this.emit("error", normalizedError);
|
|
4278
4481
|
}
|
|
4279
|
-
|
|
4482
|
+
logger8.error(errorMessage, {
|
|
4280
4483
|
vendor: this.vendor,
|
|
4281
4484
|
error: normalizedError.message,
|
|
4282
4485
|
duration: Date.now() - startTime,
|
|
@@ -4287,7 +4490,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4287
4490
|
this.scheduleReconnection();
|
|
4288
4491
|
}
|
|
4289
4492
|
} else {
|
|
4290
|
-
|
|
4493
|
+
logger8.debug("Connection initialization cancelled", {
|
|
4291
4494
|
vendor: this.vendor,
|
|
4292
4495
|
duration: Date.now() - startTime,
|
|
4293
4496
|
state: this.state
|
|
@@ -4308,7 +4511,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4308
4511
|
const oldState = this.state;
|
|
4309
4512
|
this.state = newState;
|
|
4310
4513
|
if (oldState !== newState) {
|
|
4311
|
-
|
|
4514
|
+
logger8.debug("Connection state changed", {
|
|
4312
4515
|
vendor: this.vendor,
|
|
4313
4516
|
oldState,
|
|
4314
4517
|
newState
|
|
@@ -4320,152 +4523,30 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4320
4523
|
* @private
|
|
4321
4524
|
*/
|
|
4322
4525
|
scheduleReconnection() {
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
vendor: this.vendor,
|
|
4326
|
-
attempts: this.reconnectionAttempts,
|
|
4327
|
-
maxAttempts: this.reconnectionConfig.maxAttempts
|
|
4328
|
-
});
|
|
4329
|
-
return;
|
|
4330
|
-
}
|
|
4331
|
-
const delay2 = Math.min(
|
|
4332
|
-
this.reconnectionConfig.baseDelayMs * Math.pow(2, this.reconnectionAttempts),
|
|
4333
|
-
this.reconnectionConfig.maxDelayMs
|
|
4334
|
-
);
|
|
4335
|
-
this.reconnectionAttempts++;
|
|
4336
|
-
this.setState("reconnecting" /* RECONNECTING */);
|
|
4337
|
-
logger7.info("Scheduling reconnection attempt", {
|
|
4338
|
-
vendor: this.vendor,
|
|
4339
|
-
attempt: this.reconnectionAttempts,
|
|
4340
|
-
maxAttempts: this.reconnectionConfig.maxAttempts,
|
|
4341
|
-
delayMs: delay2
|
|
4342
|
-
});
|
|
4343
|
-
this.emit("reconnecting", {
|
|
4344
|
-
attempt: this.reconnectionAttempts,
|
|
4345
|
-
maxAttempts: this.reconnectionConfig.maxAttempts,
|
|
4346
|
-
delayMs: delay2
|
|
4347
|
-
});
|
|
4348
|
-
this.reconnectionTimer = setTimeout(async () => {
|
|
4349
|
-
this.reconnectionTimer = null;
|
|
4350
|
-
try {
|
|
4351
|
-
logger7.info("Attempting reconnection", {
|
|
4352
|
-
vendor: this.vendor,
|
|
4353
|
-
attempt: this.reconnectionAttempts
|
|
4354
|
-
});
|
|
4355
|
-
this.connectPromise = this.initialize().finally(() => {
|
|
4356
|
-
this.connectPromise = null;
|
|
4357
|
-
});
|
|
4358
|
-
await this.connectPromise;
|
|
4359
|
-
} catch (error) {
|
|
4360
|
-
logger7.error("Reconnection attempt failed", {
|
|
4361
|
-
vendor: this.vendor,
|
|
4362
|
-
attempt: this.reconnectionAttempts,
|
|
4363
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4364
|
-
});
|
|
4365
|
-
}
|
|
4366
|
-
}, delay2);
|
|
4367
|
-
}
|
|
4368
|
-
/**
|
|
4369
|
-
* Initialize PostgreSQL connection using Drizzle ORM with node-postgres
|
|
4370
|
-
*
|
|
4371
|
-
* Applies pool configuration options to pg.Pool for connection management.
|
|
4372
|
-
*/
|
|
4373
|
-
async initializePostgreSQL() {
|
|
4374
|
-
const { drizzle } = await import('drizzle-orm/node-postgres');
|
|
4375
|
-
const { Pool } = await import('pg');
|
|
4376
|
-
const { pool: poolConfig, ...baseConfig } = typeof this.config.connection === "string" ? { connectionString: this.config.connection } : this.config.connection;
|
|
4377
|
-
if (poolConfig) {
|
|
4378
|
-
validatePoolConfig(poolConfig);
|
|
4379
|
-
}
|
|
4380
|
-
const connectionConfig = {
|
|
4381
|
-
...baseConfig,
|
|
4382
|
-
// Map our PoolConfig to pg.Pool options
|
|
4383
|
-
// Note: pg.Pool does not support a `min` option
|
|
4384
|
-
...poolConfig?.max !== void 0 && { max: poolConfig.max },
|
|
4385
|
-
...poolConfig?.idleTimeoutMillis !== void 0 && { idleTimeoutMillis: poolConfig.idleTimeoutMillis },
|
|
4386
|
-
...poolConfig?.acquireTimeoutMillis !== void 0 && { connectionTimeoutMillis: poolConfig.acquireTimeoutMillis }
|
|
4387
|
-
};
|
|
4388
|
-
logger7.debug("Creating PostgreSQL connection pool", {
|
|
4389
|
-
vendor: this.vendor,
|
|
4390
|
-
poolConfig: {
|
|
4391
|
-
...connectionConfig.max !== void 0 ? { max: connectionConfig.max } : {},
|
|
4392
|
-
...connectionConfig.idleTimeoutMillis !== void 0 ? { idleTimeoutMillis: connectionConfig.idleTimeoutMillis } : {},
|
|
4393
|
-
...connectionConfig.connectionTimeoutMillis !== void 0 ? { connectionTimeoutMillis: connectionConfig.connectionTimeoutMillis } : {}
|
|
4394
|
-
}
|
|
4395
|
-
});
|
|
4396
|
-
this.client = new Pool(connectionConfig);
|
|
4397
|
-
this.db = drizzle({ client: this.client });
|
|
4398
|
-
}
|
|
4399
|
-
/**
|
|
4400
|
-
* Initialize MySQL connection using Drizzle ORM with mysql2
|
|
4401
|
-
*
|
|
4402
|
-
* Applies pool configuration options to mysql2.createPool for connection management.
|
|
4403
|
-
*/
|
|
4404
|
-
async initializeMySQL() {
|
|
4405
|
-
const { drizzle } = await import('drizzle-orm/mysql2');
|
|
4406
|
-
const mysql = await import('mysql2/promise');
|
|
4407
|
-
let connectionConfig;
|
|
4408
|
-
if (typeof this.config.connection === "string") {
|
|
4409
|
-
connectionConfig = this.config.connection;
|
|
4410
|
-
logger7.debug("Creating MySQL connection pool from connection string", {
|
|
4411
|
-
vendor: this.vendor
|
|
4412
|
-
});
|
|
4413
|
-
} else {
|
|
4414
|
-
const { pool: poolConfig, ...baseConfig } = this.config.connection;
|
|
4415
|
-
if (poolConfig) {
|
|
4416
|
-
validatePoolConfig(poolConfig);
|
|
4417
|
-
}
|
|
4418
|
-
connectionConfig = {
|
|
4419
|
-
...baseConfig,
|
|
4420
|
-
// Map our PoolConfig to mysql2 pool options
|
|
4421
|
-
...poolConfig?.max !== void 0 && { connectionLimit: poolConfig.max },
|
|
4422
|
-
...poolConfig?.acquireTimeoutMillis !== void 0 && { acquireTimeout: poolConfig.acquireTimeoutMillis },
|
|
4423
|
-
...poolConfig?.idleTimeoutMillis !== void 0 && { idleTimeout: poolConfig.idleTimeoutMillis }
|
|
4424
|
-
};
|
|
4425
|
-
logger7.debug("Creating MySQL connection pool", {
|
|
4426
|
-
vendor: this.vendor,
|
|
4427
|
-
poolConfig: {
|
|
4428
|
-
...connectionConfig.connectionLimit !== void 0 ? { connectionLimit: connectionConfig.connectionLimit } : {},
|
|
4429
|
-
...connectionConfig.acquireTimeout !== void 0 ? { acquireTimeout: connectionConfig.acquireTimeout } : {},
|
|
4430
|
-
...connectionConfig.idleTimeout !== void 0 ? { idleTimeout: connectionConfig.idleTimeout } : {}
|
|
4431
|
-
}
|
|
4432
|
-
});
|
|
4433
|
-
}
|
|
4434
|
-
this.client = mysql.createPool(connectionConfig);
|
|
4435
|
-
this.db = drizzle({ client: this.client });
|
|
4436
|
-
}
|
|
4437
|
-
/**
|
|
4438
|
-
* Initialize SQLite connection using Drizzle ORM with better-sqlite3
|
|
4439
|
-
*
|
|
4440
|
-
* Note: SQLite uses a single connection. Pool configuration is logged but not applied
|
|
4441
|
-
* as SQLite handles concurrent access through its internal locking mechanism.
|
|
4442
|
-
*/
|
|
4443
|
-
async initializeSQLite() {
|
|
4444
|
-
const { drizzle } = await import('drizzle-orm/better-sqlite3');
|
|
4445
|
-
const DatabaseModule = await import('better-sqlite3');
|
|
4446
|
-
const Database = DatabaseModule.default;
|
|
4447
|
-
const url = typeof this.config.connection === "string" ? this.config.connection : this.config.connection.url;
|
|
4448
|
-
if (!url) {
|
|
4449
|
-
throw new Error("SQLite connection requires a url property");
|
|
4450
|
-
}
|
|
4451
|
-
if (typeof this.config.connection === "object" && this.config.connection.pool) {
|
|
4452
|
-
validatePoolConfig(this.config.connection.pool);
|
|
4453
|
-
logger7.debug("SQLite pool configuration provided but not applied (SQLite uses single connection)", {
|
|
4526
|
+
scheduleReconnection(
|
|
4527
|
+
{
|
|
4454
4528
|
vendor: this.vendor,
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4529
|
+
reconnectionConfig: this.reconnectionConfig,
|
|
4530
|
+
reconnectionAttempts: this.reconnectionAttempts,
|
|
4531
|
+
setReconnectionAttempts: (attempts) => {
|
|
4532
|
+
this.reconnectionAttempts = attempts;
|
|
4533
|
+
},
|
|
4534
|
+
setState: (state) => {
|
|
4535
|
+
this.setState(state);
|
|
4536
|
+
},
|
|
4537
|
+
emitReconnecting: (payload) => {
|
|
4538
|
+
this.emit("reconnecting", payload);
|
|
4539
|
+
},
|
|
4540
|
+
initialize: () => this.initialize(),
|
|
4541
|
+
setConnectPromise: (promise) => {
|
|
4542
|
+
this.connectPromise = promise;
|
|
4543
|
+
},
|
|
4544
|
+
setReconnectionTimer: (timer) => {
|
|
4545
|
+
this.reconnectionTimer = timer;
|
|
4459
4546
|
}
|
|
4460
|
-
}
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
vendor: this.vendor,
|
|
4464
|
-
url: url === ":memory:" ? ":memory:" : "file"
|
|
4465
|
-
});
|
|
4466
|
-
this.client = new Database(url);
|
|
4467
|
-
this.client.pragma("foreign_keys = ON");
|
|
4468
|
-
this.db = drizzle({ client: this.client });
|
|
4547
|
+
},
|
|
4548
|
+
logger8
|
|
4549
|
+
);
|
|
4469
4550
|
}
|
|
4470
4551
|
/**
|
|
4471
4552
|
* Determine whether an error thrown by drizzle-orm's better-sqlite3 adapter
|
|
@@ -4505,7 +4586,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4505
4586
|
if (!this.db) {
|
|
4506
4587
|
throw new Error("Database not initialized. Call initialize() first.");
|
|
4507
4588
|
}
|
|
4508
|
-
|
|
4589
|
+
logger8.debug("Executing SQL query", {
|
|
4509
4590
|
vendor: this.vendor
|
|
4510
4591
|
});
|
|
4511
4592
|
if (this.vendor === "sqlite") {
|
|
@@ -4635,42 +4716,33 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4635
4716
|
*/
|
|
4636
4717
|
async close() {
|
|
4637
4718
|
this.connectionGeneration++;
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
await this.connectPromise;
|
|
4651
|
-
} catch {
|
|
4652
|
-
}
|
|
4653
|
-
this.connectPromise = null;
|
|
4654
|
-
}
|
|
4719
|
+
this.reconnectionTimer = cancelPendingReconnection(
|
|
4720
|
+
this.reconnectionTimer,
|
|
4721
|
+
logger8,
|
|
4722
|
+
this.vendor,
|
|
4723
|
+
"Canceling pending reconnection timer during close"
|
|
4724
|
+
);
|
|
4725
|
+
this.connectPromise = await waitForInFlightConnection(
|
|
4726
|
+
this.connectPromise,
|
|
4727
|
+
logger8,
|
|
4728
|
+
this.vendor,
|
|
4729
|
+
"close"
|
|
4730
|
+
);
|
|
4655
4731
|
if (this.client) {
|
|
4656
|
-
|
|
4732
|
+
logger8.info("Closing database connection", {
|
|
4657
4733
|
vendor: this.vendor,
|
|
4658
4734
|
state: this.state
|
|
4659
4735
|
});
|
|
4660
4736
|
try {
|
|
4661
|
-
|
|
4662
|
-
await this.client.end();
|
|
4663
|
-
} else if (this.vendor === "sqlite") {
|
|
4664
|
-
this.client.close();
|
|
4665
|
-
}
|
|
4737
|
+
await shutdownClient(this.vendor, this.client);
|
|
4666
4738
|
this.setState("disconnected" /* DISCONNECTED */);
|
|
4667
4739
|
this.emit("disconnected");
|
|
4668
|
-
|
|
4740
|
+
logger8.debug("Database connection closed successfully", {
|
|
4669
4741
|
vendor: this.vendor,
|
|
4670
4742
|
state: this.state
|
|
4671
4743
|
});
|
|
4672
4744
|
} catch (error) {
|
|
4673
|
-
|
|
4745
|
+
logger8.error("Error closing database connection", {
|
|
4674
4746
|
vendor: this.vendor,
|
|
4675
4747
|
error: error instanceof Error ? error.message : String(error),
|
|
4676
4748
|
state: this.state
|
|
@@ -4695,17 +4767,13 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4695
4767
|
if (!this.client) {
|
|
4696
4768
|
return;
|
|
4697
4769
|
}
|
|
4698
|
-
|
|
4770
|
+
logger8.debug("Cleaning up cancelled connection", {
|
|
4699
4771
|
vendor: this.vendor
|
|
4700
4772
|
});
|
|
4701
4773
|
try {
|
|
4702
|
-
|
|
4703
|
-
await this.client.end();
|
|
4704
|
-
} else if (this.vendor === "sqlite") {
|
|
4705
|
-
this.client.close();
|
|
4706
|
-
}
|
|
4774
|
+
await shutdownClient(this.vendor, this.client);
|
|
4707
4775
|
} catch (error) {
|
|
4708
|
-
|
|
4776
|
+
logger8.debug("Error during cancelled connection cleanup", {
|
|
4709
4777
|
vendor: this.vendor,
|
|
4710
4778
|
error: error instanceof Error ? error.message : String(error)
|
|
4711
4779
|
});
|
|
@@ -4720,15 +4788,15 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4720
4788
|
*/
|
|
4721
4789
|
async isHealthy() {
|
|
4722
4790
|
if (!this.db || !this.client) {
|
|
4723
|
-
|
|
4791
|
+
logger8.debug("Health check failed: connection not initialized", { vendor: this.vendor });
|
|
4724
4792
|
return false;
|
|
4725
4793
|
}
|
|
4726
4794
|
try {
|
|
4727
4795
|
await this.execute(drizzleOrm.sql`SELECT 1`);
|
|
4728
|
-
|
|
4796
|
+
logger8.debug("Health check passed", { vendor: this.vendor });
|
|
4729
4797
|
return true;
|
|
4730
4798
|
} catch (error) {
|
|
4731
|
-
|
|
4799
|
+
logger8.debug("Health check failed", {
|
|
4732
4800
|
vendor: this.vendor,
|
|
4733
4801
|
error: error instanceof Error ? error.message : String(error)
|
|
4734
4802
|
});
|
|
@@ -4736,7 +4804,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4736
4804
|
}
|
|
4737
4805
|
}
|
|
4738
4806
|
};
|
|
4739
|
-
var
|
|
4807
|
+
var logger9 = core.createLogger("agentforge:tools:data:relational:query");
|
|
4740
4808
|
function buildParameterizedQuery(sqlString, params) {
|
|
4741
4809
|
if (!params) {
|
|
4742
4810
|
return drizzleOrm.sql.raw(sqlString);
|
|
@@ -4811,7 +4879,7 @@ function buildParameterizedQuery(sqlString, params) {
|
|
|
4811
4879
|
}
|
|
4812
4880
|
async function executeQuery(manager, input, context) {
|
|
4813
4881
|
const startTime = Date.now();
|
|
4814
|
-
|
|
4882
|
+
logger9.debug("Executing query", {
|
|
4815
4883
|
vendor: input.vendor,
|
|
4816
4884
|
hasParams: !!input.params,
|
|
4817
4885
|
paramCount: input.params ? Array.isArray(input.params) ? input.params.length : Object.keys(input.params).length : 0
|
|
@@ -4825,7 +4893,7 @@ async function executeQuery(manager, input, context) {
|
|
|
4825
4893
|
const executionTime = Date.now() - startTime;
|
|
4826
4894
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
4827
4895
|
const rowCount = result.rowCount || result.affectedRows || rows.length;
|
|
4828
|
-
|
|
4896
|
+
logger9.debug("Query executed successfully", {
|
|
4829
4897
|
vendor: input.vendor,
|
|
4830
4898
|
rowCount,
|
|
4831
4899
|
executionTime
|
|
@@ -4837,7 +4905,7 @@ async function executeQuery(manager, input, context) {
|
|
|
4837
4905
|
};
|
|
4838
4906
|
} catch (error) {
|
|
4839
4907
|
const executionTime = Date.now() - startTime;
|
|
4840
|
-
|
|
4908
|
+
logger9.error("Query execution failed", {
|
|
4841
4909
|
vendor: input.vendor,
|
|
4842
4910
|
error: error instanceof Error ? error.message : String(error),
|
|
4843
4911
|
executionTime
|
|
@@ -5261,7 +5329,7 @@ function buildSelectQuery(input) {
|
|
|
5261
5329
|
}
|
|
5262
5330
|
return query;
|
|
5263
5331
|
}
|
|
5264
|
-
var
|
|
5332
|
+
var logger10 = core.createLogger("agentforge:tools:data:relational:batch");
|
|
5265
5333
|
var DEFAULT_BATCH_SIZE = 100;
|
|
5266
5334
|
var MAX_BATCH_SIZE = 5e3;
|
|
5267
5335
|
var MAX_RETRY_ATTEMPTS = 5;
|
|
@@ -5312,7 +5380,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5312
5380
|
let successfulItems = 0;
|
|
5313
5381
|
let failedItems = 0;
|
|
5314
5382
|
let retries = 0;
|
|
5315
|
-
|
|
5383
|
+
logger10.debug("Starting batched execution", {
|
|
5316
5384
|
operation: task.operation,
|
|
5317
5385
|
totalItems: task.items.length,
|
|
5318
5386
|
totalBatches: batches.length,
|
|
@@ -5351,7 +5419,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5351
5419
|
lastError = error;
|
|
5352
5420
|
if (attempts <= resolved.maxRetries) {
|
|
5353
5421
|
retries += 1;
|
|
5354
|
-
|
|
5422
|
+
logger10.warn("Batch execution failed, retrying", {
|
|
5355
5423
|
operation: task.operation,
|
|
5356
5424
|
batchIndex,
|
|
5357
5425
|
attempts,
|
|
@@ -5390,7 +5458,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5390
5458
|
{ cause: lastError }
|
|
5391
5459
|
);
|
|
5392
5460
|
}
|
|
5393
|
-
|
|
5461
|
+
logger10.warn("Batch execution failed and was recorded for partial success", {
|
|
5394
5462
|
operation: task.operation,
|
|
5395
5463
|
batchIndex,
|
|
5396
5464
|
attempts,
|
|
@@ -5402,7 +5470,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5402
5470
|
}
|
|
5403
5471
|
const executionTime = Date.now() - startTime;
|
|
5404
5472
|
const partialSuccess = successfulItems > 0 && failedItems > 0;
|
|
5405
|
-
|
|
5473
|
+
logger10.debug("Batched execution completed", {
|
|
5406
5474
|
operation: task.operation,
|
|
5407
5475
|
totalItems: task.items.length,
|
|
5408
5476
|
successfulItems,
|
|
@@ -5446,7 +5514,7 @@ async function benchmarkBatchExecution(params) {
|
|
|
5446
5514
|
const timeSavedMs = Math.max(individualExecutionTime - batchedExecutionTime, 0);
|
|
5447
5515
|
const speedupRatio = batchedExecutionTime > 0 ? individualExecutionTime / batchedExecutionTime : 0;
|
|
5448
5516
|
const speedupPercent = individualExecutionTime > 0 ? timeSavedMs / individualExecutionTime * 100 : 0;
|
|
5449
|
-
|
|
5517
|
+
logger10.debug("Batch benchmark completed", {
|
|
5450
5518
|
itemCount: params.items.length,
|
|
5451
5519
|
batchCount: batches.length,
|
|
5452
5520
|
batchSize,
|
|
@@ -5466,7 +5534,7 @@ async function benchmarkBatchExecution(params) {
|
|
|
5466
5534
|
speedupPercent
|
|
5467
5535
|
};
|
|
5468
5536
|
}
|
|
5469
|
-
var
|
|
5537
|
+
var logger11 = core.createLogger("agentforge:tools:data:relational:stream");
|
|
5470
5538
|
var DEFAULT_CHUNK_SIZE = 100;
|
|
5471
5539
|
var MAX_CHUNK_SIZE = 5e3;
|
|
5472
5540
|
var DEFAULT_SAMPLE_SIZE = 50;
|
|
@@ -5599,7 +5667,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5599
5667
|
const endHeapUsed = process.memoryUsage().heapUsed;
|
|
5600
5668
|
peakHeapUsed = Math.max(peakHeapUsed, endHeapUsed);
|
|
5601
5669
|
const executionTime = Date.now() - startTime;
|
|
5602
|
-
|
|
5670
|
+
logger11.debug("Streaming SELECT execution completed", {
|
|
5603
5671
|
table: input.table,
|
|
5604
5672
|
vendor: input.vendor,
|
|
5605
5673
|
chunkCount,
|
|
@@ -5623,7 +5691,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5623
5691
|
};
|
|
5624
5692
|
}
|
|
5625
5693
|
async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
5626
|
-
|
|
5694
|
+
logger11.warn("Running streaming benchmark will execute the SELECT query twice (regular + streaming).", {
|
|
5627
5695
|
table: input.table,
|
|
5628
5696
|
vendor: input.vendor
|
|
5629
5697
|
});
|
|
@@ -5643,7 +5711,7 @@ async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
|
5643
5711
|
0
|
|
5644
5712
|
);
|
|
5645
5713
|
const memorySavedPercent = nonStreamingPeakHeapUsed > 0 ? memorySavedBytes / nonStreamingPeakHeapUsed * 100 : 0;
|
|
5646
|
-
|
|
5714
|
+
logger11.debug("Streaming benchmark completed", {
|
|
5647
5715
|
table: input.table,
|
|
5648
5716
|
vendor: input.vendor,
|
|
5649
5717
|
nonStreamingRows: nonStreamingRows.length,
|
|
@@ -5661,7 +5729,7 @@ async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
|
5661
5729
|
memorySavedPercent
|
|
5662
5730
|
};
|
|
5663
5731
|
}
|
|
5664
|
-
var
|
|
5732
|
+
var logger12 = core.createLogger("agentforge:tools:data:relational:transaction");
|
|
5665
5733
|
var transactionSequence = 0;
|
|
5666
5734
|
var SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
5667
5735
|
function toSqlIsolationLevel(level) {
|
|
@@ -5820,7 +5888,7 @@ var ManagedTransaction = class {
|
|
|
5820
5888
|
await this.executeQuery(drizzleOrm.sql.raw("PRAGMA read_uncommitted = 1"));
|
|
5821
5889
|
this.shouldRestoreSqliteReadUncommitted = true;
|
|
5822
5890
|
} else {
|
|
5823
|
-
|
|
5891
|
+
logger12.debug("Ignoring SQLite isolation level override", {
|
|
5824
5892
|
transactionId: this.id,
|
|
5825
5893
|
isolationLevel: this.options.isolationLevel
|
|
5826
5894
|
});
|
|
@@ -5845,7 +5913,7 @@ var ManagedTransaction = class {
|
|
|
5845
5913
|
const targetValue = this.sqliteReadUncommittedOriginal ?? 0;
|
|
5846
5914
|
await this.executeQuery(drizzleOrm.sql.raw(`PRAGMA read_uncommitted = ${targetValue}`));
|
|
5847
5915
|
} catch (error) {
|
|
5848
|
-
|
|
5916
|
+
logger12.warn("Failed to restore SQLite read_uncommitted pragma", {
|
|
5849
5917
|
transactionId: this.id,
|
|
5850
5918
|
error: error instanceof Error ? error.message : String(error)
|
|
5851
5919
|
});
|
|
@@ -5874,7 +5942,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
5874
5942
|
const resolvedOptions = resolveOptions2(options);
|
|
5875
5943
|
const transactionId = `tx-${++transactionSequence}`;
|
|
5876
5944
|
const vendor = manager.getVendor();
|
|
5877
|
-
|
|
5945
|
+
logger12.debug("Starting transaction", {
|
|
5878
5946
|
transactionId,
|
|
5879
5947
|
vendor,
|
|
5880
5948
|
...resolvedOptions.isolationLevel ? { isolationLevel: resolvedOptions.isolationLevel } : {},
|
|
@@ -5901,7 +5969,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
5901
5969
|
if (transaction.isActive()) {
|
|
5902
5970
|
await transaction.commit();
|
|
5903
5971
|
}
|
|
5904
|
-
|
|
5972
|
+
logger12.debug("Transaction committed", {
|
|
5905
5973
|
transactionId,
|
|
5906
5974
|
vendor,
|
|
5907
5975
|
duration: Date.now() - startTime
|
|
@@ -5912,14 +5980,14 @@ async function withTransaction(manager, operation, options) {
|
|
|
5912
5980
|
try {
|
|
5913
5981
|
await transaction.rollback();
|
|
5914
5982
|
} catch (rollbackError) {
|
|
5915
|
-
|
|
5983
|
+
logger12.error("Transaction rollback failed", {
|
|
5916
5984
|
transactionId,
|
|
5917
5985
|
vendor,
|
|
5918
5986
|
error: rollbackError instanceof Error ? rollbackError.message : String(rollbackError)
|
|
5919
5987
|
});
|
|
5920
5988
|
}
|
|
5921
5989
|
}
|
|
5922
|
-
|
|
5990
|
+
logger12.error("Transaction failed", {
|
|
5923
5991
|
transactionId,
|
|
5924
5992
|
vendor,
|
|
5925
5993
|
duration: Date.now() - startTime,
|
|
@@ -5934,7 +6002,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
5934
6002
|
var VALID_TABLE_FILTER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)?$/;
|
|
5935
6003
|
|
|
5936
6004
|
// src/data/relational/schema/schema-inspector.ts
|
|
5937
|
-
var
|
|
6005
|
+
var logger13 = core.createLogger("agentforge:tools:data:relational:schema-inspector");
|
|
5938
6006
|
var DEFAULT_CACHE_TTL_MS = 6e4;
|
|
5939
6007
|
var schemaCache = /* @__PURE__ */ new Map();
|
|
5940
6008
|
var POSTGRES_TABLES_QUERY = `
|
|
@@ -6224,7 +6292,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6224
6292
|
if (!bypassCache && this.cacheKey) {
|
|
6225
6293
|
const cached = schemaCache.get(this.cacheKey);
|
|
6226
6294
|
if (cached && cached.expiresAt > Date.now()) {
|
|
6227
|
-
|
|
6295
|
+
logger13.debug("Schema cache hit", { vendor: this.vendor });
|
|
6228
6296
|
return filterSchemaTables(cloneSchema(cached.schema), tableFilters);
|
|
6229
6297
|
}
|
|
6230
6298
|
}
|
|
@@ -6491,7 +6559,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6491
6559
|
}
|
|
6492
6560
|
}
|
|
6493
6561
|
};
|
|
6494
|
-
var
|
|
6562
|
+
var logger14 = core.createLogger("agentforge:tools:data:relational:schema-validator");
|
|
6495
6563
|
function validateTableExists(schema, tableName) {
|
|
6496
6564
|
const errors = [];
|
|
6497
6565
|
if (!tableName || typeof tableName !== "string") {
|
|
@@ -6505,7 +6573,7 @@ function validateTableExists(schema, tableName) {
|
|
|
6505
6573
|
`Table "${tableName}" does not exist. Available tables: ${available || "(none)"}`
|
|
6506
6574
|
);
|
|
6507
6575
|
}
|
|
6508
|
-
|
|
6576
|
+
logger14.debug("Table existence validation", { tableName, valid: errors.length === 0 });
|
|
6509
6577
|
return { valid: errors.length === 0, errors };
|
|
6510
6578
|
}
|
|
6511
6579
|
function validateColumnsExist(schema, tableName, columnNames) {
|
|
@@ -6528,7 +6596,7 @@ function validateColumnsExist(schema, tableName, columnNames) {
|
|
|
6528
6596
|
);
|
|
6529
6597
|
}
|
|
6530
6598
|
}
|
|
6531
|
-
|
|
6599
|
+
logger14.debug("Column existence validation", {
|
|
6532
6600
|
tableName,
|
|
6533
6601
|
columnCount: columnNames.length,
|
|
6534
6602
|
valid: errors.length === 0
|
|
@@ -6564,7 +6632,7 @@ function validateColumnTypes(schema, tableName, expectedTypes) {
|
|
|
6564
6632
|
);
|
|
6565
6633
|
}
|
|
6566
6634
|
}
|
|
6567
|
-
|
|
6635
|
+
logger14.debug("Column type validation", {
|
|
6568
6636
|
tableName,
|
|
6569
6637
|
typeChecks: Object.keys(expectedTypes).length,
|
|
6570
6638
|
valid: errors.length === 0
|
|
@@ -6584,7 +6652,7 @@ function findTable(schema, tableName) {
|
|
|
6584
6652
|
function formatTableName(table) {
|
|
6585
6653
|
return table.schema ? `${table.schema}.${table.name}` : table.name;
|
|
6586
6654
|
}
|
|
6587
|
-
var
|
|
6655
|
+
var logger15 = core.createLogger("agentforge:tools:data:relational:type-mapper");
|
|
6588
6656
|
var POSTGRES_TYPE_MAP = {
|
|
6589
6657
|
// Numeric
|
|
6590
6658
|
smallint: "number",
|
|
@@ -6750,7 +6818,7 @@ function mapColumnType(vendor, dbType, nullable = false) {
|
|
|
6750
6818
|
const result = { tsType, nullable, dbType };
|
|
6751
6819
|
if (tsType === "unknown" && normalised !== "json" && normalised !== "jsonb") {
|
|
6752
6820
|
result.notes = `No explicit mapping for "${dbType}"; defaulting to unknown`;
|
|
6753
|
-
|
|
6821
|
+
logger15.debug("Unmapped database type", { vendor, dbType, normalised });
|
|
6754
6822
|
}
|
|
6755
6823
|
if ((normalised === "bigint" || normalised === "int8" || normalised === "bigserial") && (vendor === "postgresql" || vendor === "mysql")) {
|
|
6756
6824
|
result.notes = "Mapped to string to avoid JavaScript number precision loss for 64-bit integers";
|
|
@@ -6765,7 +6833,7 @@ function mapSchemaTypes(vendor, columns) {
|
|
|
6765
6833
|
}
|
|
6766
6834
|
result.get(col.table).set(col.name, mapColumnType(vendor, col.type, col.nullable));
|
|
6767
6835
|
}
|
|
6768
|
-
|
|
6836
|
+
logger15.debug("Schema type mapping complete", {
|
|
6769
6837
|
vendor,
|
|
6770
6838
|
tables: result.size,
|
|
6771
6839
|
columns: columns.length
|
|
@@ -6782,7 +6850,7 @@ function normaliseDbType(raw) {
|
|
|
6782
6850
|
type = type.replace(/\s+unsigned$/, "");
|
|
6783
6851
|
return type.trim();
|
|
6784
6852
|
}
|
|
6785
|
-
var
|
|
6853
|
+
var logger16 = core.createLogger("agentforge:tools:data:relational:schema-diff");
|
|
6786
6854
|
function diffSchemas(before, after) {
|
|
6787
6855
|
const tableDiffs = [];
|
|
6788
6856
|
let columnsAdded = 0;
|
|
@@ -6822,7 +6890,7 @@ function diffSchemas(before, after) {
|
|
|
6822
6890
|
const tablesRemoved = tableDiffs.filter((d) => d.type === "removed").length;
|
|
6823
6891
|
const tablesChanged = tableDiffs.filter((d) => d.type === "changed").length;
|
|
6824
6892
|
const identical = tableDiffs.length === 0;
|
|
6825
|
-
|
|
6893
|
+
logger16.debug("Schema diff computed", {
|
|
6826
6894
|
identical,
|
|
6827
6895
|
tablesAdded,
|
|
6828
6896
|
tablesRemoved,
|
|
@@ -6866,7 +6934,7 @@ function importSchemaFromJson(json) {
|
|
|
6866
6934
|
throw new Error(`Invalid schema JSON: table "${table.name}" missing "primaryKey" array`);
|
|
6867
6935
|
}
|
|
6868
6936
|
}
|
|
6869
|
-
|
|
6937
|
+
logger16.debug("Schema imported from JSON", {
|
|
6870
6938
|
vendor: obj.vendor,
|
|
6871
6939
|
tableCount: obj.tables.length
|
|
6872
6940
|
});
|
|
@@ -7163,7 +7231,7 @@ function isSafeValidationError(error) {
|
|
|
7163
7231
|
}
|
|
7164
7232
|
|
|
7165
7233
|
// src/data/relational/tools/relational-select/executor.ts
|
|
7166
|
-
var
|
|
7234
|
+
var logger17 = core.createLogger("agentforge:tools:data:relational:select");
|
|
7167
7235
|
function toSelectQueryInput(input) {
|
|
7168
7236
|
return {
|
|
7169
7237
|
table: input.table,
|
|
@@ -7177,7 +7245,7 @@ function toSelectQueryInput(input) {
|
|
|
7177
7245
|
}
|
|
7178
7246
|
async function executeSelect(manager, input, context) {
|
|
7179
7247
|
const startTime = Date.now();
|
|
7180
|
-
|
|
7248
|
+
logger17.debug("Building SELECT query", {
|
|
7181
7249
|
vendor: input.vendor,
|
|
7182
7250
|
table: input.table,
|
|
7183
7251
|
hasWhere: !!input.where,
|
|
@@ -7195,7 +7263,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7195
7263
|
};
|
|
7196
7264
|
const streamInput = toSelectQueryInput(input);
|
|
7197
7265
|
if (input.streaming.benchmark) {
|
|
7198
|
-
|
|
7266
|
+
logger17.warn("Streaming benchmark enabled; SELECT will execute up to three times (result + benchmark regular + benchmark streaming).", {
|
|
7199
7267
|
vendor: input.vendor,
|
|
7200
7268
|
table: input.table,
|
|
7201
7269
|
chunkSize: streamOptions.chunkSize ?? DEFAULT_CHUNK_SIZE,
|
|
@@ -7206,7 +7274,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7206
7274
|
const streamResult = await executeStreamingSelect(executor, streamInput, streamOptions);
|
|
7207
7275
|
const benchmark = input.streaming.benchmark ? await benchmarkStreamingSelectMemory(executor, streamInput, streamOptions) : void 0;
|
|
7208
7276
|
const executionTime2 = Date.now() - startTime;
|
|
7209
|
-
|
|
7277
|
+
logger17.debug("Streaming SELECT query executed successfully", {
|
|
7210
7278
|
vendor: input.vendor,
|
|
7211
7279
|
table: input.table,
|
|
7212
7280
|
rowCount: streamResult.rowCount,
|
|
@@ -7235,7 +7303,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7235
7303
|
const executionTime = Date.now() - startTime;
|
|
7236
7304
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
7237
7305
|
const rowCount = rows.length;
|
|
7238
|
-
|
|
7306
|
+
logger17.debug("SELECT query executed successfully", {
|
|
7239
7307
|
vendor: input.vendor,
|
|
7240
7308
|
table: input.table,
|
|
7241
7309
|
rowCount,
|
|
@@ -7248,7 +7316,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7248
7316
|
};
|
|
7249
7317
|
} catch (error) {
|
|
7250
7318
|
const executionTime = Date.now() - startTime;
|
|
7251
|
-
|
|
7319
|
+
logger17.error("SELECT query execution failed", {
|
|
7252
7320
|
vendor: input.vendor,
|
|
7253
7321
|
table: input.table,
|
|
7254
7322
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -7424,7 +7492,7 @@ function isSafeInsertError(error) {
|
|
|
7424
7492
|
}
|
|
7425
7493
|
|
|
7426
7494
|
// src/data/relational/tools/relational-insert/executor.ts
|
|
7427
|
-
var
|
|
7495
|
+
var logger18 = core.createLogger("agentforge:tools:data:relational:insert");
|
|
7428
7496
|
function toNumber(value) {
|
|
7429
7497
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7430
7498
|
}
|
|
@@ -7573,7 +7641,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7573
7641
|
maxRetries: options.maxRetries,
|
|
7574
7642
|
retryDelayMs: options.retryDelayMs,
|
|
7575
7643
|
onProgress: (progress) => {
|
|
7576
|
-
|
|
7644
|
+
logger18.debug("INSERT batch progress", {
|
|
7577
7645
|
vendor: input.vendor,
|
|
7578
7646
|
table: input.table,
|
|
7579
7647
|
...progress
|
|
@@ -7586,7 +7654,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7586
7654
|
const insertedIds = batchResult.results.flatMap((result) => result.insertedIds);
|
|
7587
7655
|
let benchmark;
|
|
7588
7656
|
if (options.benchmark) {
|
|
7589
|
-
|
|
7657
|
+
logger18.warn("INSERT batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
7590
7658
|
vendor: input.vendor,
|
|
7591
7659
|
table: input.table,
|
|
7592
7660
|
totalRows: input.data.length,
|
|
@@ -7623,7 +7691,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7623
7691
|
}
|
|
7624
7692
|
async function executeInsert(manager, input, context) {
|
|
7625
7693
|
const startTime = Date.now();
|
|
7626
|
-
|
|
7694
|
+
logger18.debug("Building INSERT query", {
|
|
7627
7695
|
vendor: input.vendor,
|
|
7628
7696
|
table: input.table,
|
|
7629
7697
|
isBatch: Array.isArray(input.data),
|
|
@@ -7639,7 +7707,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7639
7707
|
batchOptions
|
|
7640
7708
|
) : await executeInsertOnce(manager, input, context);
|
|
7641
7709
|
const executionTime = Date.now() - startTime;
|
|
7642
|
-
|
|
7710
|
+
logger18.debug("INSERT query executed successfully", {
|
|
7643
7711
|
vendor: input.vendor,
|
|
7644
7712
|
table: input.table,
|
|
7645
7713
|
rowCount: result.rowCount,
|
|
@@ -7655,7 +7723,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7655
7723
|
};
|
|
7656
7724
|
} catch (error) {
|
|
7657
7725
|
const executionTime = Date.now() - startTime;
|
|
7658
|
-
|
|
7726
|
+
logger18.error("INSERT query execution failed", {
|
|
7659
7727
|
vendor: input.vendor,
|
|
7660
7728
|
table: input.table,
|
|
7661
7729
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -7985,7 +8053,7 @@ function isSafeUpdateError(error) {
|
|
|
7985
8053
|
}
|
|
7986
8054
|
|
|
7987
8055
|
// src/data/relational/tools/relational-update/executor.ts
|
|
7988
|
-
var
|
|
8056
|
+
var logger19 = core.createLogger("agentforge:tools:data:relational:update");
|
|
7989
8057
|
function toNumber2(value) {
|
|
7990
8058
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7991
8059
|
}
|
|
@@ -8107,7 +8175,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8107
8175
|
maxRetries: options.maxRetries,
|
|
8108
8176
|
retryDelayMs: options.retryDelayMs,
|
|
8109
8177
|
onProgress: (progress) => {
|
|
8110
|
-
|
|
8178
|
+
logger19.debug("UPDATE batch progress", {
|
|
8111
8179
|
vendor: input.vendor,
|
|
8112
8180
|
table: input.table,
|
|
8113
8181
|
...progress
|
|
@@ -8119,7 +8187,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8119
8187
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8120
8188
|
let benchmark;
|
|
8121
8189
|
if (options.benchmark) {
|
|
8122
|
-
|
|
8190
|
+
logger19.warn("UPDATE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8123
8191
|
vendor: input.vendor,
|
|
8124
8192
|
table: input.table,
|
|
8125
8193
|
operationCount: input.operations.length,
|
|
@@ -8154,7 +8222,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8154
8222
|
}
|
|
8155
8223
|
async function executeUpdate(manager, input, context) {
|
|
8156
8224
|
const startTime = Date.now();
|
|
8157
|
-
|
|
8225
|
+
logger19.debug("Building UPDATE query", {
|
|
8158
8226
|
vendor: input.vendor,
|
|
8159
8227
|
table: input.table,
|
|
8160
8228
|
hasWhere: !!input.where?.length,
|
|
@@ -8172,7 +8240,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8172
8240
|
batchOptions
|
|
8173
8241
|
) : await executeSingleUpdate(manager, input, toSingleUpdateOperation(input), context);
|
|
8174
8242
|
const executionTime = Date.now() - startTime;
|
|
8175
|
-
|
|
8243
|
+
logger19.debug("UPDATE query executed successfully", {
|
|
8176
8244
|
vendor: input.vendor,
|
|
8177
8245
|
table: input.table,
|
|
8178
8246
|
rowCount: result.rowCount,
|
|
@@ -8186,7 +8254,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8186
8254
|
};
|
|
8187
8255
|
} catch (error) {
|
|
8188
8256
|
const executionTime = Date.now() - startTime;
|
|
8189
|
-
|
|
8257
|
+
logger19.error("UPDATE query execution failed", {
|
|
8190
8258
|
vendor: input.vendor,
|
|
8191
8259
|
table: input.table,
|
|
8192
8260
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8490,7 +8558,7 @@ function isSafeDeleteError(error) {
|
|
|
8490
8558
|
}
|
|
8491
8559
|
|
|
8492
8560
|
// src/data/relational/tools/relational-delete/executor.ts
|
|
8493
|
-
var
|
|
8561
|
+
var logger20 = core.createLogger("agentforge:tools:data:relational:delete");
|
|
8494
8562
|
function toNumber3(value) {
|
|
8495
8563
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8496
8564
|
}
|
|
@@ -8611,7 +8679,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8611
8679
|
maxRetries: options.maxRetries,
|
|
8612
8680
|
retryDelayMs: options.retryDelayMs,
|
|
8613
8681
|
onProgress: (progress) => {
|
|
8614
|
-
|
|
8682
|
+
logger20.debug("DELETE batch progress", {
|
|
8615
8683
|
vendor: input.vendor,
|
|
8616
8684
|
table: input.table,
|
|
8617
8685
|
...progress
|
|
@@ -8624,7 +8692,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8624
8692
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8625
8693
|
let benchmark;
|
|
8626
8694
|
if (options.benchmark) {
|
|
8627
|
-
|
|
8695
|
+
logger20.warn("DELETE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8628
8696
|
vendor: input.vendor,
|
|
8629
8697
|
table: input.table,
|
|
8630
8698
|
operationCount: input.operations.length,
|
|
@@ -8660,7 +8728,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8660
8728
|
}
|
|
8661
8729
|
async function executeDelete(manager, input, context) {
|
|
8662
8730
|
const startTime = Date.now();
|
|
8663
|
-
|
|
8731
|
+
logger20.debug("Building DELETE query", {
|
|
8664
8732
|
vendor: input.vendor,
|
|
8665
8733
|
table: input.table,
|
|
8666
8734
|
hasWhere: !!input.where?.length,
|
|
@@ -8679,7 +8747,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8679
8747
|
batchOptions
|
|
8680
8748
|
) : await executeSingleDelete(manager, input, toSingleDeleteOperation(input), context);
|
|
8681
8749
|
const executionTime = Date.now() - startTime;
|
|
8682
|
-
|
|
8750
|
+
logger20.debug("DELETE query executed successfully", {
|
|
8683
8751
|
vendor: input.vendor,
|
|
8684
8752
|
table: input.table,
|
|
8685
8753
|
rowCount: result.rowCount,
|
|
@@ -8695,7 +8763,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8695
8763
|
};
|
|
8696
8764
|
} catch (error) {
|
|
8697
8765
|
const executionTime = Date.now() - startTime;
|
|
8698
|
-
|
|
8766
|
+
logger20.error("DELETE query execution failed", {
|
|
8699
8767
|
vendor: input.vendor,
|
|
8700
8768
|
table: input.table,
|
|
8701
8769
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8800,7 +8868,7 @@ function isSafeGetSchemaValidationError(error) {
|
|
|
8800
8868
|
}
|
|
8801
8869
|
|
|
8802
8870
|
// src/data/relational/tools/relational-get-schema.ts
|
|
8803
|
-
var
|
|
8871
|
+
var logger21 = core.createLogger("agentforge:tools:data:relational:get-schema");
|
|
8804
8872
|
function buildSchemaCacheKey(vendor, connectionString, database) {
|
|
8805
8873
|
const databaseScope = database ?? "default";
|
|
8806
8874
|
const connectionHash = crypto.createHash("sha256").update(connectionString).digest("hex");
|
|
@@ -8872,7 +8940,7 @@ var relationalGetSchema = core.toolBuilder().name("relational-get-schema").displ
|
|
|
8872
8940
|
summary
|
|
8873
8941
|
};
|
|
8874
8942
|
} catch (error) {
|
|
8875
|
-
|
|
8943
|
+
logger21.error("Schema introspection failed", {
|
|
8876
8944
|
vendor: input.vendor,
|
|
8877
8945
|
hasTablesFilter: Array.isArray(input.tables),
|
|
8878
8946
|
tablesFilterCount: input.tables?.length ?? 0,
|
|
@@ -10038,7 +10106,7 @@ var AskHumanInputSchema = zod.z.object({
|
|
|
10038
10106
|
suggestions: zod.z.array(zod.z.string()).optional().describe("Suggested responses for the human")
|
|
10039
10107
|
});
|
|
10040
10108
|
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
|
|
10041
|
-
var
|
|
10109
|
+
var logger22 = core.createLogger("agentforge:tools:agent:ask-human", { level: logLevel3 });
|
|
10042
10110
|
function isRecord(value) {
|
|
10043
10111
|
return typeof value === "object" && value !== null;
|
|
10044
10112
|
}
|
|
@@ -10103,7 +10171,7 @@ function createAskHumanTool() {
|
|
|
10103
10171
|
suggestions: validatedInput.suggestions,
|
|
10104
10172
|
status: "pending"
|
|
10105
10173
|
};
|
|
10106
|
-
|
|
10174
|
+
logger22.debug("About to call interrupt()", {
|
|
10107
10175
|
humanRequest: {
|
|
10108
10176
|
id: humanRequest.id,
|
|
10109
10177
|
question: humanRequest.question,
|
|
@@ -10119,13 +10187,13 @@ function createAskHumanTool() {
|
|
|
10119
10187
|
let response;
|
|
10120
10188
|
try {
|
|
10121
10189
|
response = interrupt(humanRequest);
|
|
10122
|
-
|
|
10190
|
+
logger22.debug("interrupt() returned successfully", {
|
|
10123
10191
|
responseType: typeof response,
|
|
10124
10192
|
hasResponse: response != null,
|
|
10125
10193
|
...typeof response === "string" ? { responseLength: response.length } : {}
|
|
10126
10194
|
});
|
|
10127
10195
|
} catch (error) {
|
|
10128
|
-
|
|
10196
|
+
logger22.debug("interrupt() threw error (expected for GraphInterrupt)", {
|
|
10129
10197
|
...error && typeof error === "object" && "constructor" in error ? { errorType: error.constructor?.name } : {},
|
|
10130
10198
|
error: error instanceof Error ? error.message : String(error)
|
|
10131
10199
|
});
|