@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.cjs
CHANGED
|
@@ -815,7 +815,7 @@ function getDefaultSlackClient() {
|
|
|
815
815
|
}
|
|
816
816
|
};
|
|
817
817
|
}
|
|
818
|
-
function createSendSlackMessageTool(getSlackClient,
|
|
818
|
+
function createSendSlackMessageTool(getSlackClient, logger22) {
|
|
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, logger23) {
|
|
|
824
824
|
message: zod.z.string().describe("Message content to send")
|
|
825
825
|
})
|
|
826
826
|
).implementSafe(async ({ channel, message }) => {
|
|
827
|
-
|
|
827
|
+
logger22.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, logger23) {
|
|
|
833
833
|
username: config.botName,
|
|
834
834
|
icon_emoji: config.botIcon
|
|
835
835
|
});
|
|
836
|
-
|
|
836
|
+
logger22.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, logger23) {
|
|
|
846
846
|
message_id: result.ts
|
|
847
847
|
};
|
|
848
848
|
} catch (error) {
|
|
849
|
-
|
|
849
|
+
logger22.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, logger23) {
|
|
|
855
855
|
}
|
|
856
856
|
}).build();
|
|
857
857
|
}
|
|
858
|
-
function createNotifySlackTool(getSlackClient,
|
|
858
|
+
function createNotifySlackTool(getSlackClient, logger22) {
|
|
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, logger23) {
|
|
|
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
|
+
logger22.info("notify-slack called", {
|
|
869
869
|
channel,
|
|
870
870
|
messageLength: message.length,
|
|
871
871
|
mentionCount: mentions.length
|
|
@@ -879,7 +879,7 @@ function createNotifySlackTool(getSlackClient, logger23) {
|
|
|
879
879
|
username: config.botName,
|
|
880
880
|
icon_emoji: config.botIcon
|
|
881
881
|
});
|
|
882
|
-
|
|
882
|
+
logger22.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, logger23) {
|
|
|
893
893
|
};
|
|
894
894
|
}).build();
|
|
895
895
|
}
|
|
896
|
-
function createGetSlackChannelsTool(getSlackClient,
|
|
896
|
+
function createGetSlackChannelsTool(getSlackClient, logger22) {
|
|
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, logger23) {
|
|
|
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
|
+
logger22.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, logger23) {
|
|
|
915
915
|
});
|
|
916
916
|
allChannels = [...allChannels, ...privateChannels.channels || []];
|
|
917
917
|
}
|
|
918
|
-
|
|
918
|
+
logger22.info("get-slack-channels result", {
|
|
919
919
|
channelCount: allChannels.length,
|
|
920
920
|
includePrivate: include_private
|
|
921
921
|
});
|
|
@@ -930,7 +930,7 @@ function createGetSlackChannelsTool(getSlackClient, logger23) {
|
|
|
930
930
|
};
|
|
931
931
|
}).build();
|
|
932
932
|
}
|
|
933
|
-
function createGetSlackMessagesTool(getSlackClient,
|
|
933
|
+
function createGetSlackMessagesTool(getSlackClient, logger22) {
|
|
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, logger23) {
|
|
|
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
|
+
logger22.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, logger23) {
|
|
|
950
950
|
});
|
|
951
951
|
const found = channels.channels?.find((c) => c.name === channel);
|
|
952
952
|
if (!found) {
|
|
953
|
-
|
|
953
|
+
logger22.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, logger23) {
|
|
|
962
962
|
limit: Math.min(limit, 100)
|
|
963
963
|
// Cap at 100 for performance
|
|
964
964
|
});
|
|
965
|
-
|
|
965
|
+
logger22.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, logger23) {
|
|
|
980
980
|
})) || []
|
|
981
981
|
};
|
|
982
982
|
} catch (error) {
|
|
983
|
-
|
|
983
|
+
logger22.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, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1091
1091
|
lastModified: page.version?.when || ""
|
|
1092
1092
|
}));
|
|
1093
1093
|
if (results.length === 0) {
|
|
1094
|
-
|
|
1094
|
+
logger22.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
|
+
logger22.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, logger23) {
|
|
|
1112
1112
|
results
|
|
1113
1113
|
});
|
|
1114
1114
|
} catch (error) {
|
|
1115
|
-
|
|
1115
|
+
logger22.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, logger23) {
|
|
|
1124
1124
|
}
|
|
1125
1125
|
}).build();
|
|
1126
1126
|
}
|
|
1127
|
-
function createGetConfluencePageTool(getAuth, getAuthHeader2,
|
|
1127
|
+
function createGetConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1141
1141
|
}
|
|
1142
1142
|
});
|
|
1143
1143
|
const page = response.data;
|
|
1144
|
-
|
|
1144
|
+
logger22.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, logger23) {
|
|
|
1163
1163
|
}
|
|
1164
1164
|
});
|
|
1165
1165
|
} catch (error) {
|
|
1166
|
-
|
|
1166
|
+
logger22.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, logger23) {
|
|
|
1175
1175
|
}
|
|
1176
1176
|
}).build();
|
|
1177
1177
|
}
|
|
1178
|
-
function createListConfluenceSpacesTool(getAuth, getAuthHeader2,
|
|
1178
|
+
function createListConfluenceSpacesTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1198
1198
|
description: space.description?.plain?.value || "",
|
|
1199
1199
|
url: `${ATLASSIAN_SITE_URL}/wiki${space._links.webui}`
|
|
1200
1200
|
}));
|
|
1201
|
-
|
|
1201
|
+
logger22.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, logger23) {
|
|
|
1209
1209
|
spaces
|
|
1210
1210
|
});
|
|
1211
1211
|
} catch (error) {
|
|
1212
|
-
|
|
1212
|
+
logger22.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, logger23) {
|
|
|
1220
1220
|
}
|
|
1221
1221
|
}).build();
|
|
1222
1222
|
}
|
|
1223
|
-
function createGetSpacePagesTool(getAuth, getAuthHeader2,
|
|
1223
|
+
function createGetSpacePagesTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1247
1247
|
lastModified: page.version?.when || ""
|
|
1248
1248
|
}));
|
|
1249
1249
|
if (pages.length === 0) {
|
|
1250
|
-
|
|
1250
|
+
logger22.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
|
+
logger22.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, logger23) {
|
|
|
1266
1266
|
pages
|
|
1267
1267
|
});
|
|
1268
1268
|
} catch (error) {
|
|
1269
|
-
|
|
1269
|
+
logger22.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, logger23) {
|
|
|
1278
1278
|
}
|
|
1279
1279
|
}).build();
|
|
1280
1280
|
}
|
|
1281
|
-
function createCreateConfluencePageTool(getAuth, getAuthHeader2,
|
|
1281
|
+
function createCreateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1312
1312
|
}
|
|
1313
1313
|
}
|
|
1314
1314
|
);
|
|
1315
|
-
|
|
1315
|
+
logger22.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, logger23) {
|
|
|
1328
1328
|
}
|
|
1329
1329
|
});
|
|
1330
1330
|
} catch (error) {
|
|
1331
|
-
|
|
1331
|
+
logger22.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, logger23) {
|
|
|
1341
1341
|
}
|
|
1342
1342
|
}).build();
|
|
1343
1343
|
}
|
|
1344
|
-
function createUpdateConfluencePageTool(getAuth, getAuthHeader2,
|
|
1344
|
+
function createUpdateConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.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, logger23) {
|
|
|
1380
1380
|
}
|
|
1381
1381
|
}
|
|
1382
1382
|
);
|
|
1383
|
-
|
|
1383
|
+
logger22.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, logger23) {
|
|
|
1397
1397
|
}
|
|
1398
1398
|
});
|
|
1399
1399
|
} catch (error) {
|
|
1400
|
-
|
|
1400
|
+
logger22.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, logger23) {
|
|
|
1410
1410
|
}
|
|
1411
1411
|
}).build();
|
|
1412
1412
|
}
|
|
1413
|
-
function createArchiveConfluencePageTool(getAuth, getAuthHeader2,
|
|
1413
|
+
function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger22) {
|
|
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
|
+
logger22.info("archive-confluence-page called", {
|
|
1419
1419
|
page_id,
|
|
1420
1420
|
...reason ? { reason } : {}
|
|
1421
1421
|
});
|
|
@@ -1449,7 +1449,7 @@ function createArchiveConfluencePageTool(getAuth, getAuthHeader2, logger23) {
|
|
|
1449
1449
|
}
|
|
1450
1450
|
}
|
|
1451
1451
|
);
|
|
1452
|
-
|
|
1452
|
+
logger22.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, logger23) {
|
|
|
1467
1467
|
}
|
|
1468
1468
|
});
|
|
1469
1469
|
} catch (error) {
|
|
1470
|
-
|
|
1470
|
+
logger22.error("archive-confluence-page error", {
|
|
1471
1471
|
page_id,
|
|
1472
1472
|
error: error.response?.data?.message || error.message,
|
|
1473
1473
|
status: error.response?.status
|
|
@@ -2456,6 +2456,20 @@ function validateBatch(texts) {
|
|
|
2456
2456
|
}
|
|
2457
2457
|
});
|
|
2458
2458
|
}
|
|
2459
|
+
var embeddingLogger = core.createLogger("agentforge:tools:neo4j:embeddings");
|
|
2460
|
+
var NOT_INITIALIZED_ERROR = "Embedding manager not initialized. Call initialize() or initializeFromEnv() first.";
|
|
2461
|
+
function requireEmbeddingProvider(provider) {
|
|
2462
|
+
if (!provider) {
|
|
2463
|
+
throw new Error(NOT_INITIALIZED_ERROR);
|
|
2464
|
+
}
|
|
2465
|
+
return provider;
|
|
2466
|
+
}
|
|
2467
|
+
function requireEmbeddingConfig(config) {
|
|
2468
|
+
if (!config) {
|
|
2469
|
+
throw new Error(NOT_INITIALIZED_ERROR);
|
|
2470
|
+
}
|
|
2471
|
+
return config;
|
|
2472
|
+
}
|
|
2459
2473
|
var OpenAIEmbeddingProvider = class {
|
|
2460
2474
|
name = "openai";
|
|
2461
2475
|
defaultModel = "text-embedding-3-small";
|
|
@@ -2940,8 +2954,176 @@ var OllamaEmbeddingProvider = class {
|
|
|
2940
2954
|
}
|
|
2941
2955
|
};
|
|
2942
2956
|
|
|
2957
|
+
// src/data/neo4j/embeddings/embedding-provider-factory.ts
|
|
2958
|
+
var DEFAULT_OLLAMA_BASE_URL = "http://localhost:11434";
|
|
2959
|
+
function parseEmbeddingProvider(providerName) {
|
|
2960
|
+
switch (providerName) {
|
|
2961
|
+
case "openai":
|
|
2962
|
+
case "cohere":
|
|
2963
|
+
case "huggingface":
|
|
2964
|
+
case "voyage":
|
|
2965
|
+
case "ollama":
|
|
2966
|
+
return providerName;
|
|
2967
|
+
default:
|
|
2968
|
+
throw new Error(`Unknown embedding provider: ${providerName}`);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
function getDefaultEmbeddingModel(provider) {
|
|
2972
|
+
switch (provider) {
|
|
2973
|
+
case "openai":
|
|
2974
|
+
return "text-embedding-3-small";
|
|
2975
|
+
case "cohere":
|
|
2976
|
+
return "embed-english-v3.0";
|
|
2977
|
+
case "huggingface":
|
|
2978
|
+
return "sentence-transformers/all-MiniLM-L6-v2";
|
|
2979
|
+
case "voyage":
|
|
2980
|
+
return "voyage-2";
|
|
2981
|
+
case "ollama":
|
|
2982
|
+
return "nomic-embed-text";
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
function createEmbeddingProvider(providerName, apiKey, model, baseUrl) {
|
|
2986
|
+
switch (providerName) {
|
|
2987
|
+
case "openai":
|
|
2988
|
+
return new OpenAIEmbeddingProvider(apiKey);
|
|
2989
|
+
case "cohere":
|
|
2990
|
+
return new CohereEmbeddingProvider(apiKey);
|
|
2991
|
+
case "huggingface":
|
|
2992
|
+
return new HuggingFaceEmbeddingProvider(apiKey);
|
|
2993
|
+
case "voyage":
|
|
2994
|
+
return new VoyageEmbeddingProvider(apiKey);
|
|
2995
|
+
case "ollama":
|
|
2996
|
+
return new OllamaEmbeddingProvider(model, baseUrl || DEFAULT_OLLAMA_BASE_URL);
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
|
|
3000
|
+
// src/data/neo4j/embeddings/embedding-environment.ts
|
|
3001
|
+
function resolveEmbeddingEnvironment() {
|
|
3002
|
+
const providerName = validateEmbeddingProvider(getEmbeddingProvider());
|
|
3003
|
+
const model = getEmbeddingModel() || getDefaultEmbeddingModel(providerName);
|
|
3004
|
+
embeddingLogger.debug("Initializing embedding manager from environment", {
|
|
3005
|
+
provider: providerName,
|
|
3006
|
+
model
|
|
3007
|
+
});
|
|
3008
|
+
switch (providerName) {
|
|
3009
|
+
case "openai":
|
|
3010
|
+
return createCredentialEnvironment(
|
|
3011
|
+
providerName,
|
|
3012
|
+
model,
|
|
3013
|
+
getOpenAIApiKey(),
|
|
3014
|
+
"OPENAI_API_KEY environment variable is required for OpenAI embeddings",
|
|
3015
|
+
"OPENAI_API_KEY environment variable not set"
|
|
3016
|
+
);
|
|
3017
|
+
case "cohere":
|
|
3018
|
+
return createCredentialEnvironment(
|
|
3019
|
+
providerName,
|
|
3020
|
+
model,
|
|
3021
|
+
getCohereApiKey(),
|
|
3022
|
+
"COHERE_API_KEY environment variable is required for Cohere embeddings",
|
|
3023
|
+
"COHERE_API_KEY environment variable not set"
|
|
3024
|
+
);
|
|
3025
|
+
case "huggingface":
|
|
3026
|
+
return createCredentialEnvironment(
|
|
3027
|
+
providerName,
|
|
3028
|
+
model,
|
|
3029
|
+
getHuggingFaceApiKey(),
|
|
3030
|
+
"HUGGINGFACE_API_KEY environment variable is required for HuggingFace embeddings",
|
|
3031
|
+
"HUGGINGFACE_API_KEY environment variable not set"
|
|
3032
|
+
);
|
|
3033
|
+
case "voyage":
|
|
3034
|
+
return createCredentialEnvironment(
|
|
3035
|
+
providerName,
|
|
3036
|
+
model,
|
|
3037
|
+
getVoyageApiKey(),
|
|
3038
|
+
"VOYAGE_API_KEY environment variable is required for Voyage AI embeddings",
|
|
3039
|
+
"VOYAGE_API_KEY environment variable not set"
|
|
3040
|
+
);
|
|
3041
|
+
case "ollama": {
|
|
3042
|
+
const baseUrl = getOllamaBaseUrl();
|
|
3043
|
+
embeddingLogger.debug("Using Ollama (local, no API key required)", {
|
|
3044
|
+
baseUrl
|
|
3045
|
+
});
|
|
3046
|
+
return {
|
|
3047
|
+
providerName,
|
|
3048
|
+
apiKey: "",
|
|
3049
|
+
baseUrl,
|
|
3050
|
+
config: {
|
|
3051
|
+
provider: providerName,
|
|
3052
|
+
model,
|
|
3053
|
+
apiKey: ""
|
|
3054
|
+
}
|
|
3055
|
+
};
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
function validateEmbeddingProvider(providerName) {
|
|
3060
|
+
try {
|
|
3061
|
+
return parseEmbeddingProvider(providerName);
|
|
3062
|
+
} catch (error) {
|
|
3063
|
+
embeddingLogger.error("Unknown embedding provider", {
|
|
3064
|
+
provider: providerName
|
|
3065
|
+
});
|
|
3066
|
+
throw error;
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
function createCredentialEnvironment(providerName, model, apiKey, missingKeyError, missingKeyLog) {
|
|
3070
|
+
if (!apiKey) {
|
|
3071
|
+
embeddingLogger.error(missingKeyLog, {
|
|
3072
|
+
provider: providerName,
|
|
3073
|
+
required: true
|
|
3074
|
+
});
|
|
3075
|
+
throw new Error(missingKeyError);
|
|
3076
|
+
}
|
|
3077
|
+
embeddingLogger.debug(`${providerName} API key found`);
|
|
3078
|
+
return {
|
|
3079
|
+
providerName,
|
|
3080
|
+
apiKey,
|
|
3081
|
+
config: {
|
|
3082
|
+
provider: providerName,
|
|
3083
|
+
model,
|
|
3084
|
+
apiKey: ""
|
|
3085
|
+
}
|
|
3086
|
+
};
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3089
|
+
// src/data/neo4j/embeddings/embedding-generation.ts
|
|
3090
|
+
async function generateManagedEmbedding(state, text, model) {
|
|
3091
|
+
const startTime = Date.now();
|
|
3092
|
+
const modelToUse = model || state.config.model;
|
|
3093
|
+
embeddingLogger.debug("Generating embedding", {
|
|
3094
|
+
provider: state.provider.name,
|
|
3095
|
+
model: modelToUse,
|
|
3096
|
+
textLength: text.length
|
|
3097
|
+
});
|
|
3098
|
+
const result = await state.provider.generateEmbedding(text, modelToUse);
|
|
3099
|
+
embeddingLogger.info("Embedding generated", {
|
|
3100
|
+
provider: state.provider.name,
|
|
3101
|
+
model: result.model,
|
|
3102
|
+
dimensions: result.dimensions,
|
|
3103
|
+
duration: Date.now() - startTime
|
|
3104
|
+
});
|
|
3105
|
+
return result;
|
|
3106
|
+
}
|
|
3107
|
+
async function generateManagedBatchEmbeddings(state, texts, model) {
|
|
3108
|
+
const startTime = Date.now();
|
|
3109
|
+
const modelToUse = model || state.config.model;
|
|
3110
|
+
embeddingLogger.debug("Generating batch embeddings", {
|
|
3111
|
+
provider: state.provider.name,
|
|
3112
|
+
model: modelToUse,
|
|
3113
|
+
count: texts.length
|
|
3114
|
+
});
|
|
3115
|
+
const result = await state.provider.generateBatchEmbeddings(texts, modelToUse);
|
|
3116
|
+
embeddingLogger.info("Batch embeddings generated", {
|
|
3117
|
+
provider: state.provider.name,
|
|
3118
|
+
model: result.model,
|
|
3119
|
+
dimensions: result.dimensions,
|
|
3120
|
+
count: texts.length,
|
|
3121
|
+
duration: Date.now() - startTime
|
|
3122
|
+
});
|
|
3123
|
+
return result;
|
|
3124
|
+
}
|
|
3125
|
+
|
|
2943
3126
|
// src/data/neo4j/embeddings/embedding-manager.ts
|
|
2944
|
-
var logger4 = core.createLogger("agentforge:tools:neo4j:embeddings");
|
|
2945
3127
|
var EmbeddingManager = class {
|
|
2946
3128
|
provider = null;
|
|
2947
3129
|
config = null;
|
|
@@ -2949,103 +3131,31 @@ var EmbeddingManager = class {
|
|
|
2949
3131
|
* Initialize with configuration
|
|
2950
3132
|
*/
|
|
2951
3133
|
initialize(config) {
|
|
2952
|
-
|
|
3134
|
+
embeddingLogger.debug("Initializing embedding manager", {
|
|
2953
3135
|
provider: config.provider,
|
|
2954
3136
|
model: config.model
|
|
2955
3137
|
});
|
|
2956
3138
|
this.config = config;
|
|
2957
|
-
this.provider =
|
|
2958
|
-
|
|
3139
|
+
this.provider = createEmbeddingProvider(config.provider, config.apiKey);
|
|
3140
|
+
embeddingLogger.info("Embedding manager initialized", {
|
|
2959
3141
|
provider: config.provider,
|
|
2960
|
-
model: config.model ||
|
|
3142
|
+
model: config.model || getDefaultEmbeddingModel(config.provider)
|
|
2961
3143
|
});
|
|
2962
3144
|
}
|
|
2963
3145
|
/**
|
|
2964
3146
|
* Initialize from environment variables
|
|
2965
3147
|
*/
|
|
2966
3148
|
initializeFromEnv() {
|
|
2967
|
-
const
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
model
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
const key = getOpenAIApiKey();
|
|
2978
|
-
if (!key) {
|
|
2979
|
-
logger4.error("OPENAI_API_KEY environment variable not set", {
|
|
2980
|
-
provider: "openai",
|
|
2981
|
-
required: true
|
|
2982
|
-
});
|
|
2983
|
-
throw new Error("OPENAI_API_KEY environment variable is required for OpenAI embeddings");
|
|
2984
|
-
}
|
|
2985
|
-
apiKey = key;
|
|
2986
|
-
logger4.debug("OpenAI API key found");
|
|
2987
|
-
break;
|
|
2988
|
-
}
|
|
2989
|
-
case "cohere": {
|
|
2990
|
-
const key = getCohereApiKey();
|
|
2991
|
-
if (!key) {
|
|
2992
|
-
logger4.error("COHERE_API_KEY environment variable not set", {
|
|
2993
|
-
provider: "cohere",
|
|
2994
|
-
required: true
|
|
2995
|
-
});
|
|
2996
|
-
throw new Error("COHERE_API_KEY environment variable is required for Cohere embeddings");
|
|
2997
|
-
}
|
|
2998
|
-
apiKey = key;
|
|
2999
|
-
logger4.debug("Cohere API key found");
|
|
3000
|
-
break;
|
|
3001
|
-
}
|
|
3002
|
-
case "huggingface": {
|
|
3003
|
-
const key = getHuggingFaceApiKey();
|
|
3004
|
-
if (!key) {
|
|
3005
|
-
logger4.error("HUGGINGFACE_API_KEY environment variable not set", {
|
|
3006
|
-
provider: "huggingface",
|
|
3007
|
-
required: true
|
|
3008
|
-
});
|
|
3009
|
-
throw new Error("HUGGINGFACE_API_KEY environment variable is required for HuggingFace embeddings");
|
|
3010
|
-
}
|
|
3011
|
-
apiKey = key;
|
|
3012
|
-
logger4.debug("HuggingFace API key found");
|
|
3013
|
-
break;
|
|
3014
|
-
}
|
|
3015
|
-
case "voyage": {
|
|
3016
|
-
const key = getVoyageApiKey();
|
|
3017
|
-
if (!key) {
|
|
3018
|
-
logger4.error("VOYAGE_API_KEY environment variable not set", {
|
|
3019
|
-
provider: "voyage",
|
|
3020
|
-
required: true
|
|
3021
|
-
});
|
|
3022
|
-
throw new Error("VOYAGE_API_KEY environment variable is required for Voyage AI embeddings");
|
|
3023
|
-
}
|
|
3024
|
-
apiKey = key;
|
|
3025
|
-
logger4.debug("Voyage API key found");
|
|
3026
|
-
break;
|
|
3027
|
-
}
|
|
3028
|
-
case "ollama":
|
|
3029
|
-
baseUrl = getOllamaBaseUrl();
|
|
3030
|
-
logger4.debug("Using Ollama (local, no API key required)", {
|
|
3031
|
-
baseUrl: baseUrl || "http://localhost:11434"
|
|
3032
|
-
});
|
|
3033
|
-
break;
|
|
3034
|
-
default:
|
|
3035
|
-
logger4.error("Unknown embedding provider", {
|
|
3036
|
-
provider: providerName
|
|
3037
|
-
});
|
|
3038
|
-
throw new Error(`Unknown embedding provider: ${providerName}`);
|
|
3039
|
-
}
|
|
3040
|
-
this.provider = this.createProvider(providerName, apiKey, model, baseUrl);
|
|
3041
|
-
this.config = {
|
|
3042
|
-
provider: providerName,
|
|
3043
|
-
model: model || this.getDefaultModel(providerName),
|
|
3044
|
-
apiKey: ""
|
|
3045
|
-
// Not stored when using env
|
|
3046
|
-
};
|
|
3047
|
-
logger4.info("Embedding manager initialized from environment", {
|
|
3048
|
-
provider: providerName,
|
|
3149
|
+
const resolved = resolveEmbeddingEnvironment();
|
|
3150
|
+
this.provider = createEmbeddingProvider(
|
|
3151
|
+
resolved.providerName,
|
|
3152
|
+
resolved.apiKey,
|
|
3153
|
+
resolved.config.model,
|
|
3154
|
+
resolved.baseUrl
|
|
3155
|
+
);
|
|
3156
|
+
this.config = resolved.config;
|
|
3157
|
+
embeddingLogger.info("Embedding manager initialized from environment", {
|
|
3158
|
+
provider: resolved.providerName,
|
|
3049
3159
|
model: this.config.model
|
|
3050
3160
|
});
|
|
3051
3161
|
}
|
|
@@ -3059,102 +3169,39 @@ var EmbeddingManager = class {
|
|
|
3059
3169
|
* Get current provider
|
|
3060
3170
|
*/
|
|
3061
3171
|
getProvider() {
|
|
3062
|
-
|
|
3063
|
-
throw new Error("Embedding manager not initialized. Call initialize() or initializeFromEnv() first.");
|
|
3064
|
-
}
|
|
3065
|
-
return this.provider;
|
|
3172
|
+
return requireEmbeddingProvider(this.provider);
|
|
3066
3173
|
}
|
|
3067
3174
|
/**
|
|
3068
3175
|
* Get current configuration
|
|
3069
3176
|
*/
|
|
3070
3177
|
getConfig() {
|
|
3071
|
-
|
|
3072
|
-
throw new Error("Embedding manager not initialized. Call initialize() or initializeFromEnv() first.");
|
|
3073
|
-
}
|
|
3074
|
-
return this.config;
|
|
3178
|
+
return requireEmbeddingConfig(this.config);
|
|
3075
3179
|
}
|
|
3076
3180
|
/**
|
|
3077
3181
|
* Generate embedding for a single text
|
|
3078
3182
|
*/
|
|
3079
3183
|
async generateEmbedding(text, model) {
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
model
|
|
3087
|
-
|
|
3088
|
-
});
|
|
3089
|
-
const result = await provider.generateEmbedding(text, modelToUse);
|
|
3090
|
-
logger4.info("Embedding generated", {
|
|
3091
|
-
provider: provider.name,
|
|
3092
|
-
model: result.model,
|
|
3093
|
-
dimensions: result.dimensions,
|
|
3094
|
-
duration: Date.now() - startTime
|
|
3095
|
-
});
|
|
3096
|
-
return result;
|
|
3184
|
+
return generateManagedEmbedding(
|
|
3185
|
+
{
|
|
3186
|
+
provider: this.getProvider(),
|
|
3187
|
+
config: this.getConfig()
|
|
3188
|
+
},
|
|
3189
|
+
text,
|
|
3190
|
+
model
|
|
3191
|
+
);
|
|
3097
3192
|
}
|
|
3098
3193
|
/**
|
|
3099
3194
|
* Generate embeddings for multiple texts (batch)
|
|
3100
3195
|
*/
|
|
3101
3196
|
async generateBatchEmbeddings(texts, model) {
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
model
|
|
3109
|
-
|
|
3110
|
-
});
|
|
3111
|
-
const result = await provider.generateBatchEmbeddings(texts, modelToUse);
|
|
3112
|
-
logger4.info("Batch embeddings generated", {
|
|
3113
|
-
provider: provider.name,
|
|
3114
|
-
model: result.model,
|
|
3115
|
-
dimensions: result.dimensions,
|
|
3116
|
-
count: texts.length,
|
|
3117
|
-
duration: Date.now() - startTime
|
|
3118
|
-
});
|
|
3119
|
-
return result;
|
|
3120
|
-
}
|
|
3121
|
-
/**
|
|
3122
|
-
* Get default model for a provider
|
|
3123
|
-
*/
|
|
3124
|
-
getDefaultModel(provider) {
|
|
3125
|
-
switch (provider) {
|
|
3126
|
-
case "openai":
|
|
3127
|
-
return "text-embedding-3-small";
|
|
3128
|
-
case "cohere":
|
|
3129
|
-
return "embed-english-v3.0";
|
|
3130
|
-
case "huggingface":
|
|
3131
|
-
return "sentence-transformers/all-MiniLM-L6-v2";
|
|
3132
|
-
case "voyage":
|
|
3133
|
-
return "voyage-2";
|
|
3134
|
-
case "ollama":
|
|
3135
|
-
return "nomic-embed-text";
|
|
3136
|
-
default:
|
|
3137
|
-
return "text-embedding-3-small";
|
|
3138
|
-
}
|
|
3139
|
-
}
|
|
3140
|
-
/**
|
|
3141
|
-
* Create a provider instance
|
|
3142
|
-
*/
|
|
3143
|
-
createProvider(providerName, apiKey, model, baseUrl) {
|
|
3144
|
-
switch (providerName) {
|
|
3145
|
-
case "openai":
|
|
3146
|
-
return new OpenAIEmbeddingProvider(apiKey);
|
|
3147
|
-
case "cohere":
|
|
3148
|
-
return new CohereEmbeddingProvider(apiKey);
|
|
3149
|
-
case "huggingface":
|
|
3150
|
-
return new HuggingFaceEmbeddingProvider(apiKey);
|
|
3151
|
-
case "voyage":
|
|
3152
|
-
return new VoyageEmbeddingProvider(apiKey);
|
|
3153
|
-
case "ollama":
|
|
3154
|
-
return new OllamaEmbeddingProvider(model, baseUrl || "http://localhost:11434");
|
|
3155
|
-
default:
|
|
3156
|
-
throw new Error(`Unknown embedding provider: ${providerName}`);
|
|
3157
|
-
}
|
|
3197
|
+
return generateManagedBatchEmbeddings(
|
|
3198
|
+
{
|
|
3199
|
+
provider: this.getProvider(),
|
|
3200
|
+
config: this.getConfig()
|
|
3201
|
+
},
|
|
3202
|
+
texts,
|
|
3203
|
+
model
|
|
3204
|
+
);
|
|
3158
3205
|
}
|
|
3159
3206
|
/**
|
|
3160
3207
|
* Reset the manager (for testing)
|
|
@@ -3266,20 +3313,20 @@ function formatResults(records) {
|
|
|
3266
3313
|
}
|
|
3267
3314
|
|
|
3268
3315
|
// src/data/neo4j/tools/neo4j-query.ts
|
|
3269
|
-
var
|
|
3316
|
+
var logger4 = core.createLogger("agentforge:tools:neo4j:query");
|
|
3270
3317
|
function createNeo4jQueryTool() {
|
|
3271
3318
|
return core.toolBuilder().name("neo4j-query").description(
|
|
3272
3319
|
"Execute a Cypher query against the Neo4j graph database. Supports parameterized queries for safety. Use this for complex queries, graph traversals, and custom operations."
|
|
3273
3320
|
).category(core.ToolCategory.DATABASE).tags(["neo4j", "graph", "database", "cypher", "query"]).schema(neo4jQuerySchema).implement(async (input) => {
|
|
3274
3321
|
if (!neo4jPool.isInitialized()) {
|
|
3275
|
-
|
|
3322
|
+
logger4.warn("Neo4j query attempted but connection not initialized");
|
|
3276
3323
|
return {
|
|
3277
3324
|
success: false,
|
|
3278
3325
|
error: "Neo4j connection not initialized. Please configure Neo4j connection first."
|
|
3279
3326
|
};
|
|
3280
3327
|
}
|
|
3281
3328
|
const startTime = Date.now();
|
|
3282
|
-
|
|
3329
|
+
logger4.debug("Executing Neo4j query", {
|
|
3283
3330
|
cypherPreview: input.cypher.substring(0, 100),
|
|
3284
3331
|
parameterCount: Object.keys(input.parameters || {}).length,
|
|
3285
3332
|
...input.database ? { database: input.database } : {}
|
|
@@ -3290,7 +3337,7 @@ function createNeo4jQueryTool() {
|
|
|
3290
3337
|
const result = await session.run(input.cypher, input.parameters || {});
|
|
3291
3338
|
const formattedResults = formatResults(result.records);
|
|
3292
3339
|
const duration = Date.now() - startTime;
|
|
3293
|
-
|
|
3340
|
+
logger4.info("Neo4j query executed successfully", {
|
|
3294
3341
|
recordCount: result.records.length,
|
|
3295
3342
|
nodesCreated: result.summary.counters.updates().nodesCreated,
|
|
3296
3343
|
nodesDeleted: result.summary.counters.updates().nodesDeleted,
|
|
@@ -3321,7 +3368,7 @@ function createNeo4jQueryTool() {
|
|
|
3321
3368
|
} catch (error) {
|
|
3322
3369
|
const duration = Date.now() - startTime;
|
|
3323
3370
|
const errorMessage = error instanceof Error ? error.message : "Failed to execute query";
|
|
3324
|
-
|
|
3371
|
+
logger4.error("Neo4j query execution failed", {
|
|
3325
3372
|
error: errorMessage,
|
|
3326
3373
|
cypherPreview: input.cypher.substring(0, 100),
|
|
3327
3374
|
duration
|
|
@@ -3631,27 +3678,27 @@ function createNeo4jVectorSearchTool() {
|
|
|
3631
3678
|
}
|
|
3632
3679
|
}).build();
|
|
3633
3680
|
}
|
|
3634
|
-
var
|
|
3681
|
+
var logger5 = core.createLogger("agentforge:tools:neo4j:vector-search");
|
|
3635
3682
|
function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
3636
3683
|
return core.toolBuilder().name("neo4j-vector-search-with-embedding").description(
|
|
3637
3684
|
"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."
|
|
3638
3685
|
).category(core.ToolCategory.DATABASE).tags(["neo4j", "graph", "database", "vector", "search", "semantic", "graphrag", "embedding", "ai"]).schema(neo4jVectorSearchWithEmbeddingSchema).implement(async (input) => {
|
|
3639
3686
|
if (!neo4jPool.isInitialized()) {
|
|
3640
|
-
|
|
3687
|
+
logger5.warn("Vector search attempted but Neo4j connection not initialized");
|
|
3641
3688
|
return {
|
|
3642
3689
|
success: false,
|
|
3643
3690
|
error: "Neo4j connection not initialized. Please configure Neo4j connection first."
|
|
3644
3691
|
};
|
|
3645
3692
|
}
|
|
3646
3693
|
if (!embeddingManager.isInitialized()) {
|
|
3647
|
-
|
|
3694
|
+
logger5.warn("Vector search attempted but embedding manager not initialized");
|
|
3648
3695
|
return {
|
|
3649
3696
|
success: false,
|
|
3650
3697
|
error: "Embedding manager not initialized. Please configure embedding provider (set OPENAI_API_KEY and optionally EMBEDDING_MODEL)."
|
|
3651
3698
|
};
|
|
3652
3699
|
}
|
|
3653
3700
|
const startTime = Date.now();
|
|
3654
|
-
|
|
3701
|
+
logger5.debug("Performing vector search with embedding", {
|
|
3655
3702
|
queryTextLength: input.queryText.length,
|
|
3656
3703
|
indexName: input.indexName,
|
|
3657
3704
|
...input.limit !== void 0 ? { limit: input.limit } : {},
|
|
@@ -3675,7 +3722,7 @@ function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
|
3675
3722
|
const result = await session.run(cypher, parameters);
|
|
3676
3723
|
const formattedResults = formatResults(result.records);
|
|
3677
3724
|
const duration = Date.now() - startTime;
|
|
3678
|
-
|
|
3725
|
+
logger5.info("Vector search completed successfully", {
|
|
3679
3726
|
resultCount: result.records.length,
|
|
3680
3727
|
indexName: input.indexName,
|
|
3681
3728
|
embeddingModel: embeddingResult.model,
|
|
@@ -3716,7 +3763,7 @@ function createNeo4jVectorSearchWithEmbeddingTool() {
|
|
|
3716
3763
|
} else if (errorMessage.includes("dimension")) {
|
|
3717
3764
|
helpText = " Make sure the vector index dimensions match your embedding model dimensions.";
|
|
3718
3765
|
}
|
|
3719
|
-
|
|
3766
|
+
logger5.error("Vector search failed", {
|
|
3720
3767
|
error: errorMessage,
|
|
3721
3768
|
indexName: input.indexName,
|
|
3722
3769
|
queryTextLength: input.queryText.length,
|
|
@@ -4148,19 +4195,19 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
|
4148
4195
|
ConnectionState2["ERROR"] = "error";
|
|
4149
4196
|
return ConnectionState2;
|
|
4150
4197
|
})(ConnectionState || {});
|
|
4151
|
-
function cancelPendingReconnection(timer,
|
|
4198
|
+
function cancelPendingReconnection(timer, logger22, vendor, message) {
|
|
4152
4199
|
if (!timer) {
|
|
4153
4200
|
return null;
|
|
4154
4201
|
}
|
|
4155
|
-
|
|
4202
|
+
logger22.debug(message, { vendor });
|
|
4156
4203
|
clearTimeout(timer);
|
|
4157
4204
|
return null;
|
|
4158
4205
|
}
|
|
4159
|
-
async function waitForInFlightConnection(promise,
|
|
4206
|
+
async function waitForInFlightConnection(promise, logger22, vendor, phase) {
|
|
4160
4207
|
if (!promise) {
|
|
4161
4208
|
return null;
|
|
4162
4209
|
}
|
|
4163
|
-
|
|
4210
|
+
logger22.debug(`Waiting for in-flight connection attempt to complete before ${phase}`, {
|
|
4164
4211
|
vendor
|
|
4165
4212
|
});
|
|
4166
4213
|
try {
|
|
@@ -4177,9 +4224,9 @@ function shutdownClient(vendor, client) {
|
|
|
4177
4224
|
client.close();
|
|
4178
4225
|
}
|
|
4179
4226
|
}
|
|
4180
|
-
function scheduleReconnection(context,
|
|
4227
|
+
function scheduleReconnection(context, logger22) {
|
|
4181
4228
|
if (context.reconnectionConfig.maxAttempts > 0 && context.reconnectionAttempts >= context.reconnectionConfig.maxAttempts) {
|
|
4182
|
-
|
|
4229
|
+
logger22.error("Max reconnection attempts reached", {
|
|
4183
4230
|
vendor: context.vendor,
|
|
4184
4231
|
attempts: context.reconnectionAttempts,
|
|
4185
4232
|
maxAttempts: context.reconnectionConfig.maxAttempts
|
|
@@ -4193,7 +4240,7 @@ function scheduleReconnection(context, logger23) {
|
|
|
4193
4240
|
const nextAttempt = context.reconnectionAttempts + 1;
|
|
4194
4241
|
context.setReconnectionAttempts(nextAttempt);
|
|
4195
4242
|
context.setState("reconnecting" /* RECONNECTING */);
|
|
4196
|
-
|
|
4243
|
+
logger22.info("Scheduling reconnection attempt", {
|
|
4197
4244
|
vendor: context.vendor,
|
|
4198
4245
|
attempt: nextAttempt,
|
|
4199
4246
|
maxAttempts: context.reconnectionConfig.maxAttempts,
|
|
@@ -4207,7 +4254,7 @@ function scheduleReconnection(context, logger23) {
|
|
|
4207
4254
|
const timer = setTimeout(async () => {
|
|
4208
4255
|
context.setReconnectionTimer(null);
|
|
4209
4256
|
try {
|
|
4210
|
-
|
|
4257
|
+
logger22.info("Attempting reconnection", {
|
|
4211
4258
|
vendor: context.vendor,
|
|
4212
4259
|
attempt: nextAttempt
|
|
4213
4260
|
});
|
|
@@ -4217,7 +4264,7 @@ function scheduleReconnection(context, logger23) {
|
|
|
4217
4264
|
context.setConnectPromise(promise);
|
|
4218
4265
|
await promise;
|
|
4219
4266
|
} catch (error) {
|
|
4220
|
-
|
|
4267
|
+
logger22.error("Reconnection attempt failed", {
|
|
4221
4268
|
vendor: context.vendor,
|
|
4222
4269
|
attempt: nextAttempt,
|
|
4223
4270
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -4228,17 +4275,17 @@ function scheduleReconnection(context, logger23) {
|
|
|
4228
4275
|
}
|
|
4229
4276
|
|
|
4230
4277
|
// src/data/relational/connection/connection-cleanup.ts
|
|
4231
|
-
async function cleanupConnectionResources(vendor, client, clearConnection,
|
|
4278
|
+
async function cleanupConnectionResources(vendor, client, clearConnection, logger22) {
|
|
4232
4279
|
if (!client) {
|
|
4233
4280
|
return;
|
|
4234
4281
|
}
|
|
4235
|
-
|
|
4282
|
+
logger22.debug("Cleaning up cancelled connection", {
|
|
4236
4283
|
vendor
|
|
4237
4284
|
});
|
|
4238
4285
|
try {
|
|
4239
4286
|
await shutdownClient(vendor, client);
|
|
4240
4287
|
} catch (error) {
|
|
4241
|
-
|
|
4288
|
+
logger22.debug("Error during cancelled connection cleanup", {
|
|
4242
4289
|
vendor,
|
|
4243
4290
|
error: error instanceof Error ? error.message : String(error)
|
|
4244
4291
|
});
|
|
@@ -4246,10 +4293,10 @@ async function cleanupConnectionResources(vendor, client, clearConnection, logge
|
|
|
4246
4293
|
clearConnection();
|
|
4247
4294
|
}
|
|
4248
4295
|
}
|
|
4249
|
-
async function closeManagedConnection(runtime,
|
|
4296
|
+
async function closeManagedConnection(runtime, logger22) {
|
|
4250
4297
|
const client = runtime.getClient();
|
|
4251
4298
|
if (client) {
|
|
4252
|
-
|
|
4299
|
+
logger22.info("Closing database connection", {
|
|
4253
4300
|
vendor: runtime.vendor,
|
|
4254
4301
|
state: runtime.getState()
|
|
4255
4302
|
});
|
|
@@ -4257,12 +4304,12 @@ async function closeManagedConnection(runtime, logger23) {
|
|
|
4257
4304
|
await shutdownClient(runtime.vendor, client);
|
|
4258
4305
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4259
4306
|
runtime.emitDisconnected();
|
|
4260
|
-
|
|
4307
|
+
logger22.debug("Database connection closed successfully", {
|
|
4261
4308
|
vendor: runtime.vendor,
|
|
4262
4309
|
state: runtime.getState()
|
|
4263
4310
|
});
|
|
4264
4311
|
} catch (error) {
|
|
4265
|
-
|
|
4312
|
+
logger22.error("Error closing database connection", {
|
|
4266
4313
|
vendor: runtime.vendor,
|
|
4267
4314
|
error: error instanceof Error ? error.message : String(error),
|
|
4268
4315
|
state: runtime.getState()
|
|
@@ -4279,7 +4326,7 @@ async function closeManagedConnection(runtime, logger23) {
|
|
|
4279
4326
|
runtime.emitDisconnected();
|
|
4280
4327
|
}
|
|
4281
4328
|
}
|
|
4282
|
-
var
|
|
4329
|
+
var logger6 = core.createLogger("agentforge:tools:data:relational:connection:vendor-init");
|
|
4283
4330
|
var SAFE_INITIALIZATION_PATTERNS = [
|
|
4284
4331
|
"Pool max connections must be",
|
|
4285
4332
|
"Pool acquire timeout must be",
|
|
@@ -4325,7 +4372,7 @@ function normalizePostgreSQLConfig(connection) {
|
|
|
4325
4372
|
}
|
|
4326
4373
|
function normalizeMySQLConfig(connection) {
|
|
4327
4374
|
if (typeof connection === "string") {
|
|
4328
|
-
|
|
4375
|
+
logger6.debug("Creating MySQL connection pool from connection string", {
|
|
4329
4376
|
vendor: "mysql"
|
|
4330
4377
|
});
|
|
4331
4378
|
return connection;
|
|
@@ -4374,7 +4421,7 @@ async function initializePostgreSQLConnection(connection) {
|
|
|
4374
4421
|
const { drizzle } = await import('drizzle-orm/node-postgres');
|
|
4375
4422
|
const { Pool } = await import('pg');
|
|
4376
4423
|
const { connectionConfig } = normalizePostgreSQLConfig(connection);
|
|
4377
|
-
|
|
4424
|
+
logger6.debug("Creating PostgreSQL connection pool", {
|
|
4378
4425
|
vendor: "postgresql",
|
|
4379
4426
|
poolConfig: pickConfiguredPoolFields({
|
|
4380
4427
|
max: connectionConfig.max,
|
|
@@ -4391,7 +4438,7 @@ async function initializeMySQLConnection(connection) {
|
|
|
4391
4438
|
const mysql = await import('mysql2/promise');
|
|
4392
4439
|
const connectionConfig = normalizeMySQLConfig(connection);
|
|
4393
4440
|
if (typeof connectionConfig !== "string") {
|
|
4394
|
-
|
|
4441
|
+
logger6.debug("Creating MySQL connection pool", {
|
|
4395
4442
|
vendor: "mysql",
|
|
4396
4443
|
poolConfig: pickConfiguredPoolFields({
|
|
4397
4444
|
connectionLimit: connectionConfig.connectionLimit,
|
|
@@ -4415,7 +4462,7 @@ async function initializeSQLiteConnection(connection) {
|
|
|
4415
4462
|
const Database = DatabaseModule.default;
|
|
4416
4463
|
const { url, poolConfig } = resolveSqliteUrl(connection);
|
|
4417
4464
|
if (poolConfig) {
|
|
4418
|
-
|
|
4465
|
+
logger6.debug("SQLite pool configuration provided but not applied (SQLite uses single connection)", {
|
|
4419
4466
|
vendor: "sqlite",
|
|
4420
4467
|
poolConfig: pickConfiguredPoolFields({
|
|
4421
4468
|
max: poolConfig.max,
|
|
@@ -4424,7 +4471,7 @@ async function initializeSQLiteConnection(connection) {
|
|
|
4424
4471
|
})
|
|
4425
4472
|
});
|
|
4426
4473
|
}
|
|
4427
|
-
|
|
4474
|
+
logger6.debug("Creating SQLite connection", {
|
|
4428
4475
|
vendor: "sqlite",
|
|
4429
4476
|
url: url === ":memory:" ? ":memory:" : "file"
|
|
4430
4477
|
});
|
|
@@ -4435,11 +4482,11 @@ async function initializeSQLiteConnection(connection) {
|
|
|
4435
4482
|
}
|
|
4436
4483
|
|
|
4437
4484
|
// src/data/relational/connection/connection-initialization.ts
|
|
4438
|
-
async function initializeManagedConnection(runtime,
|
|
4485
|
+
async function initializeManagedConnection(runtime, logger22) {
|
|
4439
4486
|
const startTime = Date.now();
|
|
4440
4487
|
const currentGeneration = runtime.getConnectionGeneration();
|
|
4441
4488
|
if (runtime.getState() === "connected" /* CONNECTED */ && runtime.getClient()) {
|
|
4442
|
-
|
|
4489
|
+
logger22.warn("Re-initializing an already connected manager; emitting disconnected before cleanup", {
|
|
4443
4490
|
vendor: runtime.vendor
|
|
4444
4491
|
});
|
|
4445
4492
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
@@ -4451,11 +4498,11 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4451
4498
|
runtime.setClient(null);
|
|
4452
4499
|
runtime.setDb(null);
|
|
4453
4500
|
},
|
|
4454
|
-
|
|
4501
|
+
logger22
|
|
4455
4502
|
);
|
|
4456
4503
|
}
|
|
4457
4504
|
runtime.setState("connecting" /* CONNECTING */);
|
|
4458
|
-
|
|
4505
|
+
logger22.info("Initializing database connection", {
|
|
4459
4506
|
vendor: runtime.vendor,
|
|
4460
4507
|
connectionType: typeof runtime.config.connection,
|
|
4461
4508
|
state: runtime.getState()
|
|
@@ -4465,7 +4512,7 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4465
4512
|
runtime.setClient(initialized.client);
|
|
4466
4513
|
runtime.setDb(initialized.db);
|
|
4467
4514
|
if (currentGeneration !== runtime.getConnectionGeneration()) {
|
|
4468
|
-
|
|
4515
|
+
logger22.debug("Connection cancelled during initialization", {
|
|
4469
4516
|
vendor: runtime.vendor,
|
|
4470
4517
|
currentGeneration,
|
|
4471
4518
|
newGeneration: runtime.getConnectionGeneration()
|
|
@@ -4477,18 +4524,18 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4477
4524
|
runtime.setClient(null);
|
|
4478
4525
|
runtime.setDb(null);
|
|
4479
4526
|
},
|
|
4480
|
-
|
|
4527
|
+
logger22
|
|
4481
4528
|
);
|
|
4482
4529
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4483
4530
|
throw new Error("Connection cancelled during initialization");
|
|
4484
4531
|
}
|
|
4485
|
-
|
|
4532
|
+
logger22.debug("Validating connection health", { vendor: runtime.vendor });
|
|
4486
4533
|
const healthy = await runtime.isHealthy();
|
|
4487
4534
|
if (!healthy) {
|
|
4488
4535
|
throw new Error(`Failed to establish healthy connection to ${runtime.vendor} database`);
|
|
4489
4536
|
}
|
|
4490
4537
|
if (currentGeneration !== runtime.getConnectionGeneration()) {
|
|
4491
|
-
|
|
4538
|
+
logger22.debug("Connection cancelled during health check", {
|
|
4492
4539
|
vendor: runtime.vendor,
|
|
4493
4540
|
currentGeneration,
|
|
4494
4541
|
newGeneration: runtime.getConnectionGeneration()
|
|
@@ -4500,7 +4547,7 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4500
4547
|
runtime.setClient(null);
|
|
4501
4548
|
runtime.setDb(null);
|
|
4502
4549
|
},
|
|
4503
|
-
|
|
4550
|
+
logger22
|
|
4504
4551
|
);
|
|
4505
4552
|
runtime.setState("disconnected" /* DISCONNECTED */);
|
|
4506
4553
|
throw new Error("Connection cancelled during health check");
|
|
@@ -4508,7 +4555,7 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4508
4555
|
runtime.setState("connected" /* CONNECTED */);
|
|
4509
4556
|
runtime.emitConnected();
|
|
4510
4557
|
runtime.resetReconnectionAttempts();
|
|
4511
|
-
|
|
4558
|
+
logger22.info("Database connection initialized successfully", {
|
|
4512
4559
|
vendor: runtime.vendor,
|
|
4513
4560
|
duration: Date.now() - startTime,
|
|
4514
4561
|
state: runtime.getState()
|
|
@@ -4529,7 +4576,7 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4529
4576
|
if (runtime.errorListenerCount() > 0) {
|
|
4530
4577
|
runtime.emitError(normalizedError);
|
|
4531
4578
|
}
|
|
4532
|
-
|
|
4579
|
+
logger22.error(errorMessage, {
|
|
4533
4580
|
vendor: runtime.vendor,
|
|
4534
4581
|
error: normalizedError.message,
|
|
4535
4582
|
duration: Date.now() - startTime,
|
|
@@ -4542,13 +4589,13 @@ async function initializeManagedConnection(runtime, logger23) {
|
|
|
4542
4589
|
runtime.setClient(null);
|
|
4543
4590
|
runtime.setDb(null);
|
|
4544
4591
|
},
|
|
4545
|
-
|
|
4592
|
+
logger22
|
|
4546
4593
|
);
|
|
4547
4594
|
if (runtime.getReconnectionConfig().enabled && currentGeneration === runtime.getConnectionGeneration()) {
|
|
4548
4595
|
runtime.scheduleReconnection();
|
|
4549
4596
|
}
|
|
4550
4597
|
} else {
|
|
4551
|
-
|
|
4598
|
+
logger22.debug("Connection initialization cancelled", {
|
|
4552
4599
|
vendor: runtime.vendor,
|
|
4553
4600
|
duration: Date.now() - startTime,
|
|
4554
4601
|
state: runtime.getState()
|
|
@@ -4566,17 +4613,17 @@ function isSqliteNonQueryError(error) {
|
|
|
4566
4613
|
const hasNonQueryMessage = error.message.includes("does not return data");
|
|
4567
4614
|
return isSqliteOrTypeError && hasNonQueryMessage;
|
|
4568
4615
|
}
|
|
4569
|
-
async function checkConnectionHealth(args,
|
|
4616
|
+
async function checkConnectionHealth(args, logger22) {
|
|
4570
4617
|
if (!args.db || !args.client) {
|
|
4571
|
-
|
|
4618
|
+
logger22.debug("Health check failed: connection not initialized", { vendor: args.vendor });
|
|
4572
4619
|
return false;
|
|
4573
4620
|
}
|
|
4574
4621
|
try {
|
|
4575
4622
|
await args.execute(drizzleOrm.sql`SELECT 1`);
|
|
4576
|
-
|
|
4623
|
+
logger22.debug("Health check passed", { vendor: args.vendor });
|
|
4577
4624
|
return true;
|
|
4578
4625
|
} catch (error) {
|
|
4579
|
-
|
|
4626
|
+
logger22.debug("Health check failed", {
|
|
4580
4627
|
vendor: args.vendor,
|
|
4581
4628
|
error: error instanceof Error ? error.message : String(error)
|
|
4582
4629
|
});
|
|
@@ -4619,8 +4666,8 @@ function getConnectionPoolMetrics(vendor, client) {
|
|
|
4619
4666
|
}
|
|
4620
4667
|
|
|
4621
4668
|
// src/data/relational/connection/query-execution.ts
|
|
4622
|
-
async function executeQuery(context, query,
|
|
4623
|
-
|
|
4669
|
+
async function executeQuery(context, query, logger22) {
|
|
4670
|
+
logger22.debug("Executing SQL query", {
|
|
4624
4671
|
vendor: context.vendor
|
|
4625
4672
|
});
|
|
4626
4673
|
if (context.vendor === "sqlite") {
|
|
@@ -4690,7 +4737,7 @@ async function executeInDedicatedConnection(context, callback) {
|
|
|
4690
4737
|
}
|
|
4691
4738
|
throw new Error(`Unsupported database vendor: ${context.vendor}`);
|
|
4692
4739
|
}
|
|
4693
|
-
var
|
|
4740
|
+
var logger7 = core.createLogger("agentforge:tools:data:relational:connection");
|
|
4694
4741
|
var ConnectionManager = class extends events.EventEmitter {
|
|
4695
4742
|
vendor;
|
|
4696
4743
|
db;
|
|
@@ -4720,11 +4767,11 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4720
4767
|
}
|
|
4721
4768
|
async connect() {
|
|
4722
4769
|
if (this.state === "connected" /* CONNECTED */) {
|
|
4723
|
-
|
|
4770
|
+
logger7.debug("Already connected", { vendor: this.vendor });
|
|
4724
4771
|
return;
|
|
4725
4772
|
}
|
|
4726
4773
|
if (this.connectPromise) {
|
|
4727
|
-
|
|
4774
|
+
logger7.debug("Connection already in progress, waiting for completion", {
|
|
4728
4775
|
vendor: this.vendor,
|
|
4729
4776
|
state: this.state
|
|
4730
4777
|
});
|
|
@@ -4732,7 +4779,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4732
4779
|
}
|
|
4733
4780
|
this.reconnectionTimer = cancelPendingReconnection(
|
|
4734
4781
|
this.reconnectionTimer,
|
|
4735
|
-
|
|
4782
|
+
logger7,
|
|
4736
4783
|
this.vendor,
|
|
4737
4784
|
"Clearing pending reconnection timer before manual connect"
|
|
4738
4785
|
);
|
|
@@ -4745,14 +4792,14 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4745
4792
|
this.connectionGeneration++;
|
|
4746
4793
|
this.reconnectionTimer = cancelPendingReconnection(
|
|
4747
4794
|
this.reconnectionTimer,
|
|
4748
|
-
|
|
4795
|
+
logger7,
|
|
4749
4796
|
this.vendor,
|
|
4750
4797
|
"Clearing pending reconnection timer before disconnect"
|
|
4751
4798
|
);
|
|
4752
4799
|
this.reconnectionAttempts = 0;
|
|
4753
4800
|
this.connectPromise = await waitForInFlightConnection(
|
|
4754
4801
|
this.connectPromise,
|
|
4755
|
-
|
|
4802
|
+
logger7,
|
|
4756
4803
|
this.vendor,
|
|
4757
4804
|
"disconnect"
|
|
4758
4805
|
);
|
|
@@ -4772,13 +4819,13 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4772
4819
|
return this.vendor;
|
|
4773
4820
|
}
|
|
4774
4821
|
async initialize() {
|
|
4775
|
-
return initializeManagedConnection(this.createRuntimeAdapter(),
|
|
4822
|
+
return initializeManagedConnection(this.createRuntimeAdapter(), logger7);
|
|
4776
4823
|
}
|
|
4777
4824
|
setState(newState) {
|
|
4778
4825
|
const oldState = this.state;
|
|
4779
4826
|
this.state = newState;
|
|
4780
4827
|
if (oldState !== newState) {
|
|
4781
|
-
|
|
4828
|
+
logger7.debug("Connection state changed", {
|
|
4782
4829
|
vendor: this.vendor,
|
|
4783
4830
|
oldState,
|
|
4784
4831
|
newState
|
|
@@ -4808,7 +4855,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4808
4855
|
this.reconnectionTimer = timer;
|
|
4809
4856
|
}
|
|
4810
4857
|
},
|
|
4811
|
-
|
|
4858
|
+
logger7
|
|
4812
4859
|
);
|
|
4813
4860
|
}
|
|
4814
4861
|
createRuntimeAdapter() {
|
|
@@ -4855,7 +4902,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4855
4902
|
isSqliteNonQueryError
|
|
4856
4903
|
},
|
|
4857
4904
|
query,
|
|
4858
|
-
|
|
4905
|
+
logger7
|
|
4859
4906
|
);
|
|
4860
4907
|
}
|
|
4861
4908
|
async executeInConnection(callback) {
|
|
@@ -4879,13 +4926,13 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4879
4926
|
this.connectionGeneration++;
|
|
4880
4927
|
this.reconnectionTimer = cancelPendingReconnection(
|
|
4881
4928
|
this.reconnectionTimer,
|
|
4882
|
-
|
|
4929
|
+
logger7,
|
|
4883
4930
|
this.vendor,
|
|
4884
4931
|
"Canceling pending reconnection timer during close"
|
|
4885
4932
|
);
|
|
4886
4933
|
this.connectPromise = await waitForInFlightConnection(
|
|
4887
4934
|
this.connectPromise,
|
|
4888
|
-
|
|
4935
|
+
logger7,
|
|
4889
4936
|
this.vendor,
|
|
4890
4937
|
"close"
|
|
4891
4938
|
);
|
|
@@ -4908,7 +4955,7 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4908
4955
|
this.emit("error", error);
|
|
4909
4956
|
}
|
|
4910
4957
|
},
|
|
4911
|
-
|
|
4958
|
+
logger7
|
|
4912
4959
|
);
|
|
4913
4960
|
}
|
|
4914
4961
|
async isHealthy() {
|
|
@@ -4919,11 +4966,11 @@ var ConnectionManager = class extends events.EventEmitter {
|
|
|
4919
4966
|
client: this.client,
|
|
4920
4967
|
execute: (query) => this.execute(query)
|
|
4921
4968
|
},
|
|
4922
|
-
|
|
4969
|
+
logger7
|
|
4923
4970
|
);
|
|
4924
4971
|
}
|
|
4925
4972
|
};
|
|
4926
|
-
var
|
|
4973
|
+
var logger8 = core.createLogger("agentforge:tools:data:relational:query");
|
|
4927
4974
|
function buildParameterizedQuery(sqlString, params) {
|
|
4928
4975
|
if (!params) {
|
|
4929
4976
|
return drizzleOrm.sql.raw(sqlString);
|
|
@@ -4998,7 +5045,7 @@ function buildParameterizedQuery(sqlString, params) {
|
|
|
4998
5045
|
}
|
|
4999
5046
|
async function executeQuery2(manager, input, context) {
|
|
5000
5047
|
const startTime = Date.now();
|
|
5001
|
-
|
|
5048
|
+
logger8.debug("Executing query", {
|
|
5002
5049
|
vendor: input.vendor,
|
|
5003
5050
|
hasParams: !!input.params,
|
|
5004
5051
|
paramCount: input.params ? Array.isArray(input.params) ? input.params.length : Object.keys(input.params).length : 0
|
|
@@ -5012,7 +5059,7 @@ async function executeQuery2(manager, input, context) {
|
|
|
5012
5059
|
const executionTime = Date.now() - startTime;
|
|
5013
5060
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
5014
5061
|
const rowCount = result.rowCount || result.affectedRows || rows.length;
|
|
5015
|
-
|
|
5062
|
+
logger8.debug("Query executed successfully", {
|
|
5016
5063
|
vendor: input.vendor,
|
|
5017
5064
|
rowCount,
|
|
5018
5065
|
executionTime
|
|
@@ -5024,7 +5071,7 @@ async function executeQuery2(manager, input, context) {
|
|
|
5024
5071
|
};
|
|
5025
5072
|
} catch (error) {
|
|
5026
5073
|
const executionTime = Date.now() - startTime;
|
|
5027
|
-
|
|
5074
|
+
logger8.error("Query execution failed", {
|
|
5028
5075
|
vendor: input.vendor,
|
|
5029
5076
|
error: error instanceof Error ? error.message : String(error),
|
|
5030
5077
|
executionTime
|
|
@@ -5605,7 +5652,7 @@ async function executeBatchedTask(task, options = {}) {
|
|
|
5605
5652
|
failures
|
|
5606
5653
|
};
|
|
5607
5654
|
}
|
|
5608
|
-
var
|
|
5655
|
+
var logger9 = core.createLogger("agentforge:tools:data:relational:stream");
|
|
5609
5656
|
var DEFAULT_CHUNK_SIZE = 100;
|
|
5610
5657
|
var MAX_CHUNK_SIZE = 5e3;
|
|
5611
5658
|
var DEFAULT_SAMPLE_SIZE = 50;
|
|
@@ -5738,7 +5785,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5738
5785
|
const endHeapUsed = process.memoryUsage().heapUsed;
|
|
5739
5786
|
peakHeapUsed = Math.max(peakHeapUsed, endHeapUsed);
|
|
5740
5787
|
const executionTime = Date.now() - startTime;
|
|
5741
|
-
|
|
5788
|
+
logger9.debug("Streaming SELECT execution completed", {
|
|
5742
5789
|
table: input.table,
|
|
5743
5790
|
vendor: input.vendor,
|
|
5744
5791
|
chunkCount,
|
|
@@ -5762,7 +5809,7 @@ async function executeStreamingSelect(executor, input, options = {}) {
|
|
|
5762
5809
|
};
|
|
5763
5810
|
}
|
|
5764
5811
|
async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
5765
|
-
|
|
5812
|
+
logger9.warn("Running streaming benchmark will execute the SELECT query twice (regular + streaming).", {
|
|
5766
5813
|
table: input.table,
|
|
5767
5814
|
vendor: input.vendor
|
|
5768
5815
|
});
|
|
@@ -5782,7 +5829,7 @@ async function benchmarkStreamingSelectMemory(executor, input, options = {}) {
|
|
|
5782
5829
|
0
|
|
5783
5830
|
);
|
|
5784
5831
|
const memorySavedPercent = nonStreamingPeakHeapUsed > 0 ? memorySavedBytes / nonStreamingPeakHeapUsed * 100 : 0;
|
|
5785
|
-
|
|
5832
|
+
logger9.debug("Streaming benchmark completed", {
|
|
5786
5833
|
table: input.table,
|
|
5787
5834
|
vendor: input.vendor,
|
|
5788
5835
|
nonStreamingRows: nonStreamingRows.length,
|
|
@@ -5854,7 +5901,7 @@ function withTransactionTimeout(operation, timeoutMs, onTimeout) {
|
|
|
5854
5901
|
}
|
|
5855
5902
|
|
|
5856
5903
|
// src/data/relational/query/transaction-managed.ts
|
|
5857
|
-
var
|
|
5904
|
+
var logger10 = core.createLogger("agentforge:tools:data:relational:transaction");
|
|
5858
5905
|
var SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
5859
5906
|
var ManagedTransaction = class {
|
|
5860
5907
|
id;
|
|
@@ -5962,7 +6009,7 @@ var ManagedTransaction = class {
|
|
|
5962
6009
|
await this.executeQuery(drizzleOrm.sql.raw("PRAGMA read_uncommitted = 1"));
|
|
5963
6010
|
this.shouldRestoreSqliteReadUncommitted = true;
|
|
5964
6011
|
} else {
|
|
5965
|
-
|
|
6012
|
+
logger10.debug("Ignoring SQLite isolation level override", {
|
|
5966
6013
|
transactionId: this.id,
|
|
5967
6014
|
isolationLevel: this.options.isolationLevel
|
|
5968
6015
|
});
|
|
@@ -5987,7 +6034,7 @@ var ManagedTransaction = class {
|
|
|
5987
6034
|
const targetValue = this.sqliteReadUncommittedOriginal ?? 0;
|
|
5988
6035
|
await this.executeQuery(drizzleOrm.sql.raw(`PRAGMA read_uncommitted = ${targetValue}`));
|
|
5989
6036
|
} catch (error) {
|
|
5990
|
-
|
|
6037
|
+
logger10.warn("Failed to restore SQLite read_uncommitted pragma", {
|
|
5991
6038
|
transactionId: this.id,
|
|
5992
6039
|
error: error instanceof Error ? error.message : String(error)
|
|
5993
6040
|
});
|
|
@@ -6013,14 +6060,14 @@ var ManagedTransaction = class {
|
|
|
6013
6060
|
};
|
|
6014
6061
|
|
|
6015
6062
|
// src/data/relational/query/transaction-runner.ts
|
|
6016
|
-
var
|
|
6063
|
+
var logger11 = core.createLogger("agentforge:tools:data:relational:transaction");
|
|
6017
6064
|
var transactionSequence = 0;
|
|
6018
6065
|
async function withTransaction(manager, operation, options) {
|
|
6019
6066
|
const startTime = Date.now();
|
|
6020
6067
|
const resolvedOptions = resolveTransactionOptions(options);
|
|
6021
6068
|
const transactionId = `tx-${++transactionSequence}`;
|
|
6022
6069
|
const vendor = manager.getVendor();
|
|
6023
|
-
|
|
6070
|
+
logger11.debug("Starting transaction", {
|
|
6024
6071
|
transactionId,
|
|
6025
6072
|
vendor,
|
|
6026
6073
|
...resolvedOptions.isolationLevel ? { isolationLevel: resolvedOptions.isolationLevel } : {},
|
|
@@ -6047,7 +6094,7 @@ async function withTransaction(manager, operation, options) {
|
|
|
6047
6094
|
if (transaction.isActive()) {
|
|
6048
6095
|
await transaction.commit();
|
|
6049
6096
|
}
|
|
6050
|
-
|
|
6097
|
+
logger11.debug("Transaction committed", {
|
|
6051
6098
|
transactionId,
|
|
6052
6099
|
vendor,
|
|
6053
6100
|
duration: Date.now() - startTime
|
|
@@ -6058,14 +6105,14 @@ async function withTransaction(manager, operation, options) {
|
|
|
6058
6105
|
try {
|
|
6059
6106
|
await transaction.rollback();
|
|
6060
6107
|
} catch (rollbackError) {
|
|
6061
|
-
|
|
6108
|
+
logger11.error("Transaction rollback failed", {
|
|
6062
6109
|
transactionId,
|
|
6063
6110
|
vendor,
|
|
6064
6111
|
error: rollbackError instanceof Error ? rollbackError.message : String(rollbackError)
|
|
6065
6112
|
});
|
|
6066
6113
|
}
|
|
6067
6114
|
}
|
|
6068
|
-
|
|
6115
|
+
logger11.error("Transaction failed", {
|
|
6069
6116
|
transactionId,
|
|
6070
6117
|
vendor,
|
|
6071
6118
|
duration: Date.now() - startTime,
|
|
@@ -6556,7 +6603,7 @@ async function inspectSQLite(runQueryRows) {
|
|
|
6556
6603
|
}
|
|
6557
6604
|
|
|
6558
6605
|
// src/data/relational/schema/schema-inspector.ts
|
|
6559
|
-
var
|
|
6606
|
+
var logger12 = core.createLogger("agentforge:tools:data:relational:schema-inspector");
|
|
6560
6607
|
var DEFAULT_CACHE_TTL_MS = 6e4;
|
|
6561
6608
|
var schemaCache = /* @__PURE__ */ new Map();
|
|
6562
6609
|
var SchemaInspector = class _SchemaInspector {
|
|
@@ -6584,7 +6631,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6584
6631
|
if (!bypassCache && this.cacheKey) {
|
|
6585
6632
|
const cached = schemaCache.get(this.cacheKey);
|
|
6586
6633
|
if (cached && cached.expiresAt > Date.now()) {
|
|
6587
|
-
|
|
6634
|
+
logger12.debug("Schema cache hit", { vendor: this.vendor });
|
|
6588
6635
|
return filterSchemaTables(cloneSchema(cached.schema), tableFilters);
|
|
6589
6636
|
}
|
|
6590
6637
|
}
|
|
@@ -6629,7 +6676,7 @@ var SchemaInspector = class _SchemaInspector {
|
|
|
6629
6676
|
return result.rows;
|
|
6630
6677
|
}
|
|
6631
6678
|
};
|
|
6632
|
-
var
|
|
6679
|
+
var logger13 = core.createLogger("agentforge:tools:data:relational:schema-validator");
|
|
6633
6680
|
function validateTableExists(schema, tableName) {
|
|
6634
6681
|
const errors = [];
|
|
6635
6682
|
if (!tableName || typeof tableName !== "string") {
|
|
@@ -6643,7 +6690,7 @@ function validateTableExists(schema, tableName) {
|
|
|
6643
6690
|
`Table "${tableName}" does not exist. Available tables: ${available || "(none)"}`
|
|
6644
6691
|
);
|
|
6645
6692
|
}
|
|
6646
|
-
|
|
6693
|
+
logger13.debug("Table existence validation", { tableName, valid: errors.length === 0 });
|
|
6647
6694
|
return { valid: errors.length === 0, errors };
|
|
6648
6695
|
}
|
|
6649
6696
|
function validateColumnsExist(schema, tableName, columnNames) {
|
|
@@ -6666,7 +6713,7 @@ function validateColumnsExist(schema, tableName, columnNames) {
|
|
|
6666
6713
|
);
|
|
6667
6714
|
}
|
|
6668
6715
|
}
|
|
6669
|
-
|
|
6716
|
+
logger13.debug("Column existence validation", {
|
|
6670
6717
|
tableName,
|
|
6671
6718
|
columnCount: columnNames.length,
|
|
6672
6719
|
valid: errors.length === 0
|
|
@@ -6702,7 +6749,7 @@ function validateColumnTypes(schema, tableName, expectedTypes) {
|
|
|
6702
6749
|
);
|
|
6703
6750
|
}
|
|
6704
6751
|
}
|
|
6705
|
-
|
|
6752
|
+
logger13.debug("Column type validation", {
|
|
6706
6753
|
tableName,
|
|
6707
6754
|
typeChecks: Object.keys(expectedTypes).length,
|
|
6708
6755
|
valid: errors.length === 0
|
|
@@ -6722,7 +6769,7 @@ function findTable(schema, tableName) {
|
|
|
6722
6769
|
function formatTableName(table) {
|
|
6723
6770
|
return table.schema ? `${table.schema}.${table.name}` : table.name;
|
|
6724
6771
|
}
|
|
6725
|
-
var
|
|
6772
|
+
var logger14 = core.createLogger("agentforge:tools:data:relational:type-mapper");
|
|
6726
6773
|
var POSTGRES_TYPE_MAP = {
|
|
6727
6774
|
// Numeric
|
|
6728
6775
|
smallint: "number",
|
|
@@ -6888,7 +6935,7 @@ function mapColumnType(vendor, dbType, nullable = false) {
|
|
|
6888
6935
|
const result = { tsType, nullable, dbType };
|
|
6889
6936
|
if (tsType === "unknown" && normalised !== "json" && normalised !== "jsonb") {
|
|
6890
6937
|
result.notes = `No explicit mapping for "${dbType}"; defaulting to unknown`;
|
|
6891
|
-
|
|
6938
|
+
logger14.debug("Unmapped database type", { vendor, dbType, normalised });
|
|
6892
6939
|
}
|
|
6893
6940
|
if ((normalised === "bigint" || normalised === "int8" || normalised === "bigserial") && (vendor === "postgresql" || vendor === "mysql")) {
|
|
6894
6941
|
result.notes = "Mapped to string to avoid JavaScript number precision loss for 64-bit integers";
|
|
@@ -6903,7 +6950,7 @@ function mapSchemaTypes(vendor, columns) {
|
|
|
6903
6950
|
}
|
|
6904
6951
|
result.get(col.table).set(col.name, mapColumnType(vendor, col.type, col.nullable));
|
|
6905
6952
|
}
|
|
6906
|
-
|
|
6953
|
+
logger14.debug("Schema type mapping complete", {
|
|
6907
6954
|
vendor,
|
|
6908
6955
|
tables: result.size,
|
|
6909
6956
|
columns: columns.length
|
|
@@ -6920,7 +6967,7 @@ function normaliseDbType(raw) {
|
|
|
6920
6967
|
type = type.replace(/\s+unsigned$/, "");
|
|
6921
6968
|
return type.trim();
|
|
6922
6969
|
}
|
|
6923
|
-
var
|
|
6970
|
+
var logger15 = core.createLogger("agentforge:tools:data:relational:schema-diff");
|
|
6924
6971
|
function diffSchemas(before, after) {
|
|
6925
6972
|
const tableDiffs = [];
|
|
6926
6973
|
let columnsAdded = 0;
|
|
@@ -6960,7 +7007,7 @@ function diffSchemas(before, after) {
|
|
|
6960
7007
|
const tablesRemoved = tableDiffs.filter((d) => d.type === "removed").length;
|
|
6961
7008
|
const tablesChanged = tableDiffs.filter((d) => d.type === "changed").length;
|
|
6962
7009
|
const identical = tableDiffs.length === 0;
|
|
6963
|
-
|
|
7010
|
+
logger15.debug("Schema diff computed", {
|
|
6964
7011
|
identical,
|
|
6965
7012
|
tablesAdded,
|
|
6966
7013
|
tablesRemoved,
|
|
@@ -7004,7 +7051,7 @@ function importSchemaFromJson(json) {
|
|
|
7004
7051
|
throw new Error(`Invalid schema JSON: table "${table.name}" missing "primaryKey" array`);
|
|
7005
7052
|
}
|
|
7006
7053
|
}
|
|
7007
|
-
|
|
7054
|
+
logger15.debug("Schema imported from JSON", {
|
|
7008
7055
|
vendor: obj.vendor,
|
|
7009
7056
|
tableCount: obj.tables.length
|
|
7010
7057
|
});
|
|
@@ -7301,7 +7348,7 @@ function isSafeValidationError(error) {
|
|
|
7301
7348
|
}
|
|
7302
7349
|
|
|
7303
7350
|
// src/data/relational/tools/relational-select/executor.ts
|
|
7304
|
-
var
|
|
7351
|
+
var logger16 = core.createLogger("agentforge:tools:data:relational:select");
|
|
7305
7352
|
function toSelectQueryInput(input) {
|
|
7306
7353
|
return {
|
|
7307
7354
|
table: input.table,
|
|
@@ -7315,7 +7362,7 @@ function toSelectQueryInput(input) {
|
|
|
7315
7362
|
}
|
|
7316
7363
|
async function executeSelect(manager, input, context) {
|
|
7317
7364
|
const startTime = Date.now();
|
|
7318
|
-
|
|
7365
|
+
logger16.debug("Building SELECT query", {
|
|
7319
7366
|
vendor: input.vendor,
|
|
7320
7367
|
table: input.table,
|
|
7321
7368
|
hasWhere: !!input.where,
|
|
@@ -7333,7 +7380,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7333
7380
|
};
|
|
7334
7381
|
const streamInput = toSelectQueryInput(input);
|
|
7335
7382
|
if (input.streaming.benchmark) {
|
|
7336
|
-
|
|
7383
|
+
logger16.warn("Streaming benchmark enabled; SELECT will execute up to three times (result + benchmark regular + benchmark streaming).", {
|
|
7337
7384
|
vendor: input.vendor,
|
|
7338
7385
|
table: input.table,
|
|
7339
7386
|
chunkSize: streamOptions.chunkSize ?? DEFAULT_CHUNK_SIZE,
|
|
@@ -7344,7 +7391,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7344
7391
|
const streamResult = await executeStreamingSelect(executor, streamInput, streamOptions);
|
|
7345
7392
|
const benchmark = input.streaming.benchmark ? await benchmarkStreamingSelectMemory(executor, streamInput, streamOptions) : void 0;
|
|
7346
7393
|
const executionTime2 = Date.now() - startTime;
|
|
7347
|
-
|
|
7394
|
+
logger16.debug("Streaming SELECT query executed successfully", {
|
|
7348
7395
|
vendor: input.vendor,
|
|
7349
7396
|
table: input.table,
|
|
7350
7397
|
rowCount: streamResult.rowCount,
|
|
@@ -7373,7 +7420,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7373
7420
|
const executionTime = Date.now() - startTime;
|
|
7374
7421
|
const rows = Array.isArray(result) ? result : result.rows || [];
|
|
7375
7422
|
const rowCount = rows.length;
|
|
7376
|
-
|
|
7423
|
+
logger16.debug("SELECT query executed successfully", {
|
|
7377
7424
|
vendor: input.vendor,
|
|
7378
7425
|
table: input.table,
|
|
7379
7426
|
rowCount,
|
|
@@ -7386,7 +7433,7 @@ async function executeSelect(manager, input, context) {
|
|
|
7386
7433
|
};
|
|
7387
7434
|
} catch (error) {
|
|
7388
7435
|
const executionTime = Date.now() - startTime;
|
|
7389
|
-
|
|
7436
|
+
logger16.error("SELECT query execution failed", {
|
|
7390
7437
|
vendor: input.vendor,
|
|
7391
7438
|
table: input.table,
|
|
7392
7439
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -7562,7 +7609,7 @@ function isSafeInsertError(error) {
|
|
|
7562
7609
|
}
|
|
7563
7610
|
|
|
7564
7611
|
// src/data/relational/tools/relational-insert/executor.ts
|
|
7565
|
-
var
|
|
7612
|
+
var logger17 = core.createLogger("agentforge:tools:data:relational:insert");
|
|
7566
7613
|
function toNumber(value) {
|
|
7567
7614
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7568
7615
|
}
|
|
@@ -7711,7 +7758,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7711
7758
|
maxRetries: options.maxRetries,
|
|
7712
7759
|
retryDelayMs: options.retryDelayMs,
|
|
7713
7760
|
onProgress: (progress) => {
|
|
7714
|
-
|
|
7761
|
+
logger17.debug("INSERT batch progress", {
|
|
7715
7762
|
vendor: input.vendor,
|
|
7716
7763
|
table: input.table,
|
|
7717
7764
|
...progress
|
|
@@ -7724,7 +7771,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7724
7771
|
const insertedIds = batchResult.results.flatMap((result) => result.insertedIds);
|
|
7725
7772
|
let benchmark;
|
|
7726
7773
|
if (options.benchmark) {
|
|
7727
|
-
|
|
7774
|
+
logger17.warn("INSERT batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
7728
7775
|
vendor: input.vendor,
|
|
7729
7776
|
table: input.table,
|
|
7730
7777
|
totalRows: input.data.length,
|
|
@@ -7761,7 +7808,7 @@ async function executeInsertInBatchMode(manager, input, context, options) {
|
|
|
7761
7808
|
}
|
|
7762
7809
|
async function executeInsert(manager, input, context) {
|
|
7763
7810
|
const startTime = Date.now();
|
|
7764
|
-
|
|
7811
|
+
logger17.debug("Building INSERT query", {
|
|
7765
7812
|
vendor: input.vendor,
|
|
7766
7813
|
table: input.table,
|
|
7767
7814
|
isBatch: Array.isArray(input.data),
|
|
@@ -7777,7 +7824,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7777
7824
|
batchOptions
|
|
7778
7825
|
) : await executeInsertOnce(manager, input, context);
|
|
7779
7826
|
const executionTime = Date.now() - startTime;
|
|
7780
|
-
|
|
7827
|
+
logger17.debug("INSERT query executed successfully", {
|
|
7781
7828
|
vendor: input.vendor,
|
|
7782
7829
|
table: input.table,
|
|
7783
7830
|
rowCount: result.rowCount,
|
|
@@ -7793,7 +7840,7 @@ async function executeInsert(manager, input, context) {
|
|
|
7793
7840
|
};
|
|
7794
7841
|
} catch (error) {
|
|
7795
7842
|
const executionTime = Date.now() - startTime;
|
|
7796
|
-
|
|
7843
|
+
logger17.error("INSERT query execution failed", {
|
|
7797
7844
|
vendor: input.vendor,
|
|
7798
7845
|
table: input.table,
|
|
7799
7846
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8123,7 +8170,7 @@ function isSafeUpdateError(error) {
|
|
|
8123
8170
|
}
|
|
8124
8171
|
|
|
8125
8172
|
// src/data/relational/tools/relational-update/executor.ts
|
|
8126
|
-
var
|
|
8173
|
+
var logger18 = core.createLogger("agentforge:tools:data:relational:update");
|
|
8127
8174
|
function toNumber2(value) {
|
|
8128
8175
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8129
8176
|
}
|
|
@@ -8245,7 +8292,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8245
8292
|
maxRetries: options.maxRetries,
|
|
8246
8293
|
retryDelayMs: options.retryDelayMs,
|
|
8247
8294
|
onProgress: (progress) => {
|
|
8248
|
-
|
|
8295
|
+
logger18.debug("UPDATE batch progress", {
|
|
8249
8296
|
vendor: input.vendor,
|
|
8250
8297
|
table: input.table,
|
|
8251
8298
|
...progress
|
|
@@ -8257,7 +8304,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8257
8304
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8258
8305
|
let benchmark;
|
|
8259
8306
|
if (options.benchmark) {
|
|
8260
|
-
|
|
8307
|
+
logger18.warn("UPDATE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8261
8308
|
vendor: input.vendor,
|
|
8262
8309
|
table: input.table,
|
|
8263
8310
|
operationCount: input.operations.length,
|
|
@@ -8292,7 +8339,7 @@ async function executeUpdateInBatchMode(manager, input, context, options) {
|
|
|
8292
8339
|
}
|
|
8293
8340
|
async function executeUpdate(manager, input, context) {
|
|
8294
8341
|
const startTime = Date.now();
|
|
8295
|
-
|
|
8342
|
+
logger18.debug("Building UPDATE query", {
|
|
8296
8343
|
vendor: input.vendor,
|
|
8297
8344
|
table: input.table,
|
|
8298
8345
|
hasWhere: !!input.where?.length,
|
|
@@ -8310,7 +8357,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8310
8357
|
batchOptions
|
|
8311
8358
|
) : await executeSingleUpdate(manager, input, toSingleUpdateOperation(input), context);
|
|
8312
8359
|
const executionTime = Date.now() - startTime;
|
|
8313
|
-
|
|
8360
|
+
logger18.debug("UPDATE query executed successfully", {
|
|
8314
8361
|
vendor: input.vendor,
|
|
8315
8362
|
table: input.table,
|
|
8316
8363
|
rowCount: result.rowCount,
|
|
@@ -8324,7 +8371,7 @@ async function executeUpdate(manager, input, context) {
|
|
|
8324
8371
|
};
|
|
8325
8372
|
} catch (error) {
|
|
8326
8373
|
const executionTime = Date.now() - startTime;
|
|
8327
|
-
|
|
8374
|
+
logger18.error("UPDATE query execution failed", {
|
|
8328
8375
|
vendor: input.vendor,
|
|
8329
8376
|
table: input.table,
|
|
8330
8377
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8628,7 +8675,7 @@ function isSafeDeleteError(error) {
|
|
|
8628
8675
|
}
|
|
8629
8676
|
|
|
8630
8677
|
// src/data/relational/tools/relational-delete/executor.ts
|
|
8631
|
-
var
|
|
8678
|
+
var logger19 = core.createLogger("agentforge:tools:data:relational:delete");
|
|
8632
8679
|
function toNumber3(value) {
|
|
8633
8680
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
8634
8681
|
}
|
|
@@ -8749,7 +8796,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8749
8796
|
maxRetries: options.maxRetries,
|
|
8750
8797
|
retryDelayMs: options.retryDelayMs,
|
|
8751
8798
|
onProgress: (progress) => {
|
|
8752
|
-
|
|
8799
|
+
logger19.debug("DELETE batch progress", {
|
|
8753
8800
|
vendor: input.vendor,
|
|
8754
8801
|
table: input.table,
|
|
8755
8802
|
...progress
|
|
@@ -8762,7 +8809,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8762
8809
|
const operationFailures = batchResult.results.flatMap((result) => result.failures);
|
|
8763
8810
|
let benchmark;
|
|
8764
8811
|
if (options.benchmark) {
|
|
8765
|
-
|
|
8812
|
+
logger19.warn("DELETE batch benchmark enabled. Synthetic benchmark callbacks are side-effect free and do not execute SQL.", {
|
|
8766
8813
|
vendor: input.vendor,
|
|
8767
8814
|
table: input.table,
|
|
8768
8815
|
operationCount: input.operations.length,
|
|
@@ -8798,7 +8845,7 @@ async function executeDeleteInBatchMode(manager, input, context, options) {
|
|
|
8798
8845
|
}
|
|
8799
8846
|
async function executeDelete(manager, input, context) {
|
|
8800
8847
|
const startTime = Date.now();
|
|
8801
|
-
|
|
8848
|
+
logger19.debug("Building DELETE query", {
|
|
8802
8849
|
vendor: input.vendor,
|
|
8803
8850
|
table: input.table,
|
|
8804
8851
|
hasWhere: !!input.where?.length,
|
|
@@ -8817,7 +8864,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8817
8864
|
batchOptions
|
|
8818
8865
|
) : await executeSingleDelete(manager, input, toSingleDeleteOperation(input), context);
|
|
8819
8866
|
const executionTime = Date.now() - startTime;
|
|
8820
|
-
|
|
8867
|
+
logger19.debug("DELETE query executed successfully", {
|
|
8821
8868
|
vendor: input.vendor,
|
|
8822
8869
|
table: input.table,
|
|
8823
8870
|
rowCount: result.rowCount,
|
|
@@ -8833,7 +8880,7 @@ async function executeDelete(manager, input, context) {
|
|
|
8833
8880
|
};
|
|
8834
8881
|
} catch (error) {
|
|
8835
8882
|
const executionTime = Date.now() - startTime;
|
|
8836
|
-
|
|
8883
|
+
logger19.error("DELETE query execution failed", {
|
|
8837
8884
|
vendor: input.vendor,
|
|
8838
8885
|
table: input.table,
|
|
8839
8886
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -8938,7 +8985,7 @@ function isSafeGetSchemaValidationError(error) {
|
|
|
8938
8985
|
}
|
|
8939
8986
|
|
|
8940
8987
|
// src/data/relational/tools/relational-get-schema.ts
|
|
8941
|
-
var
|
|
8988
|
+
var logger20 = core.createLogger("agentforge:tools:data:relational:get-schema");
|
|
8942
8989
|
function buildSchemaCacheKey(vendor, connectionString, database) {
|
|
8943
8990
|
const databaseScope = database ?? "default";
|
|
8944
8991
|
const connectionHash = crypto.createHash("sha256").update(connectionString).digest("hex");
|
|
@@ -9010,7 +9057,7 @@ var relationalGetSchema = core.toolBuilder().name("relational-get-schema").displ
|
|
|
9010
9057
|
summary
|
|
9011
9058
|
};
|
|
9012
9059
|
} catch (error) {
|
|
9013
|
-
|
|
9060
|
+
logger20.error("Schema introspection failed", {
|
|
9014
9061
|
vendor: input.vendor,
|
|
9015
9062
|
hasTablesFilter: Array.isArray(input.tables),
|
|
9016
9063
|
tablesFilterCount: input.tables?.length ?? 0,
|
|
@@ -10176,7 +10223,7 @@ var AskHumanInputSchema = zod.z.object({
|
|
|
10176
10223
|
suggestions: zod.z.array(zod.z.string()).optional().describe("Suggested responses for the human")
|
|
10177
10224
|
});
|
|
10178
10225
|
var logLevel3 = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
|
|
10179
|
-
var
|
|
10226
|
+
var logger21 = core.createLogger("agentforge:tools:agent:ask-human", { level: logLevel3 });
|
|
10180
10227
|
function isRecord2(value) {
|
|
10181
10228
|
return typeof value === "object" && value !== null;
|
|
10182
10229
|
}
|
|
@@ -10241,7 +10288,7 @@ function createAskHumanTool() {
|
|
|
10241
10288
|
suggestions: validatedInput.suggestions,
|
|
10242
10289
|
status: "pending"
|
|
10243
10290
|
};
|
|
10244
|
-
|
|
10291
|
+
logger21.debug("About to call interrupt()", {
|
|
10245
10292
|
humanRequest: {
|
|
10246
10293
|
id: humanRequest.id,
|
|
10247
10294
|
question: humanRequest.question,
|
|
@@ -10257,13 +10304,13 @@ function createAskHumanTool() {
|
|
|
10257
10304
|
let response;
|
|
10258
10305
|
try {
|
|
10259
10306
|
response = interrupt(humanRequest);
|
|
10260
|
-
|
|
10307
|
+
logger21.debug("interrupt() returned successfully", {
|
|
10261
10308
|
responseType: typeof response,
|
|
10262
10309
|
hasResponse: response != null,
|
|
10263
10310
|
...typeof response === "string" ? { responseLength: response.length } : {}
|
|
10264
10311
|
});
|
|
10265
10312
|
} catch (error) {
|
|
10266
|
-
|
|
10313
|
+
logger21.debug("interrupt() threw error (expected for GraphInterrupt)", {
|
|
10267
10314
|
...error && typeof error === "object" && "constructor" in error ? { errorType: error.constructor?.name } : {},
|
|
10268
10315
|
error: error instanceof Error ? error.message : String(error)
|
|
10269
10316
|
});
|