@agentforge/tools 0.16.13 → 0.16.15

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