@agentforge/tools 0.16.55 → 0.16.57
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 +384 -337
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -9
- package/dist/index.d.ts +1 -9
- package/dist/index.js +384 -337
- 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, logger22) {
|
|
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, logger23) {
|
|
|
797
797
|
message: z.string().describe("Message content to send")
|
|
798
798
|
})
|
|
799
799
|
).implementSafe(async ({ channel, message }) => {
|
|
800
|
-
|
|
800
|
+
logger22.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, logger23) {
|
|
|
806
806
|
username: config.botName,
|
|
807
807
|
icon_emoji: config.botIcon
|
|
808
808
|
});
|
|
809
|
-
|
|
809
|
+
logger22.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, logger23) {
|
|
|
819
819
|
message_id: result.ts
|
|
820
820
|
};
|
|
821
821
|
} catch (error) {
|
|
822
|
-
|
|
822
|
+
logger22.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, logger23) {
|
|
|
828
828
|
}
|
|
829
829
|
}).build();
|
|
830
830
|
}
|
|
831
|
-
function createNotifySlackTool(getSlackClient,
|
|
831
|
+
function createNotifySlackTool(getSlackClient, logger22) {
|
|
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, logger23) {
|
|
|
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
|
+
logger22.info("notify-slack called", {
|
|
842
842
|
channel,
|
|
843
843
|
messageLength: message.length,
|
|
844
844
|
mentionCount: mentions.length
|
|
@@ -852,7 +852,7 @@ function createNotifySlackTool(getSlackClient, logger23) {
|
|
|
852
852
|
username: config.botName,
|
|
853
853
|
icon_emoji: config.botIcon
|
|
854
854
|
});
|
|
855
|
-
|
|
855
|
+
logger22.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, logger23) {
|
|
|
866
866
|
};
|
|
867
867
|
}).build();
|
|
868
868
|
}
|
|
869
|
-
function createGetSlackChannelsTool(getSlackClient,
|
|
869
|
+
function createGetSlackChannelsTool(getSlackClient, logger22) {
|
|
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, logger23) {
|
|
|
874
874
|
include_private: z.boolean().optional().describe("Include private channels (default: false)")
|
|
875
875
|
})
|
|
876
876
|
).implementSafe(async ({ include_private = false }) => {
|
|
877
|
-
|
|
877
|
+
logger22.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, logger23) {
|
|
|
888
888
|
});
|
|
889
889
|
allChannels = [...allChannels, ...privateChannels.channels || []];
|
|
890
890
|
}
|
|
891
|
-
|
|
891
|
+
logger22.info("get-slack-channels result", {
|
|
892
892
|
channelCount: allChannels.length,
|
|
893
893
|
includePrivate: include_private
|
|
894
894
|
});
|
|
@@ -903,7 +903,7 @@ function createGetSlackChannelsTool(getSlackClient, logger23) {
|
|
|
903
903
|
};
|
|
904
904
|
}).build();
|
|
905
905
|
}
|
|
906
|
-
function createGetSlackMessagesTool(getSlackClient,
|
|
906
|
+
function createGetSlackMessagesTool(getSlackClient, logger22) {
|
|
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, logger23) {
|
|
|
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
|
+
logger22.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, logger23) {
|
|
|
923
923
|
});
|
|
924
924
|
const found = channels.channels?.find((c) => c.name === channel);
|
|
925
925
|
if (!found) {
|
|
926
|
-
|
|
926
|
+
logger22.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, logger23) {
|
|
|
935
935
|
limit: Math.min(limit, 100)
|
|
936
936
|
// Cap at 100 for performance
|
|
937
937
|
});
|
|
938
|
-
|
|
938
|
+
logger22.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, logger23) {
|
|
|
953
953
|
})) || []
|
|
954
954
|
};
|
|
955
955
|
} catch (error) {
|
|
956
|
-
|
|
956
|
+
logger22.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, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1064
1064
|
lastModified: page.version?.when || ""
|
|
1065
1065
|
}));
|
|
1066
1066
|
if (results.length === 0) {
|
|
1067
|
-
|
|
1067
|
+
logger22.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
|
+
logger22.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, logger23) {
|
|
|
1085
1085
|
results
|
|
1086
1086
|
});
|
|
1087
1087
|
} catch (error) {
|
|
1088
|
-
|
|
1088
|
+
logger22.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, logger23) {
|
|
|
1097
1097
|
}
|
|
1098
1098
|
}).build();
|
|
1099
1099
|
}
|
|
1100
|
-
function createGetConfluencePageTool(getAuth, getAuthHeader2,
|
|
1100
|
+
function createGetConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1114
1114
|
}
|
|
1115
1115
|
});
|
|
1116
1116
|
const page = response.data;
|
|
1117
|
-
|
|
1117
|
+
logger22.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, logger23) {
|
|
|
1136
1136
|
}
|
|
1137
1137
|
});
|
|
1138
1138
|
} catch (error) {
|
|
1139
|
-
|
|
1139
|
+
logger22.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, logger23) {
|
|
|
1148
1148
|
}
|
|
1149
1149
|
}).build();
|
|
1150
1150
|
}
|
|
1151
|
-
function createListConfluenceSpacesTool(getAuth, getAuthHeader2,
|
|
1151
|
+
function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1171
1171
|
description: space.description?.plain?.value || "",
|
|
1172
1172
|
url: `${ATLASSIAN_SITE_URL}/wiki${space._links.webui}`
|
|
1173
1173
|
}));
|
|
1174
|
-
|
|
1174
|
+
logger22.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, logger23) {
|
|
|
1182
1182
|
spaces
|
|
1183
1183
|
});
|
|
1184
1184
|
} catch (error) {
|
|
1185
|
-
|
|
1185
|
+
logger22.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, logger23) {
|
|
|
1193
1193
|
}
|
|
1194
1194
|
}).build();
|
|
1195
1195
|
}
|
|
1196
|
-
function createGetSpacePagesTool(getAuth, getAuthHeader2,
|
|
1196
|
+
function createGetSpacePagesTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1220
1220
|
lastModified: page.version?.when || ""
|
|
1221
1221
|
}));
|
|
1222
1222
|
if (pages.length === 0) {
|
|
1223
|
-
|
|
1223
|
+
logger22.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
|
+
logger22.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, logger23) {
|
|
|
1239
1239
|
pages
|
|
1240
1240
|
});
|
|
1241
1241
|
} catch (error) {
|
|
1242
|
-
|
|
1242
|
+
logger22.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, logger23) {
|
|
|
1251
1251
|
}
|
|
1252
1252
|
}).build();
|
|
1253
1253
|
}
|
|
1254
|
-
function createCreateConfluencePageTool(getAuth, getAuthHeader2,
|
|
1254
|
+
function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1285
1285
|
}
|
|
1286
1286
|
}
|
|
1287
1287
|
);
|
|
1288
|
-
|
|
1288
|
+
logger22.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, logger23) {
|
|
|
1301
1301
|
}
|
|
1302
1302
|
});
|
|
1303
1303
|
} catch (error) {
|
|
1304
|
-
|
|
1304
|
+
logger22.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, logger23) {
|
|
|
1314
1314
|
}
|
|
1315
1315
|
}).build();
|
|
1316
1316
|
}
|
|
1317
|
-
function createUpdateConfluencePageTool(getAuth, getAuthHeader2,
|
|
1317
|
+
function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1353
1353
|
}
|
|
1354
1354
|
}
|
|
1355
1355
|
);
|
|
1356
|
-
|
|
1356
|
+
logger22.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, logger23) {
|
|
|
1370
1370
|
}
|
|
1371
1371
|
});
|
|
1372
1372
|
} catch (error) {
|
|
1373
|
-
|
|
1373
|
+
logger22.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, logger23) {
|
|
|
1383
1383
|
}
|
|
1384
1384
|
}).build();
|
|
1385
1385
|
}
|
|
1386
|
-
function createArchiveConfluencePageTool(getAuth, getAuthHeader2,
|
|
1386
|
+
function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.info("archive-confluence-page called", {
|
|
1392
1392
|
page_id,
|
|
1393
1393
|
...reason ? { reason } : {}
|
|
1394
1394
|
});
|
|
@@ -1422,7 +1422,7 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
|
1422
1422
|
}
|
|
1423
1423
|
}
|
|
1424
1424
|
);
|
|
1425
|
-
|
|
1425
|
+
logger22.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, logger23) {
|
|
|
1440
1440
|
}
|
|
1441
1441
|
});
|
|
1442
1442
|
} catch (error) {
|
|
1443
|
-
|
|
1443
|
+
logger22.error("archive-confluence-page error", {
|
|
1444
1444
|
page_id,
|
|
1445
1445
|
error: error.response?.data?.message || error.message,
|
|
1446
1446
|
status: error.response?.status
|
|
@@ -2429,6 +2429,20 @@ function validateBatch(texts) {
|
|
|
2429
2429
|
}
|
|
2430
2430
|
});
|
|
2431
2431
|
}
|
|
2432
|
+
var embeddingLogger = createLogger("agentforge:tools:neo4j:embeddings");
|
|
2433
|
+
var NOT_INITIALIZED_ERROR = "Embedding manager not initialized. Call initialize() or initializeFromEnv() first.";
|
|
2434
|
+
function requireEmbeddingProvider(provider) {
|
|
2435
|
+
if (!provider) {
|
|
2436
|
+
throw new Error(NOT_INITIALIZED_ERROR);
|
|
2437
|
+
}
|
|
2438
|
+
return provider;
|
|
2439
|
+
}
|
|
2440
|
+
function requireEmbeddingConfig(config) {
|
|
2441
|
+
if (!config) {
|
|
2442
|
+
throw new Error(NOT_INITIALIZED_ERROR);
|
|
2443
|
+
}
|
|
2444
|
+
return config;
|
|
2445
|
+
}
|
|
2432
2446
|
var OpenAIEmbeddingProvider = class {
|
|
2433
2447
|
name = "openai";
|
|
2434
2448
|
defaultModel = "text-embedding-3-small";
|
|
@@ -2913,8 +2927,176 @@ var OllamaEmbeddingProvider = class {
|
|
|
2913
2927
|
}
|
|
2914
2928
|
};
|
|
2915
2929
|
|
|
2930
|
+
// src/data/neo4j/embeddings/embedding-provider-factory.ts
|
|
2931
|
+
var DEFAULT_OLLAMA_BASE_URL = "http://localhost:11434";
|
|
2932
|
+
function parseEmbeddingProvider(providerName) {
|
|
2933
|
+
switch (providerName) {
|
|
2934
|
+
case "openai":
|
|
2935
|
+
case "cohere":
|
|
2936
|
+
case "huggingface":
|
|
2937
|
+
case "voyage":
|
|
2938
|
+
case "ollama":
|
|
2939
|
+
return providerName;
|
|
2940
|
+
default:
|
|
2941
|
+
throw new Error(`Unknown embedding provider: ${providerName}`);
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
function getDefaultEmbeddingModel(provider) {
|
|
2945
|
+
switch (provider) {
|
|
2946
|
+
case "openai":
|
|
2947
|
+
return "text-embedding-3-small";
|
|
2948
|
+
case "cohere":
|
|
2949
|
+
return "embed-english-v3.0";
|
|
2950
|
+
case "huggingface":
|
|
2951
|
+
return "sentence-transformers/all-MiniLM-L6-v2";
|
|
2952
|
+
case "voyage":
|
|
2953
|
+
return "voyage-2";
|
|
2954
|
+
case "ollama":
|
|
2955
|
+
return "nomic-embed-text";
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
function createEmbeddingProvider(providerName, apiKey, model, baseUrl) {
|
|
2959
|
+
switch (providerName) {
|
|
2960
|
+
case "openai":
|
|
2961
|
+
return new OpenAIEmbeddingProvider(apiKey);
|
|
2962
|
+
case "cohere":
|
|
2963
|
+
return new CohereEmbeddingProvider(apiKey);
|
|
2964
|
+
case "huggingface":
|
|
2965
|
+
return new HuggingFaceEmbeddingProvider(apiKey);
|
|
2966
|
+
case "voyage":
|
|
2967
|
+
return new VoyageEmbeddingProvider(apiKey);
|
|
2968
|
+
case "ollama":
|
|
2969
|
+
return new OllamaEmbeddingProvider(model, baseUrl || DEFAULT_OLLAMA_BASE_URL);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
// src/data/neo4j/embeddings/embedding-environment.ts
|
|
2974
|
+
function resolveEmbeddingEnvironment() {
|
|
2975
|
+
const providerName = validateEmbeddingProvider(getEmbeddingProvider());
|
|
2976
|
+
const model = getEmbeddingModel() || getDefaultEmbeddingModel(providerName);
|
|
2977
|
+
embeddingLogger.debug("Initializing embedding manager from environment", {
|
|
2978
|
+
provider: providerName,
|
|
2979
|
+
model
|
|
2980
|
+
});
|
|
2981
|
+
switch (providerName) {
|
|
2982
|
+
case "openai":
|
|
2983
|
+
return createCredentialEnvironment(
|
|
2984
|
+
providerName,
|
|
2985
|
+
model,
|
|
2986
|
+
getOpenAIApiKey(),
|
|
2987
|
+
"OPENAI_API_KEY environment variable is required for OpenAI embeddings",
|
|
2988
|
+
"OPENAI_API_KEY environment variable not set"
|
|
2989
|
+
);
|
|
2990
|
+
case "cohere":
|
|
2991
|
+
return createCredentialEnvironment(
|
|
2992
|
+
providerName,
|
|
2993
|
+
model,
|
|
2994
|
+
getCohereApiKey(),
|
|
2995
|
+
"COHERE_API_KEY environment variable is required for Cohere embeddings",
|
|
2996
|
+
"COHERE_API_KEY environment variable not set"
|
|
2997
|
+
);
|
|
2998
|
+
case "huggingface":
|
|
2999
|
+
return createCredentialEnvironment(
|
|
3000
|
+
providerName,
|
|
3001
|
+
model,
|
|
3002
|
+
getHuggingFaceApiKey(),
|
|
3003
|
+
"HUGGINGFACE_API_KEY environment variable is required for HuggingFace embeddings",
|
|
3004
|
+
"HUGGINGFACE_API_KEY environment variable not set"
|
|
3005
|
+
);
|
|
3006
|
+
case "voyage":
|
|
3007
|
+
return createCredentialEnvironment(
|
|
3008
|
+
providerName,
|
|
3009
|
+
model,
|
|
3010
|
+
getVoyageApiKey(),
|
|
3011
|
+
"VOYAGE_API_KEY environment variable is required for Voyage AI embeddings",
|
|
3012
|
+
"VOYAGE_API_KEY environment variable not set"
|
|
3013
|
+
);
|
|
3014
|
+
case "ollama": {
|
|
3015
|
+
const baseUrl = getOllamaBaseUrl();
|
|
3016
|
+
embeddingLogger.debug("Using Ollama (local, no API key required)", {
|
|
3017
|
+
baseUrl
|
|
3018
|
+
});
|
|
3019
|
+
return {
|
|
3020
|
+
providerName,
|
|
3021
|
+
apiKey: "",
|
|
3022
|
+
baseUrl,
|
|
3023
|
+
config: {
|
|
3024
|
+
provider: providerName,
|
|
3025
|
+
model,
|
|
3026
|
+
apiKey: ""
|
|
3027
|
+
}
|
|
3028
|
+
};
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
function validateEmbeddingProvider(providerName) {
|
|
3033
|
+
try {
|
|
3034
|
+
return parseEmbeddingProvider(providerName);
|
|
3035
|
+
} catch (error) {
|
|
3036
|
+
embeddingLogger.error("Unknown embedding provider", {
|
|
3037
|
+
provider: providerName
|
|
3038
|
+
});
|
|
3039
|
+
throw error;
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
function createCredentialEnvironment(providerName, model, apiKey, missingKeyError, missingKeyLog) {
|
|
3043
|
+
if (!apiKey) {
|
|
3044
|
+
embeddingLogger.error(missingKeyLog, {
|
|
3045
|
+
provider: providerName,
|
|
3046
|
+
required: true
|
|
3047
|
+
});
|
|
3048
|
+
throw new Error(missingKeyError);
|
|
3049
|
+
}
|
|
3050
|
+
embeddingLogger.debug(`${providerName} API key found`);
|
|
3051
|
+
return {
|
|
3052
|
+
providerName,
|
|
3053
|
+
apiKey,
|
|
3054
|
+
config: {
|
|
3055
|
+
provider: providerName,
|
|
3056
|
+
model,
|
|
3057
|
+
apiKey: ""
|
|
3058
|
+
}
|
|
3059
|
+
};
|
|
3060
|
+
}
|
|
3061
|
+
|
|
3062
|
+
// src/data/neo4j/embeddings/embedding-generation.ts
|
|
3063
|
+
async function generateManagedEmbedding(state, text, model) {
|
|
3064
|
+
const startTime = Date.now();
|
|
3065
|
+
const modelToUse = model || state.config.model;
|
|
3066
|
+
embeddingLogger.debug("Generating embedding", {
|
|
3067
|
+
provider: state.provider.name,
|
|
3068
|
+
model: modelToUse,
|
|
3069
|
+
textLength: text.length
|
|
3070
|
+
});
|
|
3071
|
+
const result = await state.provider.generateEmbedding(text, modelToUse);
|
|
3072
|
+
embeddingLogger.info("Embedding generated", {
|
|
3073
|
+
provider: state.provider.name,
|
|
3074
|
+
model: result.model,
|
|
3075
|
+
dimensions: result.dimensions,
|
|
3076
|
+
duration: Date.now() - startTime
|
|
3077
|
+
});
|
|
3078
|
+
return result;
|
|
3079
|
+
}
|
|
3080
|
+
async function generateManagedBatchEmbeddings(state, texts, model) {
|
|
3081
|
+
const startTime = Date.now();
|
|
3082
|
+
const modelToUse = model || state.config.model;
|
|
3083
|
+
embeddingLogger.debug("Generating batch embeddings", {
|
|
3084
|
+
provider: state.provider.name,
|
|
3085
|
+
model: modelToUse,
|
|
3086
|
+
count: texts.length
|
|
3087
|
+
});
|
|
3088
|
+
const result = await state.provider.generateBatchEmbeddings(texts, modelToUse);
|
|
3089
|
+
embeddingLogger.info("Batch embeddings generated", {
|
|
3090
|
+
provider: state.provider.name,
|
|
3091
|
+
model: result.model,
|
|
3092
|
+
dimensions: result.dimensions,
|
|
3093
|
+
count: texts.length,
|
|
3094
|
+
duration: Date.now() - startTime
|
|
3095
|
+
});
|
|
3096
|
+
return result;
|
|
3097
|
+
}
|
|
3098
|
+
|
|
2916
3099
|
// src/data/neo4j/embeddings/embedding-manager.ts
|
|
2917
|
-
var logger4 = createLogger("agentforge:tools:neo4j:embeddings");
|
|
2918
3100
|
var EmbeddingManager = class {
|
|
2919
3101
|
provider = null;
|
|
2920
3102
|
config = null;
|
|
@@ -2922,103 +3104,31 @@ var EmbeddingManager = class {
|
|
|
2922
3104
|
* Initialize with configuration
|
|
2923
3105
|
*/
|
|
2924
3106
|
initialize(config) {
|
|
2925
|
-
|
|
3107
|
+
embeddingLogger.debug("Initializing embedding manager", {
|
|
2926
3108
|
provider: config.provider,
|
|
2927
3109
|
model: config.model
|
|
2928
3110
|
});
|
|
2929
3111
|
this.config = config;
|
|
2930
|
-
this.provider =
|
|
2931
|
-
|
|
3112
|
+
this.provider = createEmbeddingProvider(config.provider, config.apiKey);
|
|
3113
|
+
embeddingLogger.info("Embedding manager initialized", {
|
|
2932
3114
|
provider: config.provider,
|
|
2933
|
-
model: config.model ||
|
|
3115
|
+
model: config.model || getDefaultEmbeddingModel(config.provider)
|
|
2934
3116
|
});
|
|
2935
3117
|
}
|
|
2936
3118
|
/**
|
|
2937
3119
|
* Initialize from environment variables
|
|
2938
3120
|
*/
|
|
2939
3121
|
initializeFromEnv() {
|
|
2940
|
-
const
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
model
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
const key = getOpenAIApiKey();
|
|
2951
|
-
if (!key) {
|
|
2952
|
-
logger4.error("OPENAI_API_KEY environment variable not set", {
|
|
2953
|
-
provider: "openai",
|
|
2954
|
-
required: true
|
|
2955
|
-
});
|
|
2956
|
-
throw new Error("OPENAI_API_KEY environment variable is required for OpenAI embeddings");
|
|
2957
|
-
}
|
|
2958
|
-
apiKey = key;
|
|
2959
|
-
logger4.debug("OpenAI API key found");
|
|
2960
|
-
break;
|
|
2961
|
-
}
|
|
2962
|
-
case "cohere": {
|
|
2963
|
-
const key = getCohereApiKey();
|
|
2964
|
-
if (!key) {
|
|
2965
|
-
logger4.error("COHERE_API_KEY environment variable not set", {
|
|
2966
|
-
provider: "cohere",
|
|
2967
|
-
required: true
|
|
2968
|
-
});
|
|
2969
|
-
throw new Error("COHERE_API_KEY environment variable is required for Cohere embeddings");
|
|
2970
|
-
}
|
|
2971
|
-
apiKey = key;
|
|
2972
|
-
logger4.debug("Cohere API key found");
|
|
2973
|
-
break;
|
|
2974
|
-
}
|
|
2975
|
-
case "huggingface": {
|
|
2976
|
-
const key = getHuggingFaceApiKey();
|
|
2977
|
-
if (!key) {
|
|
2978
|
-
logger4.error("HUGGINGFACE_API_KEY environment variable not set", {
|
|
2979
|
-
provider: "huggingface",
|
|
2980
|
-
required: true
|
|
2981
|
-
});
|
|
2982
|
-
throw new Error("HUGGINGFACE_API_KEY environment variable is required for HuggingFace embeddings");
|
|
2983
|
-
}
|
|
2984
|
-
apiKey = key;
|
|
2985
|
-
logger4.debug("HuggingFace API key found");
|
|
2986
|
-
break;
|
|
2987
|
-
}
|
|
2988
|
-
case "voyage": {
|
|
2989
|
-
const key = getVoyageApiKey();
|
|
2990
|
-
if (!key) {
|
|
2991
|
-
logger4.error("VOYAGE_API_KEY environment variable not set", {
|
|
2992
|
-
provider: "voyage",
|
|
2993
|
-
required: true
|
|
2994
|
-
});
|
|
2995
|
-
throw new Error("VOYAGE_API_KEY environment variable is required for Voyage AI embeddings");
|
|
2996
|
-
}
|
|
2997
|
-
apiKey = key;
|
|
2998
|
-
logger4.debug("Voyage API key found");
|
|
2999
|
-
break;
|
|
3000
|
-
}
|
|
3001
|
-
case "ollama":
|
|
3002
|
-
baseUrl = getOllamaBaseUrl();
|
|
3003
|
-
logger4.debug("Using Ollama (local, no API key required)", {
|
|
3004
|
-
baseUrl: baseUrl || "http://localhost:11434"
|
|
3005
|
-
});
|
|
3006
|
-
break;
|
|
3007
|
-
default:
|
|
3008
|
-
logger4.error("Unknown embedding provider", {
|
|
3009
|
-
provider: providerName
|
|
3010
|
-
});
|
|
3011
|
-
throw new Error(`Unknown embedding provider: ${providerName}`);
|
|
3012
|
-
}
|
|
3013
|
-
this.provider = this.createProvider(providerName, apiKey, model, baseUrl);
|
|
3014
|
-
this.config = {
|
|
3015
|
-
provider: providerName,
|
|
3016
|
-
model: model || this.getDefaultModel(providerName),
|
|
3017
|
-
apiKey: ""
|
|
3018
|
-
// Not stored when using env
|
|
3019
|
-
};
|
|
3020
|
-
logger4.info("Embedding manager initialized from environment", {
|
|
3021
|
-
provider: providerName,
|
|
3122
|
+
const resolved = resolveEmbeddingEnvironment();
|
|
3123
|
+
this.provider = createEmbeddingProvider(
|
|
3124
|
+
resolved.providerName,
|
|
3125
|
+
resolved.apiKey,
|
|
3126
|
+
resolved.config.model,
|
|
3127
|
+
resolved.baseUrl
|
|
3128
|
+
);
|
|
3129
|
+
this.config = resolved.config;
|
|
3130
|
+
embeddingLogger.info("Embedding manager initialized from environment", {
|
|
3131
|
+
provider: resolved.providerName,
|
|
3022
3132
|
model: this.config.model
|
|
3023
3133
|
});
|
|
3024
3134
|
}
|
|
@@ -3032,102 +3142,39 @@ var EmbeddingManager = class {
|
|
|
3032
3142
|
* Get current provider
|
|
3033
3143
|
*/
|
|
3034
3144
|
getProvider() {
|
|
3035
|
-
|
|
3036
|
-
throw new Error("Embedding manager not initialized. Call initialize() or initializeFromEnv() first.");
|
|
3037
|
-
}
|
|
3038
|
-
return this.provider;
|
|
3145
|
+
return requireEmbeddingProvider(this.provider);
|
|
3039
3146
|
}
|
|
3040
3147
|
/**
|
|
3041
3148
|
* Get current configuration
|
|
3042
3149
|
*/
|
|
3043
3150
|
getConfig() {
|
|
3044
|
-
|
|
3045
|
-
throw new Error("Embedding manager not initialized. Call initialize() or initializeFromEnv() first.");
|
|
3046
|
-
}
|
|
3047
|
-
return this.config;
|
|
3151
|
+
return requireEmbeddingConfig(this.config);
|
|
3048
3152
|
}
|
|
3049
3153
|
/**
|
|
3050
3154
|
* Generate embedding for a single text
|
|
3051
3155
|
*/
|
|
3052
3156
|
async generateEmbedding(text, model) {
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
model
|
|
3060
|
-
|
|
3061
|
-
});
|
|
3062
|
-
const result = await provider.generateEmbedding(text, modelToUse);
|
|
3063
|
-
logger4.info("Embedding generated", {
|
|
3064
|
-
provider: provider.name,
|
|
3065
|
-
model: result.model,
|
|
3066
|
-
dimensions: result.dimensions,
|
|
3067
|
-
duration: Date.now() - startTime
|
|
3068
|
-
});
|
|
3069
|
-
return result;
|
|
3157
|
+
return generateManagedEmbedding(
|
|
3158
|
+
{
|
|
3159
|
+
provider: this.getProvider(),
|
|
3160
|
+
config: this.getConfig()
|
|
3161
|
+
},
|
|
3162
|
+
text,
|
|
3163
|
+
model
|
|
3164
|
+
);
|
|
3070
3165
|
}
|
|
3071
3166
|
/**
|
|
3072
3167
|
* Generate embeddings for multiple texts (batch)
|
|
3073
3168
|
*/
|
|
3074
3169
|
async generateBatchEmbeddings(texts, model) {
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
model
|
|
3082
|
-
|
|
3083
|
-
});
|
|
3084
|
-
const result = await provider.generateBatchEmbeddings(texts, modelToUse);
|
|
3085
|
-
logger4.info("Batch embeddings generated", {
|
|
3086
|
-
provider: provider.name,
|
|
3087
|
-
model: result.model,
|
|
3088
|
-
dimensions: result.dimensions,
|
|
3089
|
-
count: texts.length,
|
|
3090
|
-
duration: Date.now() - startTime
|
|
3091
|
-
});
|
|
3092
|
-
return result;
|
|
3093
|
-
}
|
|
3094
|
-
/**
|
|
3095
|
-
* Get default model for a provider
|
|
3096
|
-
*/
|
|
3097
|
-
getDefaultModel(provider) {
|
|
3098
|
-
switch (provider) {
|
|
3099
|
-
case "openai":
|
|
3100
|
-
return "text-embedding-3-small";
|
|
3101
|
-
case "cohere":
|
|
3102
|
-
return "embed-english-v3.0";
|
|
3103
|
-
case "huggingface":
|
|
3104
|
-
return "sentence-transformers/all-MiniLM-L6-v2";
|
|
3105
|
-
case "voyage":
|
|
3106
|
-
return "voyage-2";
|
|
3107
|
-
case "ollama":
|
|
3108
|
-
return "nomic-embed-text";
|
|
3109
|
-
default:
|
|
3110
|
-
return "text-embedding-3-small";
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
|
-
/**
|
|
3114
|
-
* Create a provider instance
|
|
3115
|
-
*/
|
|
3116
|
-
createProvider(providerName, apiKey, model, baseUrl) {
|
|
3117
|
-
switch (providerName) {
|
|
3118
|
-
case "openai":
|
|
3119
|
-
return new OpenAIEmbeddingProvider(apiKey);
|
|
3120
|
-
case "cohere":
|
|
3121
|
-
return new CohereEmbeddingProvider(apiKey);
|
|
3122
|
-
case "huggingface":
|
|
3123
|
-
return new HuggingFaceEmbeddingProvider(apiKey);
|
|
3124
|
-
case "voyage":
|
|
3125
|
-
return new VoyageEmbeddingProvider(apiKey);
|
|
3126
|
-
case "ollama":
|
|
3127
|
-
return new OllamaEmbeddingProvider(model, baseUrl || "http://localhost:11434");
|
|
3128
|
-
default:
|
|
3129
|
-
throw new Error(`Unknown embedding provider: ${providerName}`);
|
|
3130
|
-
}
|
|
3170
|
+
return generateManagedBatchEmbeddings(
|
|
3171
|
+
{
|
|
3172
|
+
provider: this.getProvider(),
|
|
3173
|
+
config: this.getConfig()
|
|
3174
|
+
},
|
|
3175
|
+
texts,
|
|
3176
|
+
model
|
|
3177
|
+
);
|
|
3131
3178
|
}
|
|
3132
3179
|
/**
|
|
3133
3180
|
* Reset the manager (for testing)
|
|
@@ -3239,20 +3286,20 @@ function formatResults(records) {
|
|
|
3239
3286
|
}
|
|
3240
3287
|
|
|
3241
3288
|
// src/data/neo4j/tools/neo4j-query.ts
|
|
3242
|
-
var
|
|
3289
|
+
var logger4 = createLogger("agentforge:tools:neo4j:query");
|
|
3243
3290
|
function createNeo4jQueryTool() {
|
|
3244
3291
|
return toolBuilder().name("neo4j-query").description(
|
|
3245
3292
|
"Execute a Cypher query against the Neo4j graph database. Supports parameterized queries for safety. Use this for complex queries, graph traversals, and custom operations."
|
|
3246
3293
|
).category(ToolCategory.DATABASE).tags(["neo4j", "graph", "database", "cypher", "query"]).schema(neo4jQuerySchema).implement(async (input) => {
|
|
3247
3294
|
if (!neo4jPool.isInitialized()) {
|
|
3248
|
-
|
|
3295
|
+
logger4.warn("Neo4j query attempted but connection not initialized");
|
|
3249
3296
|
return {
|
|
3250
3297
|
success: false,
|
|
3251
3298
|
error: "Neo4j connection not initialized. Please configure Neo4j connection first."
|
|
3252
3299
|
};
|
|
3253
3300
|
}
|
|
3254
3301
|
const startTime = Date.now();
|
|
3255
|
-
|
|
3302
|
+
logger4.debug("Executing Neo4j query", {
|
|
3256
3303
|
cypherPreview: input.cypher.substring(0, 100),
|
|
3257
3304
|
parameterCount: Object.keys(input.parameters || {}).length,
|
|
3258
3305
|
...input.database ? { database: input.database } : {}
|
|
@@ -3263,7 +3310,7 @@ function createNeo4jQueryTool() {
|
|
|
3263
3310
|
const result = await session.run(input.cypher, input.parameters || {});
|
|
3264
3311
|
const formattedResults = formatResults(result.records);
|
|
3265
3312
|
const duration = Date.now() - startTime;
|
|
3266
|
-
|
|
3313
|
+
logger4.info("Neo4j query executed successfully", {
|
|
3267
3314
|
recordCount: result.records.length,
|
|
3268
3315
|
nodesCreated: result.summary.counters.updates().nodesCreated,
|
|
3269
3316
|
nodesDeleted: result.summary.counters.updates().nodesDeleted,
|
|
@@ -3294,7 +3341,7 @@ function createNeo4jQueryTool() {
|
|
|
3294
3341
|
} catch (error) {
|
|
3295
3342
|
const duration = Date.now() - startTime;
|
|
3296
3343
|
const errorMessage = error instanceof Error ? error.message : "Failed to execute query";
|
|
3297
|
-
|
|
3344
|
+
logger4.error("Neo4j query execution failed", {
|
|
3298
3345
|
error: errorMessage,
|
|
3299
3346
|
cypherPreview: input.cypher.substring(0, 100),
|
|
3300
3347
|
duration
|
|
@@ -3604,27 +3651,27 @@ function createNeo4jVectorSearchTool() {
|
|
|
3604
3651
|
}
|
|
3605
3652
|
}).build();
|
|
3606
3653
|
}
|
|
3607
|
-
var
|
|
3654
|
+
var logger5 = createLogger("agentforge:tools:neo4j:vector-search");
|
|
3608
3655
|
function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
3609
3656
|
return toolBuilder().name("neo4j-vector-search-with-embedding").description(
|
|
3610
3657
|
"Perform semantic similarity search in Neo4j by automatically generating embeddings from text. This tool takes text input, generates an embedding vector, and searches for similar nodes. Essential for GraphRAG applications - no need to manually generate embeddings. Requires a vector index and embedding provider (OpenAI) to be configured."
|
|
3611
3658
|
).category(ToolCategory.DATABASE).tags(["neo4j", "graph", "database", "vector", "search", "semantic", "graphrag", "embedding", "ai"]).schema(neo4jVectorSearchWithEmbeddingSchema).implement(async (input) => {
|
|
3612
3659
|
if (!neo4jPool.isInitialized()) {
|
|
3613
|
-
|
|
3660
|
+
logger5.warn("Vector search attempted but Neo4j connection not initialized");
|
|
3614
3661
|
return {
|
|
3615
3662
|
success: false,
|
|
3616
3663
|
error: "Neo4j connection not initialized. Please configure Neo4j connection first."
|
|
3617
3664
|
};
|
|
3618
3665
|
}
|
|
3619
3666
|
if (!embeddingManager.isInitialized()) {
|
|
3620
|
-
|
|
3667
|
+
logger5.warn("Vector search attempted but embedding manager not initialized");
|
|
3621
3668
|
return {
|
|
3622
3669
|
success: false,
|
|
3623
3670
|
error: "Embedding manager not initialized. Please configure embedding provider (set OPENAI_API_KEY and optionally EMBEDDING_MODEL)."
|
|
3624
3671
|
};
|
|
3625
3672
|
}
|
|
3626
3673
|
const startTime = Date.now();
|
|
3627
|
-
|
|
3674
|
+
logger5.debug("Performing vector search with embedding", {
|
|
3628
3675
|
queryTextLength: input.queryText.length,
|
|
3629
3676
|
indexName: input.indexName,
|
|
3630
3677
|
...input.limit !== void 0 ? { limit: input.limit } : {},
|
|
@@ -3648,7 +3695,7 @@ function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
|
3648
3695
|
const result = await session.run(cypher, parameters);
|
|
3649
3696
|
const formattedResults = formatResults(result.records);
|
|
3650
3697
|
const duration = Date.now() - startTime;
|
|
3651
|
-
|
|
3698
|
+
logger5.info("Vector search completed successfully", {
|
|
3652
3699
|
resultCount: result.records.length,
|
|
3653
3700
|
indexName: input.indexName,
|
|
3654
3701
|
embeddingModel: embeddingResult.model,
|
|
@@ -3689,7 +3736,7 @@ function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
|
3689
3736
|
} else if (errorMessage.includes("dimension")) {
|
|
3690
3737
|
helpText = " Make sure the vector index dimensions match your embedding model dimensions.";
|
|
3691
3738
|
}
|
|
3692
|
-
|
|
3739
|
+
logger5.error("Vector search failed", {
|
|
3693
3740
|
error: errorMessage,
|
|
3694
3741
|
indexName: input.indexName,
|
|
3695
3742
|
queryTextLength: input.queryText.length,
|
|
@@ -4121,19 +4168,19 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
|
4121
4168
|
ConnectionState2["ERROR"] = "error";
|
|
4122
4169
|
return ConnectionState2;
|
|
4123
4170
|
})(ConnectionState || {});
|
|
4124
|
-
function cancelPendingReconnection(timer,
|
|
4171
|
+
function cancelPendingReconnection(timer, logger22, vendor, message) {
|
|
4125
4172
|
if (!timer) {
|
|
4126
4173
|
return null;
|
|
4127
4174
|
}
|
|
4128
|
-
|
|
4175
|
+
logger22.debug(message, { vendor });
|
|
4129
4176
|
clearTimeout(timer);
|
|
4130
4177
|
return null;
|
|
4131
4178
|
}
|
|
4132
|
-
async function waitForInFlightConnection(promise,
|
|
4179
|
+
async function waitForInFlightConnection(promise, logger22, vendor, phase) {
|
|
4133
4180
|
if (!promise) {
|
|
4134
4181
|
return null;
|
|
4135
4182
|
}
|
|
4136
|
-
|
|
4183
|
+
logger22.debug(`Waiting for in-flight connection attempt to complete before ${phase}`, {
|
|
4137
4184
|
vendor
|
|
4138
4185
|
});
|
|
4139
4186
|
try {
|
|
@@ -4150,9 +4197,9 @@ function shutdownClient(vendor, client) {
|
|
|
4150
4197
|
client.close();
|
|
4151
4198
|
}
|
|
4152
4199
|
}
|
|
4153
|
-
function scheduleReconnection(context,
|
|
4200
|
+
function scheduleReconnection(context, logger22) {
|
|
4154
4201
|
if (context.reconnectionConfig.maxAttempts > 0 && context.reconnectionAttempts >= context.reconnectionConfig.maxAttempts) {
|
|
4155
|
-
|
|
4202
|
+
logger22.error("Max reconnection attempts reached", {
|
|
4156
4203
|
vendor: context.vendor,
|
|
4157
4204
|
attempts: context.reconnectionAttempts,
|
|
4158
4205
|
maxAttempts: context.reconnectionConfig.maxAttempts
|
|
@@ -4166,7 +4213,7 @@ function scheduleReconnection(context, logger23) {
|
|
|
4166
4213
|
const nextAttempt = context.reconnectionAttempts + 1;
|
|
4167
4214
|
context.setReconnectionAttempts(nextAttempt);
|
|
4168
4215
|
context.setState("reconnecting" /* RECONNECTING */);
|
|
4169
|
-
|
|
4216
|
+
logger22.info("Scheduling reconnection attempt", {
|
|
4170
4217
|
vendor: context.vendor,
|
|
4171
4218
|
attempt: nextAttempt,
|
|
4172
4219
|
maxAttempts: context.reconnectionConfig.maxAttempts,
|
|
@@ -4180,7 +4227,7 @@ function scheduleReconnection(context, logger23) {
|
|
|
4180
4227
|
const timer = setTimeout(async () => {
|
|
4181
4228
|
context.setReconnectionTimer(null);
|
|
4182
4229
|
try {
|
|
4183
|
-
|
|
4230
|
+
logger22.info("Attempting reconnection", {
|
|
4184
4231
|
vendor: context.vendor,
|
|
4185
4232
|
attempt: nextAttempt
|
|
4186
4233
|
});
|
|
@@ -4190,7 +4237,7 @@ function scheduleReconnection(context, logger23) {
|
|
|
4190
4237
|
context.setConnectPromise(promise);
|
|
4191
4238
|
await promise;
|
|
4192
4239
|
} catch (error) {
|
|
4193
|
-
|
|
4240
|
+
logger22.error("Reconnection attempt failed", {
|
|
4194
4241
|
vendor: context.vendor,
|
|
4195
4242
|
attempt: nextAttempt,
|
|
4196
4243
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -4201,17 +4248,17 @@ function scheduleReconnection(context, logger23) {
|
|
|
4201
4248
|
}
|
|
4202
4249
|
|
|
4203
4250
|
// src/data/relational/connection/connection-cleanup.ts
|
|
4204
|
-
async function cleanupConnectionResources(vendor, client, clearConnection,
|
|
4251
|
+
async function cleanupConnectionResources(vendor, client, clearConnection, logger22) {
|
|
4205
4252
|
if (!client) {
|
|
4206
4253
|
return;
|
|
4207
4254
|
}
|
|
4208
|
-
|
|
4255
|
+
logger22.debug("Cleaning up cancelled connection", {
|
|
4209
4256
|
vendor
|
|
4210
4257
|
});
|
|
4211
4258
|
try {
|
|
4212
4259
|
await shutdownClient(vendor, client);
|
|
4213
4260
|
} catch (error) {
|
|
4214
|
-
|
|
4261
|
+
logger22.debug("Error during cancelled connection cleanup", {
|
|
4215
4262
|
vendor,
|
|
4216
4263
|
error: error instanceof Error ? error.message : String(error)
|
|
4217
4264
|
});
|
|
@@ -4219,10 +4266,10 @@ async function cleanupConnectionResources(vendor, client, clearConnection, logge
|
|
|
4219
4266
|
clearConnection();
|
|
4220
4267
|
}
|
|
4221
4268
|
}
|
|
4222
|
-
async function closeManagedConnection(runtime,
|
|
4269
|
+
async function closeManagedConnection(runtime, logger22) {
|
|
4223
4270
|
const client = runtime.getClient();
|
|
4224
4271
|
if (client) {
|
|
4225
|
-
|
|
4272
|
+
logger22.info("Closing database connection", {
|
|
4226
4273
|
vendor: runtime.vendor,
|
|
4227
4274
|
state: runtime.getState()
|
|
4228
4275
|
});
|
|
@@ -4230,12 +4277,12 @@ async function closeManagedConnection(runtime, logger23) {
|
|
|
4230
4277
|
await shutdownClient(runtime.vendor, client);
|
|
4231
4278
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4232
4279
|
runtime.emitDisconnected();
|
|
4233
|
-
|
|
4280
|
+
logger22.debug("Database connection closed successfully", {
|
|
4234
4281
|
vendor: runtime.vendor,
|
|
4235
4282
|
state: runtime.getState()
|
|
4236
4283
|
});
|
|
4237
4284
|
} catch (error) {
|
|
4238
|
-
|
|
4285
|
+
logger22.error("Error closing database connection", {
|
|
4239
4286
|
vendor: runtime.vendor,
|
|
4240
4287
|
error: error instanceof Error ? error.message : String(error),
|
|
4241
4288
|
state: runtime.getState()
|
|
@@ -4252,7 +4299,7 @@ async function closeManagedConnection(runtime, logger23) {
|
|
|
4252
4299
|
runtime.emitDisconnected();
|
|
4253
4300
|
}
|
|
4254
4301
|
}
|
|
4255
|
-
var
|
|
4302
|
+
var logger6 = createLogger("agentforge:tools:data:relational:connection:vendor-init");
|
|
4256
4303
|
var SAFE_INITIALIZATION_PATTERNS = [
|
|
4257
4304
|
"Pool max connections must be",
|
|
4258
4305
|
"Pool acquire timeout must be",
|
|
@@ -4298,7 +4345,7 @@ function normalizePostgreSQLConfig(connection) {
|
|
|
4298
4345
|
}
|
|
4299
4346
|
function normalizeMySQLConfig(connection) {
|
|
4300
4347
|
if (typeof connection === "string") {
|
|
4301
|
-
|
|
4348
|
+
logger6.debug("Creating MySQL connection pool from connection string", {
|
|
4302
4349
|
vendor: "mysql"
|
|
4303
4350
|
});
|
|
4304
4351
|
return connection;
|
|
@@ -4347,7 +4394,7 @@ async function initializePostgreSQLConnection(connection) {
|
|
|
4347
4394
|
const { drizzle } = await import('drizzle-orm/node-postgres');
|
|
4348
4395
|
const { Pool } = await import('pg');
|
|
4349
4396
|
const { connectionConfig } = normalizePostgreSQLConfig(connection);
|
|
4350
|
-
|
|
4397
|
+
logger6.debug("Creating PostgreSQL connection pool", {
|
|
4351
4398
|
vendor: "postgresql",
|
|
4352
4399
|
poolConfig: pickConfiguredPoolFields({
|
|
4353
4400
|
max: connectionConfig.max,
|
|
@@ -4364,7 +4411,7 @@ async function initializeMySQLConnection(connection) {
|
|
|
4364
4411
|
const mysql = await import('mysql2/promise');
|
|
4365
4412
|
const connectionConfig = normalizeMySQLConfig(connection);
|
|
4366
4413
|
if (typeof connectionConfig !== "string") {
|
|
4367
|
-
|
|
4414
|
+
logger6.debug("Creating MySQL connection pool", {
|
|
4368
4415
|
vendor: "mysql",
|
|
4369
4416
|
poolConfig: pickConfiguredPoolFields({
|
|
4370
4417
|
connectionLimit: connectionConfig.connectionLimit,
|
|
@@ -4388,7 +4435,7 @@ async function initializeSQLiteConnection(connection) {
|
|
|
4388
4435
|
const Database = DatabaseModule.default;
|
|
4389
4436
|
const { url, poolConfig } = resolveSqliteUrl(connection);
|
|
4390
4437
|
if (poolConfig) {
|
|
4391
|
-
|
|
4438
|
+
logger6.debug("SQLite pool configuration provided but not applied (SQLite uses single connection)", {
|
|
4392
4439
|
vendor: "sqlite",
|
|
4393
4440
|
poolConfig: pickConfiguredPoolFields({
|
|
4394
4441
|
max: poolConfig.max,
|
|
@@ -4397,7 +4444,7 @@ async function initializeSQLiteConnection(connection) {
|
|
|
4397
4444
|
})
|
|
4398
4445
|
});
|
|
4399
4446
|
}
|
|
4400
|
-
|
|
4447
|
+
logger6.debug("Creating SQLite connection", {
|
|
4401
4448
|
vendor: "sqlite",
|
|
4402
4449
|
url: url === ":memory:" ? ":memory:" : "file"
|
|
4403
4450
|
});
|
|
@@ -4408,11 +4455,11 @@ async function initializeSQLiteConnection(connection) {
|
|
|
4408
4455
|
}
|
|
4409
4456
|
|
|
4410
4457
|
// src/data/relational/connection/connection-initialization.ts
|
|
4411
|
-
async function initializeManagedConnection(runtime,
|
|
4458
|
+
async function initializeManagedConnection(runtime, logger22) {
|
|
4412
4459
|
const startTime = Date.now();
|
|
4413
4460
|
const currentGeneration = runtime.getConnectionGeneration();
|
|
4414
4461
|
if (runtime.getState() === "connected" /* CONNECTED */ && runtime.getClient()) {
|
|
4415
|
-
|
|
4462
|
+
logger22.warn("Re-initializing an already connected manager; emitting disconnected before cleanup", {
|
|
4416
4463
|
vendor: runtime.vendor
|
|
4417
4464
|
});
|
|
4418
4465
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
@@ -4424,11 +4471,11 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4424
4471
|
runtime.setClient(null);
|
|
4425
4472
|
runtime.setDb(null);
|
|
4426
4473
|
},
|
|
4427
|
-
|
|
4474
|
+
logger22
|
|
4428
4475
|
);
|
|
4429
4476
|
}
|
|
4430
4477
|
runtime.setState("connecting" /* CONNECTING */);
|
|
4431
|
-
|
|
4478
|
+
logger22.info("Initializing database connection", {
|
|
4432
4479
|
vendor: runtime.vendor,
|
|
4433
4480
|
connectionType: typeof runtime.config.connection,
|
|
4434
4481
|
state: runtime.getState()
|
|
@@ -4438,7 +4485,7 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4438
4485
|
runtime.setClient(initialized.client);
|
|
4439
4486
|
runtime.setDb(initialized.db);
|
|
4440
4487
|
if (currentGeneration !== runtime.getConnectionGeneration()) {
|
|
4441
|
-
|
|
4488
|
+
logger22.debug("Connection cancelled during initialization", {
|
|
4442
4489
|
vendor: runtime.vendor,
|
|
4443
4490
|
currentGeneration,
|
|
4444
4491
|
newGeneration: runtime.getConnectionGeneration()
|
|
@@ -4450,18 +4497,18 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4450
4497
|
runtime.setClient(null);
|
|
4451
4498
|
runtime.setDb(null);
|
|
4452
4499
|
},
|
|
4453
|
-
|
|
4500
|
+
logger22
|
|
4454
4501
|
);
|
|
4455
4502
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4456
4503
|
throw new Error("Connection cancelled during initialization");
|
|
4457
4504
|
}
|
|
4458
|
-
|
|
4505
|
+
logger22.debug("Validating connection health", { vendor: runtime.vendor });
|
|
4459
4506
|
const healthy = await runtime.isHealthy();
|
|
4460
4507
|
if (!healthy) {
|
|
4461
4508
|
throw new Error(`Failed to establish healthy connection to ${runtime.vendor} database`);
|
|
4462
4509
|
}
|
|
4463
4510
|
if (currentGeneration !== runtime.getConnectionGeneration()) {
|
|
4464
|
-
|
|
4511
|
+
logger22.debug("Connection cancelled during health check", {
|
|
4465
4512
|
vendor: runtime.vendor,
|
|
4466
4513
|
currentGeneration,
|
|
4467
4514
|
newGeneration: runtime.getConnectionGeneration()
|
|
@@ -4473,7 +4520,7 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4473
4520
|
runtime.setClient(null);
|
|
4474
4521
|
runtime.setDb(null);
|
|
4475
4522
|
},
|
|
4476
|
-
|
|
4523
|
+
logger22
|
|
4477
4524
|
);
|
|
4478
4525
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4479
4526
|
throw new Error("Connection cancelled during health check");
|
|
@@ -4481,7 +4528,7 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4481
4528
|
runtime.setState("connected" /* CONNECTED */);
|
|
4482
4529
|
runtime.emitConnected();
|
|
4483
4530
|
runtime.resetReconnectionAttempts();
|
|
4484
|
-
|
|
4531
|
+
logger22.info("Database connection initialized successfully", {
|
|
4485
4532
|
vendor: runtime.vendor,
|
|
4486
4533
|
duration: Date.now() - startTime,
|
|
4487
4534
|
state: runtime.getState()
|
|
@@ -4502,7 +4549,7 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4502
4549
|
if (runtime.errorListenerCount() > 0) {
|
|
4503
4550
|
runtime.emitError(normalizedError);
|
|
4504
4551
|
}
|
|
4505
|
-
|
|
4552
|
+
logger22.error(errorMessage, {
|
|
4506
4553
|
vendor: runtime.vendor,
|
|
4507
4554
|
error: normalizedError.message,
|
|
4508
4555
|
duration: Date.now() - startTime,
|
|
@@ -4515,13 +4562,13 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4515
4562
|
runtime.setClient(null);
|
|
4516
4563
|
runtime.setDb(null);
|
|
4517
4564
|
},
|
|
4518
|
-
|
|
4565
|
+
logger22
|
|
4519
4566
|
);
|
|
4520
4567
|
if (runtime.getReconnectionConfig().enabled && currentGeneration === runtime.getConnectionGeneration()) {
|
|
4521
4568
|
runtime.scheduleReconnection();
|
|
4522
4569
|
}
|
|
4523
4570
|
} else {
|
|
4524
|
-
|
|
4571
|
+
logger22.debug("Connection initialization cancelled", {
|
|
4525
4572
|
vendor: runtime.vendor,
|
|
4526
4573
|
duration: Date.now() - startTime,
|
|
4527
4574
|
state: runtime.getState()
|
|
@@ -4539,17 +4586,17 @@ function isSqliteNonQueryError(error) {
|
|
|
4539
4586
|
const hasNonQueryMessage = error.message.includes("does not return data");
|
|
4540
4587
|
return isSqliteOrTypeError && hasNonQueryMessage;
|
|
4541
4588
|
}
|
|
4542
|
-
async function checkConnectionHealth(args,
|
|
4589
|
+
async function checkConnectionHealth(args, logger22) {
|
|
4543
4590
|
if (!args.db || !args.client) {
|
|
4544
|
-
|
|
4591
|
+
logger22.debug("Health check failed: connection not initialized", { vendor: args.vendor });
|
|
4545
4592
|
return false;
|
|
4546
4593
|
}
|
|
4547
4594
|
try {
|
|
4548
4595
|
await args.execute(sql`SELECT 1`);
|
|
4549
|
-
|
|
4596
|
+
logger22.debug("Health check passed", { vendor: args.vendor });
|
|
4550
4597
|
return true;
|
|
4551
4598
|
} catch (error) {
|
|
4552
|
-
|
|
4599
|
+
logger22.debug("Health check failed", {
|
|
4553
4600
|
vendor: args.vendor,
|
|
4554
4601
|
error: error instanceof Error ? error.message : String(error)
|
|
4555
4602
|
});
|
|
@@ -4592,8 +4639,8 @@ function getConnectionPoolMetrics(vendor, client) {
|
|
|
4592
4639
|
}
|
|
4593
4640
|
|
|
4594
4641
|
// src/data/relational/connection/query-execution.ts
|
|
4595
|
-
async function executeQuery(context, query,
|
|
4596
|
-
|
|
4642
|
+
async function executeQuery(context, query, logger22) {
|
|
4643
|
+
logger22.debug("Executing SQL query", {
|
|
4597
4644
|
vendor: context.vendor
|
|
4598
4645
|
});
|
|
4599
4646
|
if (context.vendor === "sqlite") {
|
|
@@ -4663,7 +4710,7 @@ async function executeInDedicatedConnection(context, callback) {
|
|
|
4663
4710
|
}
|
|
4664
4711
|
throw new Error(`Unsupported database vendor: ${context.vendor}`);
|
|
4665
4712
|
}
|
|
4666
|
-
var
|
|
4713
|
+
var logger7 = createLogger("agentforge:tools:data:relational:connection");
|
|
4667
4714
|
var ConnectionManager = class extends EventEmitter {
|
|
4668
4715
|
vendor;
|
|
4669
4716
|
db;
|
|
@@ -4693,11 +4740,11 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4693
4740
|
}
|
|
4694
4741
|
async connect() {
|
|
4695
4742
|
if (this.state === "connected" /* CONNECTED */) {
|
|
4696
|
-
|
|
4743
|
+
logger7.debug("Already connected", { vendor: this.vendor });
|
|
4697
4744
|
return;
|
|
4698
4745
|
}
|
|
4699
4746
|
if (this.connectPromise) {
|
|
4700
|
-
|
|
4747
|
+
logger7.debug("Connection already in progress, waiting for completion", {
|
|
4701
4748
|
vendor: this.vendor,
|
|
4702
4749
|
state: this.state
|
|
4703
4750
|
});
|
|
@@ -4705,7 +4752,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4705
4752
|
}
|
|
4706
4753
|
this.reconnectionTimer = cancelPendingReconnection(
|
|
4707
4754
|
this.reconnectionTimer,
|
|
4708
|
-
|
|
4755
|
+
logger7,
|
|
4709
4756
|
this.vendor,
|
|
4710
4757
|
"Clearing pending reconnection timer before manual connect"
|
|
4711
4758
|
);
|
|
@@ -4718,14 +4765,14 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4718
4765
|
this.connectionGeneration++;
|
|
4719
4766
|
this.reconnectionTimer = cancelPendingReconnection(
|
|
4720
4767
|
this.reconnectionTimer,
|
|
4721
|
-
|
|
4768
|
+
logger7,
|
|
4722
4769
|
this.vendor,
|
|
4723
4770
|
"Clearing pending reconnection timer before disconnect"
|
|
4724
4771
|
);
|
|
4725
4772
|
this.reconnectionAttempts = 0;
|
|
4726
4773
|
this.connectPromise = await waitForInFlightConnection(
|
|
4727
4774
|
this.connectPromise,
|
|
4728
|
-
|
|
4775
|
+
logger7,
|
|
4729
4776
|
this.vendor,
|
|
4730
4777
|
"disconnect"
|
|
4731
4778
|
);
|
|
@@ -4745,13 +4792,13 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4745
4792
|
return this.vendor;
|
|
4746
4793
|
}
|
|
4747
4794
|
async initialize() {
|
|
4748
|
-
return initializeManagedConnection(this.createRuntimeAdapter(),
|
|
4795
|
+
return initializeManagedConnection(this.createRuntimeAdapter(), logger7);
|
|
4749
4796
|
}
|
|
4750
4797
|
setState(newState) {
|
|
4751
4798
|
const oldState = this.state;
|
|
4752
4799
|
this.state = newState;
|
|
4753
4800
|
if (oldState !== newState) {
|
|
4754
|
-
|
|
4801
|
+
logger7.debug("Connection state changed", {
|
|
4755
4802
|
vendor: this.vendor,
|
|
4756
4803
|
oldState,
|
|
4757
4804
|
newState
|
|
@@ -4781,7 +4828,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4781
4828
|
this.reconnectionTimer = timer;
|
|
4782
4829
|
}
|
|
4783
4830
|
},
|
|
4784
|
-
|
|
4831
|
+
logger7
|
|
4785
4832
|
);
|
|
4786
4833
|
}
|
|
4787
4834
|
createRuntimeAdapter() {
|
|
@@ -4828,7 +4875,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4828
4875
|
isSqliteNonQueryError
|
|
4829
4876
|
},
|
|
4830
4877
|
query,
|
|
4831
|
-
|
|
4878
|
+
logger7
|
|
4832
4879
|
);
|
|
4833
4880
|
}
|
|
4834
4881
|
async executeInConnection(callback) {
|
|
@@ -4852,13 +4899,13 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4852
4899
|
this.connectionGeneration++;
|
|
4853
4900
|
this.reconnectionTimer = cancelPendingReconnection(
|
|
4854
4901
|
this.reconnectionTimer,
|
|
4855
|
-
|
|
4902
|
+
logger7,
|
|
4856
4903
|
this.vendor,
|
|
4857
4904
|
"Canceling pending reconnection timer during close"
|
|
4858
4905
|
);
|
|
4859
4906
|
this.connectPromise = await waitForInFlightConnection(
|
|
4860
4907
|
this.connectPromise,
|
|
4861
|
-
|
|
4908
|
+
logger7,
|
|
4862
4909
|
this.vendor,
|
|
4863
4910
|
"close"
|
|
4864
4911
|
);
|
|
@@ -4881,7 +4928,7 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4881
4928
|
this.emit("error", error);
|
|
4882
4929
|
}
|
|
4883
4930
|
},
|
|
4884
|
-
|
|
4931
|
+
logger7
|
|
4885
4932
|
);
|
|
4886
4933
|
}
|
|
4887
4934
|
async isHealthy() {
|
|
@@ -4892,11 +4939,11 @@ var ConnectionManager = class extends EventEmitter {
|
|
|
4892
4939
|
client: this.client,
|
|
4893
4940
|
execute: (query) => this.execute(query)
|
|
4894
4941
|
},
|
|
4895
|
-
|
|
4942
|
+
logger7
|
|
4896
4943
|
);
|
|
4897
4944
|
}
|
|
4898
4945
|
};
|
|
4899
|
-
var
|
|
4946
|
+
var logger8 = createLogger("agentforge:tools:data:relational:query");
|
|
4900
4947
|
function buildParameterizedQuery(sqlString, params) {
|
|
4901
4948
|
if (!params) {
|
|
4902
4949
|
return sql.raw(sqlString);
|
|
@@ -4971,7 +5018,7 @@ function buildParameterizedQuery(sqlString, params) {
|
|
|
4971
5018
|
}
|
|
4972
5019
|
async function executeQuery2(manager, input, context) {
|
|
4973
5020
|
const startTime = Date.now();
|
|
4974
|
-
|
|
5021
|
+
logger8.debug("Executing query", {
|
|
4975
5022
|
vendor: input.vendor,
|
|
4976
5023
|
hasParams: !!input.params,
|
|
4977
5024
|
paramCount: input.params ? Array.isArray(input.params) ? input.params.length : Object.keys(input.params).length : 0
|
|
@@ -4985,7 +5032,7 @@ async function executeQuery2(manager, input, context) {
|
|
|
4985
5032
|
const executionTime = Date.now() - startTime;
|
|
4986
5033
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
4987
5034
|
const rowCount = result.rowCount || result.affectedRows || rows.length;
|
|
4988
|
-
|
|
5035
|
+
logger8.debug("Query executed successfully", {
|
|
4989
5036
|
vendor: input.vendor,
|
|
4990
5037
|
rowCount,
|
|
4991
5038
|
executionTime
|
|
@@ -4997,7 +5044,7 @@ async function executeQuery2(manager, input, context) {
|
|
|
4997
5044
|
};
|
|
4998
5045
|
} catch (error) {
|
|
4999
5046
|
const executionTime = Date.now() - startTime;
|
|
5000
|
-
|
|
5047
|
+
logger8.error("Query execution failed", {
|
|
5001
5048
|
vendor: input.vendor,
|
|
5002
5049
|
error: error instanceof Error ? error.message : String(error),
|
|
5003
5050
|
executionTime
|
|
@@ -5578,7 +5625,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5578
5625
|
failures
|
|
5579
5626
|
};
|
|
5580
5627
|
}
|
|
5581
|
-
var
|
|
5628
|
+
var logger9 = createLogger("agentforge:tools:data:relational:stream");
|
|
5582
5629
|
var DEFAULT_CHUNK_SIZE = 100;
|
|
5583
5630
|
var MAX_CHUNK_SIZE = 5e3;
|
|
5584
5631
|
var DEFAULT_SAMPLE_SIZE = 50;
|
|
@@ -5711,7 +5758,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5711
5758
|
const endHeapUsed = process.memoryUsage().heapUsed;
|
|
5712
5759
|
peakHeapUsed = Math.max(peakHeapUsed, endHeapUsed);
|
|
5713
5760
|
const executionTime = Date.now() - startTime;
|
|
5714
|
-
|
|
5761
|
+
logger9.debug("Streaming SELECT execution completed", {
|
|
5715
5762
|
table: input.table,
|
|
5716
5763
|
vendor: input.vendor,
|
|
5717
5764
|
chunkCount,
|
|
@@ -5735,7 +5782,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5735
5782
|
};
|
|
5736
5783
|
}
|
|
5737
5784
|
async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
5738
|
-
|
|
5785
|
+
logger9.warn("Running streaming benchmark will execute the SELECT query twice (regular + streaming).", {
|
|
5739
5786
|
table: input.table,
|
|
5740
5787
|
vendor: input.vendor
|
|
5741
5788
|
});
|
|
@@ -5755,7 +5802,7 @@ async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
|
5755
5802
|
0
|
|
5756
5803
|
);
|
|
5757
5804
|
const memorySavedPercent = nonStreamingPeakHeapUsed > 0 ? memorySavedBytes / nonStreamingPeakHeapUsed * 100 : 0;
|
|
5758
|
-
|
|
5805
|
+
logger9.debug("Streaming benchmark completed", {
|
|
5759
5806
|
table: input.table,
|
|
5760
5807
|
vendor: input.vendor,
|
|
5761
5808
|
nonStreamingRows: nonStreamingRows.length,
|
|
@@ -5827,7 +5874,7 @@ function withTransactionTimeout(operation, timeoutMs, onTimeout) {
|
|
|
5827
5874
|
}
|
|
5828
5875
|
|
|
5829
5876
|
// src/data/relational/query/transaction-managed.ts
|
|
5830
|
-
var
|
|
5877
|
+
var logger10 = createLogger("agentforge:tools:data:relational:transaction");
|
|
5831
5878
|
var SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
5832
5879
|
var ManagedTransaction = class {
|
|
5833
5880
|
id;
|
|
@@ -5935,7 +5982,7 @@ var ManagedTransaction = class {
|
|
|
5935
5982
|
await this.executeQuery(sql.raw("PRAGMA read_uncommitted = 1"));
|
|
5936
5983
|
this.shouldRestoreSqliteReadUncommitted = true;
|
|
5937
5984
|
} else {
|
|
5938
|
-
|
|
5985
|
+
logger10.debug("Ignoring SQLite isolation level override", {
|
|
5939
5986
|
transactionId: this.id,
|
|
5940
5987
|
isolationLevel: this.options.isolationLevel
|
|
5941
5988
|
});
|
|
@@ -5960,7 +6007,7 @@ var ManagedTransaction = class {
|
|
|
5960
6007
|
const targetValue = this.sqliteReadUncommittedOriginal ?? 0;
|
|
5961
6008
|
await this.executeQuery(sql.raw(`PRAGMA read_uncommitted = ${targetValue}`));
|
|
5962
6009
|
} catch (error) {
|
|
5963
|
-
|
|
6010
|
+
logger10.warn("Failed to restore SQLite read_uncommitted pragma", {
|
|
5964
6011
|
transactionId: this.id,
|
|
5965
6012
|
error: error instanceof Error ? error.message : String(error)
|
|
5966
6013
|
});
|
|
@@ -5986,14 +6033,14 @@ var ManagedTransaction = class {
|
|
|
5986
6033
|
};
|
|
5987
6034
|
|
|
5988
6035
|
// src/data/relational/query/transaction-runner.ts
|
|
5989
|
-
var
|
|
6036
|
+
var logger11 = createLogger("agentforge:tools:data:relational:transaction");
|
|
5990
6037
|
var transactionSequence = 0;
|
|
5991
6038
|
async function withTransaction(manager, operation, options) {
|
|
5992
6039
|
const startTime = Date.now();
|
|
5993
6040
|
const resolvedOptions = resolveTransactionOptions(options);
|
|
5994
6041
|
const transactionId = `tx-${++transactionSequence}`;
|
|
5995
6042
|
const vendor = manager.getVendor();
|
|
5996
|
-
|
|
6043
|
+
logger11.debug("Starting transaction", {
|
|
5997
6044
|
transactionId,
|
|
5998
6045
|
vendor,
|
|
5999
6046
|
...resolvedOptions.isolationLevel ? { isolationLevel: resolvedOptions.isolationLevel } : {},
|
|
@@ -6020,7 +6067,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
6020
6067
|
if (transaction.isActive()) {
|
|
6021
6068
|
await transaction.commit();
|
|
6022
6069
|
}
|
|
6023
|
-
|
|
6070
|
+
logger11.debug("Transaction committed", {
|
|
6024
6071
|
transactionId,
|
|
6025
6072
|
vendor,
|
|
6026
6073
|
duration: Date.now() - startTime
|
|
@@ -6031,14 +6078,14 @@ async function withTransaction(manager, operation, options) {
|
|
|
6031
6078
|
try {
|
|
6032
6079
|
await transaction.rollback();
|
|
6033
6080
|
} catch (rollbackError) {
|
|
6034
|
-
|
|
6081
|
+
logger11.error("Transaction rollback failed", {
|
|
6035
6082
|
transactionId,
|
|
6036
6083
|
vendor,
|
|
6037
6084
|
error: rollbackError instanceof Error ? rollbackError.message : String(rollbackError)
|
|
6038
6085
|
});
|
|
6039
6086
|
}
|
|
6040
6087
|
}
|
|
6041
|
-
|
|
6088
|
+
logger11.error("Transaction failed", {
|
|
6042
6089
|
transactionId,
|
|
6043
6090
|
vendor,
|
|
6044
6091
|
duration: Date.now() - startTime,
|
|
@@ -6529,7 +6576,7 @@ async function inspectSQLite(runQueryRows) {
|
|
|
6529
6576
|
}
|
|
6530
6577
|
|
|
6531
6578
|
// src/data/relational/schema/schema-inspector.ts
|
|
6532
|
-
var
|
|
6579
|
+
var logger12 = createLogger("agentforge:tools:data:relational:schema-inspector");
|
|
6533
6580
|
var DEFAULT_CACHE_TTL_MS = 6e4;
|
|
6534
6581
|
var schemaCache = /* @__PURE__ */ new Map();
|
|
6535
6582
|
var SchemaInspector = class _SchemaInspector {
|
|
@@ -6557,7 +6604,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6557
6604
|
if (!bypassCache && this.cacheKey) {
|
|
6558
6605
|
const cached = schemaCache.get(this.cacheKey);
|
|
6559
6606
|
if (cached && cached.expiresAt > Date.now()) {
|
|
6560
|
-
|
|
6607
|
+
logger12.debug("Schema cache hit", { vendor: this.vendor });
|
|
6561
6608
|
return filterSchemaTables(cloneSchema(cached.schema), tableFilters);
|
|
6562
6609
|
}
|
|
6563
6610
|
}
|
|
@@ -6602,7 +6649,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6602
6649
|
return result.rows;
|
|
6603
6650
|
}
|
|
6604
6651
|
};
|
|
6605
|
-
var
|
|
6652
|
+
var logger13 = createLogger("agentforge:tools:data:relational:schema-validator");
|
|
6606
6653
|
function validateTableExists(schema, tableName) {
|
|
6607
6654
|
const errors = [];
|
|
6608
6655
|
if (!tableName || typeof tableName !== "string") {
|
|
@@ -6616,7 +6663,7 @@ function validateTableExists(schema, tableName) {
|
|
|
6616
6663
|
`Table "${tableName}" does not exist. Available tables: ${available || "(none)"}`
|
|
6617
6664
|
);
|
|
6618
6665
|
}
|
|
6619
|
-
|
|
6666
|
+
logger13.debug("Table existence validation", { tableName, valid: errors.length === 0 });
|
|
6620
6667
|
return { valid: errors.length === 0, errors };
|
|
6621
6668
|
}
|
|
6622
6669
|
function validateColumnsExist(schema, tableName, columnNames) {
|
|
@@ -6639,7 +6686,7 @@ function validateColumnsExist(schema, tableName, columnNames) {
|
|
|
6639
6686
|
);
|
|
6640
6687
|
}
|
|
6641
6688
|
}
|
|
6642
|
-
|
|
6689
|
+
logger13.debug("Column existence validation", {
|
|
6643
6690
|
tableName,
|
|
6644
6691
|
columnCount: columnNames.length,
|
|
6645
6692
|
valid: errors.length === 0
|
|
@@ -6675,7 +6722,7 @@ function validateColumnTypes(schema, tableName, expectedTypes) {
|
|
|
6675
6722
|
);
|
|
6676
6723
|
}
|
|
6677
6724
|
}
|
|
6678
|
-
|
|
6725
|
+
logger13.debug("Column type validation", {
|
|
6679
6726
|
tableName,
|
|
6680
6727
|
typeChecks: Object.keys(expectedTypes).length,
|
|
6681
6728
|
valid: errors.length === 0
|
|
@@ -6695,7 +6742,7 @@ function findTable(schema, tableName) {
|
|
|
6695
6742
|
function formatTableName(table) {
|
|
6696
6743
|
return table.schema ? `${table.schema}.${table.name}` : table.name;
|
|
6697
6744
|
}
|
|
6698
|
-
var
|
|
6745
|
+
var logger14 = createLogger("agentforge:tools:data:relational:type-mapper");
|
|
6699
6746
|
var POSTGRES_TYPE_MAP = {
|
|
6700
6747
|
// Numeric
|
|
6701
6748
|
smallint: "number",
|
|
@@ -6861,7 +6908,7 @@ function mapColumnType(vendor, dbType, nullable = false) {
|
|
|
6861
6908
|
const result = { tsType, nullable, dbType };
|
|
6862
6909
|
if (tsType === "unknown" && normalised !== "json" && normalised !== "jsonb") {
|
|
6863
6910
|
result.notes = `No explicit mapping for "${dbType}"; defaulting to unknown`;
|
|
6864
|
-
|
|
6911
|
+
logger14.debug("Unmapped database type", { vendor, dbType, normalised });
|
|
6865
6912
|
}
|
|
6866
6913
|
if ((normalised === "bigint" || normalised === "int8" || normalised === "bigserial") && (vendor === "postgresql" || vendor === "mysql")) {
|
|
6867
6914
|
result.notes = "Mapped to string to avoid JavaScript number precision loss for 64-bit integers";
|
|
@@ -6876,7 +6923,7 @@ function mapSchemaTypes(vendor, columns) {
|
|
|
6876
6923
|
}
|
|
6877
6924
|
result.get(col.table).set(col.name, mapColumnType(vendor, col.type, col.nullable));
|
|
6878
6925
|
}
|
|
6879
|
-
|
|
6926
|
+
logger14.debug("Schema type mapping complete", {
|
|
6880
6927
|
vendor,
|
|
6881
6928
|
tables: result.size,
|
|
6882
6929
|
columns: columns.length
|
|
@@ -6893,7 +6940,7 @@ function normaliseDbType(raw) {
|
|
|
6893
6940
|
type = type.replace(/\s+unsigned$/, "");
|
|
6894
6941
|
return type.trim();
|
|
6895
6942
|
}
|
|
6896
|
-
var
|
|
6943
|
+
var logger15 = createLogger("agentforge:tools:data:relational:schema-diff");
|
|
6897
6944
|
function diffSchemas(before, after) {
|
|
6898
6945
|
const tableDiffs = [];
|
|
6899
6946
|
let columnsAdded = 0;
|
|
@@ -6933,7 +6980,7 @@ function diffSchemas(before, after) {
|
|
|
6933
6980
|
const tablesRemoved = tableDiffs.filter((d) => d.type === "removed").length;
|
|
6934
6981
|
const tablesChanged = tableDiffs.filter((d) => d.type === "changed").length;
|
|
6935
6982
|
const identical = tableDiffs.length === 0;
|
|
6936
|
-
|
|
6983
|
+
logger15.debug("Schema diff computed", {
|
|
6937
6984
|
identical,
|
|
6938
6985
|
tablesAdded,
|
|
6939
6986
|
tablesRemoved,
|
|
@@ -6977,7 +7024,7 @@ function importSchemaFromJson(json) {
|
|
|
6977
7024
|
throw new Error(`Invalid schema JSON: table "${table.name}" missing "primaryKey" array`);
|
|
6978
7025
|
}
|
|
6979
7026
|
}
|
|
6980
|
-
|
|
7027
|
+
logger15.debug("Schema imported from JSON", {
|
|
6981
7028
|
vendor: obj.vendor,
|
|
6982
7029
|
tableCount: obj.tables.length
|
|
6983
7030
|
});
|
|
@@ -7274,7 +7321,7 @@ function isSafeValidationError(error) {
|
|
|
7274
7321
|
}
|
|
7275
7322
|
|
|
7276
7323
|
// src/data/relational/tools/relational-select/executor.ts
|
|
7277
|
-
var
|
|
7324
|
+
var logger16 = createLogger("agentforge:tools:data:relational:select");
|
|
7278
7325
|
function toSelectQueryInput(input) {
|
|
7279
7326
|
return {
|
|
7280
7327
|
table: input.table,
|
|
@@ -7288,7 +7335,7 @@ function toSelectQueryInput(input) {
|
|
|
7288
7335
|
}
|
|
7289
7336
|
async function executeSelect(manager, input, context) {
|
|
7290
7337
|
const startTime = Date.now();
|
|
7291
|
-
|
|
7338
|
+
logger16.debug("Building SELECT query", {
|
|
7292
7339
|
vendor: input.vendor,
|
|
7293
7340
|
table: input.table,
|
|
7294
7341
|
hasWhere: !!input.where,
|
|
@@ -7306,7 +7353,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7306
7353
|
};
|
|
7307
7354
|
const streamInput = toSelectQueryInput(input);
|
|
7308
7355
|
if (input.streaming.benchmark) {
|
|
7309
|
-
|
|
7356
|
+
logger16.warn("Streaming benchmark enabled; SELECT will execute up to three times (result + benchmark regular + benchmark streaming).", {
|
|
7310
7357
|
vendor: input.vendor,
|
|
7311
7358
|
table: input.table,
|
|
7312
7359
|
chunkSize: streamOptions.chunkSize ?? DEFAULT_CHUNK_SIZE,
|
|
@@ -7317,7 +7364,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7317
7364
|
const streamResult = await executeStreamingSelect(executor, streamInput, streamOptions);
|
|
7318
7365
|
const benchmark = input.streaming.benchmark ? await benchmarkStreamingSelectMemory(executor, streamInput, streamOptions) : void 0;
|
|
7319
7366
|
const executionTime2 = Date.now() - startTime;
|
|
7320
|
-
|
|
7367
|
+
logger16.debug("Streaming SELECT query executed successfully", {
|
|
7321
7368
|
vendor: input.vendor,
|
|
7322
7369
|
table: input.table,
|
|
7323
7370
|
rowCount: streamResult.rowCount,
|
|
@@ -7346,7 +7393,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7346
7393
|
const executionTime = Date.now() - startTime;
|
|
7347
7394
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
7348
7395
|
const rowCount = rows.length;
|
|
7349
|
-
|
|
7396
|
+
logger16.debug("SELECT query executed successfully", {
|
|
7350
7397
|
vendor: input.vendor,
|
|
7351
7398
|
table: input.table,
|
|
7352
7399
|
rowCount,
|
|
@@ -7359,7 +7406,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7359
7406
|
};
|
|
7360
7407
|
} catch (error) {
|
|
7361
7408
|
const executionTime = Date.now() - startTime;
|
|
7362
|
-
|
|
7409
|
+
logger16.error("SELECT query execution failed", {
|
|
7363
7410
|
vendor: input.vendor,
|
|
7364
7411
|
table: input.table,
|
|
7365
7412
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -7535,7 +7582,7 @@ function isSafeInsertError(error) {
|
|
|
7535
7582
|
}
|
|
7536
7583
|
|
|
7537
7584
|
// src/data/relational/tools/relational-insert/executor.ts
|
|
7538
|
-
var
|
|
7585
|
+
var logger17 = createLogger("agentforge:tools:data:relational:insert");
|
|
7539
7586
|
function toNumber(value) {
|
|
7540
7587
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7541
7588
|
}
|
|
@@ -7684,7 +7731,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7684
7731
|
maxRetries: options.maxRetries,
|
|
7685
7732
|
retryDelayMs: options.retryDelayMs,
|
|
7686
7733
|
onProgress: (progress) => {
|
|
7687
|
-
|
|
7734
|
+
logger17.debug("INSERT batch progress", {
|
|
7688
7735
|
vendor: input.vendor,
|
|
7689
7736
|
table: input.table,
|
|
7690
7737
|
...progress
|
|
@@ -7697,7 +7744,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7697
7744
|
const insertedIds = batchResult.results.flatMap((result) => result.insertedIds);
|
|
7698
7745
|
let benchmark;
|
|
7699
7746
|
if (options.benchmark) {
|
|
7700
|
-
|
|
7747
|
+
logger17.warn("INSERT batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
7701
7748
|
vendor: input.vendor,
|
|
7702
7749
|
table: input.table,
|
|
7703
7750
|
totalRows: input.data.length,
|
|
@@ -7734,7 +7781,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7734
7781
|
}
|
|
7735
7782
|
async function executeInsert(manager, input, context) {
|
|
7736
7783
|
const startTime = Date.now();
|
|
7737
|
-
|
|
7784
|
+
logger17.debug("Building INSERT query", {
|
|
7738
7785
|
vendor: input.vendor,
|
|
7739
7786
|
table: input.table,
|
|
7740
7787
|
isBatch: Array.isArray(input.data),
|
|
@@ -7750,7 +7797,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7750
7797
|
batchOptions
|
|
7751
7798
|
) : await executeInsertOnce(manager, input, context);
|
|
7752
7799
|
const executionTime = Date.now() - startTime;
|
|
7753
|
-
|
|
7800
|
+
logger17.debug("INSERT query executed successfully", {
|
|
7754
7801
|
vendor: input.vendor,
|
|
7755
7802
|
table: input.table,
|
|
7756
7803
|
rowCount: result.rowCount,
|
|
@@ -7766,7 +7813,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7766
7813
|
};
|
|
7767
7814
|
} catch (error) {
|
|
7768
7815
|
const executionTime = Date.now() - startTime;
|
|
7769
|
-
|
|
7816
|
+
logger17.error("INSERT query execution failed", {
|
|
7770
7817
|
vendor: input.vendor,
|
|
7771
7818
|
table: input.table,
|
|
7772
7819
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8096,7 +8143,7 @@ function isSafeUpdateError(error) {
|
|
|
8096
8143
|
}
|
|
8097
8144
|
|
|
8098
8145
|
// src/data/relational/tools/relational-update/executor.ts
|
|
8099
|
-
var
|
|
8146
|
+
var logger18 = createLogger("agentforge:tools:data:relational:update");
|
|
8100
8147
|
function toNumber2(value) {
|
|
8101
8148
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8102
8149
|
}
|
|
@@ -8218,7 +8265,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8218
8265
|
maxRetries: options.maxRetries,
|
|
8219
8266
|
retryDelayMs: options.retryDelayMs,
|
|
8220
8267
|
onProgress: (progress) => {
|
|
8221
|
-
|
|
8268
|
+
logger18.debug("UPDATE batch progress", {
|
|
8222
8269
|
vendor: input.vendor,
|
|
8223
8270
|
table: input.table,
|
|
8224
8271
|
...progress
|
|
@@ -8230,7 +8277,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8230
8277
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8231
8278
|
let benchmark;
|
|
8232
8279
|
if (options.benchmark) {
|
|
8233
|
-
|
|
8280
|
+
logger18.warn("UPDATE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8234
8281
|
vendor: input.vendor,
|
|
8235
8282
|
table: input.table,
|
|
8236
8283
|
operationCount: input.operations.length,
|
|
@@ -8265,7 +8312,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8265
8312
|
}
|
|
8266
8313
|
async function executeUpdate(manager, input, context) {
|
|
8267
8314
|
const startTime = Date.now();
|
|
8268
|
-
|
|
8315
|
+
logger18.debug("Building UPDATE query", {
|
|
8269
8316
|
vendor: input.vendor,
|
|
8270
8317
|
table: input.table,
|
|
8271
8318
|
hasWhere: !!input.where?.length,
|
|
@@ -8283,7 +8330,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8283
8330
|
batchOptions
|
|
8284
8331
|
) : await executeSingleUpdate(manager, input, toSingleUpdateOperation(input), context);
|
|
8285
8332
|
const executionTime = Date.now() - startTime;
|
|
8286
|
-
|
|
8333
|
+
logger18.debug("UPDATE query executed successfully", {
|
|
8287
8334
|
vendor: input.vendor,
|
|
8288
8335
|
table: input.table,
|
|
8289
8336
|
rowCount: result.rowCount,
|
|
@@ -8297,7 +8344,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8297
8344
|
};
|
|
8298
8345
|
} catch (error) {
|
|
8299
8346
|
const executionTime = Date.now() - startTime;
|
|
8300
|
-
|
|
8347
|
+
logger18.error("UPDATE query execution failed", {
|
|
8301
8348
|
vendor: input.vendor,
|
|
8302
8349
|
table: input.table,
|
|
8303
8350
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8601,7 +8648,7 @@ function isSafeDeleteError(error) {
|
|
|
8601
8648
|
}
|
|
8602
8649
|
|
|
8603
8650
|
// src/data/relational/tools/relational-delete/executor.ts
|
|
8604
|
-
var
|
|
8651
|
+
var logger19 = createLogger("agentforge:tools:data:relational:delete");
|
|
8605
8652
|
function toNumber3(value) {
|
|
8606
8653
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8607
8654
|
}
|
|
@@ -8722,7 +8769,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8722
8769
|
maxRetries: options.maxRetries,
|
|
8723
8770
|
retryDelayMs: options.retryDelayMs,
|
|
8724
8771
|
onProgress: (progress) => {
|
|
8725
|
-
|
|
8772
|
+
logger19.debug("DELETE batch progress", {
|
|
8726
8773
|
vendor: input.vendor,
|
|
8727
8774
|
table: input.table,
|
|
8728
8775
|
...progress
|
|
@@ -8735,7 +8782,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8735
8782
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8736
8783
|
let benchmark;
|
|
8737
8784
|
if (options.benchmark) {
|
|
8738
|
-
|
|
8785
|
+
logger19.warn("DELETE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8739
8786
|
vendor: input.vendor,
|
|
8740
8787
|
table: input.table,
|
|
8741
8788
|
operationCount: input.operations.length,
|
|
@@ -8771,7 +8818,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8771
8818
|
}
|
|
8772
8819
|
async function executeDelete(manager, input, context) {
|
|
8773
8820
|
const startTime = Date.now();
|
|
8774
|
-
|
|
8821
|
+
logger19.debug("Building DELETE query", {
|
|
8775
8822
|
vendor: input.vendor,
|
|
8776
8823
|
table: input.table,
|
|
8777
8824
|
hasWhere: !!input.where?.length,
|
|
@@ -8790,7 +8837,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8790
8837
|
batchOptions
|
|
8791
8838
|
) : await executeSingleDelete(manager, input, toSingleDeleteOperation(input), context);
|
|
8792
8839
|
const executionTime = Date.now() - startTime;
|
|
8793
|
-
|
|
8840
|
+
logger19.debug("DELETE query executed successfully", {
|
|
8794
8841
|
vendor: input.vendor,
|
|
8795
8842
|
table: input.table,
|
|
8796
8843
|
rowCount: result.rowCount,
|
|
@@ -8806,7 +8853,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8806
8853
|
};
|
|
8807
8854
|
} catch (error) {
|
|
8808
8855
|
const executionTime = Date.now() - startTime;
|
|
8809
|
-
|
|
8856
|
+
logger19.error("DELETE query execution failed", {
|
|
8810
8857
|
vendor: input.vendor,
|
|
8811
8858
|
table: input.table,
|
|
8812
8859
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8911,7 +8958,7 @@ function isSafeGetSchemaValidationError(error) {
|
|
|
8911
8958
|
}
|
|
8912
8959
|
|
|
8913
8960
|
// src/data/relational/tools/relational-get-schema.ts
|
|
8914
|
-
var
|
|
8961
|
+
var logger20 = createLogger("agentforge:tools:data:relational:get-schema");
|
|
8915
8962
|
function buildSchemaCacheKey(vendor, connectionString, database) {
|
|
8916
8963
|
const databaseScope = database ?? "default";
|
|
8917
8964
|
const connectionHash = createHash("sha256").update(connectionString).digest("hex");
|
|
@@ -8983,7 +9030,7 @@ var relationalGetSchema = toolBuilder().name("relational-get-schema").displayNam
|
|
|
8983
9030
|
summary
|
|
8984
9031
|
};
|
|
8985
9032
|
} catch (error) {
|
|
8986
|
-
|
|
9033
|
+
logger20.error("Schema introspection failed", {
|
|
8987
9034
|
vendor: input.vendor,
|
|
8988
9035
|
hasTablesFilter: Array.isArray(input.tables),
|
|
8989
9036
|
tablesFilterCount: input.tables?.length ?? 0,
|
|
@@ -10149,7 +10196,7 @@ var AskHumanInputSchema = z.object({
|
|
|
10149
10196
|
suggestions: z.array(z.string()).optional().describe("Suggested responses for the human")
|
|
10150
10197
|
});
|
|
10151
10198
|
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || LogLevel.INFO;
|
|
10152
|
-
var
|
|
10199
|
+
var logger21 = createLogger("agentforge:tools:agent:ask-human", { level: logLevel3 });
|
|
10153
10200
|
function isRecord2(value) {
|
|
10154
10201
|
return typeof value === "object" && value !== null;
|
|
10155
10202
|
}
|
|
@@ -10214,7 +10261,7 @@ function createAskHumanTool() {
|
|
|
10214
10261
|
suggestions: validatedInput.suggestions,
|
|
10215
10262
|
status: "pending"
|
|
10216
10263
|
};
|
|
10217
|
-
|
|
10264
|
+
logger21.debug("About to call interrupt()", {
|
|
10218
10265
|
humanRequest: {
|
|
10219
10266
|
id: humanRequest.id,
|
|
10220
10267
|
question: humanRequest.question,
|
|
@@ -10230,13 +10277,13 @@ function createAskHumanTool() {
|
|
|
10230
10277
|
let response;
|
|
10231
10278
|
try {
|
|
10232
10279
|
response = interrupt(humanRequest);
|
|
10233
|
-
|
|
10280
|
+
logger21.debug("interrupt() returned successfully", {
|
|
10234
10281
|
responseType: typeof response,
|
|
10235
10282
|
hasResponse: response != null,
|
|
10236
10283
|
...typeof response === "string" ? { responseLength: response.length } : {}
|
|
10237
10284
|
});
|
|
10238
10285
|
} catch (error) {
|
|
10239
|
-
|
|
10286
|
+
logger21.debug("interrupt() threw error (expected for GraphInterrupt)", {
|
|
10240
10287
|
...error && typeof error === "object" && "constructor" in error ? { errorType: error.constructor?.name } : {},
|
|
10241
10288
|
error: error instanceof Error ? error.message : String(error)
|
|
10242
10289
|
});
|