@samanhappy/mcphub 1.0.30 → 1.0.32

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.
Files changed (277) hide show
  1. package/dist/betterAuth.js +13 -5
  2. package/dist/betterAuth.js.map +1 -1
  3. package/dist/cli/commands/cache.js.map +1 -1
  4. package/dist/cli/commands/call.js +2 -2
  5. package/dist/cli/commands/call.js.map +1 -1
  6. package/dist/cli/commands/config.js.map +1 -1
  7. package/dist/cli/commands/discover.js.map +1 -1
  8. package/dist/cli/commands/export.js.map +1 -1
  9. package/dist/cli/commands/groups.js.map +1 -1
  10. package/dist/cli/commands/install.js +1 -1
  11. package/dist/cli/commands/install.js.map +1 -1
  12. package/dist/cli/commands/keys.js.map +1 -1
  13. package/dist/cli/commands/login.js.map +1 -1
  14. package/dist/cli/commands/servers.js.map +1 -1
  15. package/dist/cli/commands/tools.js +2 -2
  16. package/dist/cli/commands/tools.js.map +1 -1
  17. package/dist/cli/context.js +1 -1
  18. package/dist/cli/context.js.map +1 -1
  19. package/dist/cli/http.js +3 -1
  20. package/dist/cli/http.js.map +1 -1
  21. package/dist/clients/openapi.js +75 -7
  22. package/dist/clients/openapi.js.map +1 -1
  23. package/dist/config/DaoConfigService.js +3 -2
  24. package/dist/config/DaoConfigService.js.map +1 -1
  25. package/dist/config/configManager.js +11 -9
  26. package/dist/config/configManager.js.map +1 -1
  27. package/dist/config/index.js +32 -7
  28. package/dist/config/index.js.map +1 -1
  29. package/dist/config/jwt.js +2 -1
  30. package/dist/config/jwt.js.map +1 -1
  31. package/dist/config/migrationUtils.js +46 -45
  32. package/dist/config/migrationUtils.js.map +1 -1
  33. package/dist/constants/oauthServerDefaults.js.map +1 -1
  34. package/dist/controllers/activityController.js +6 -5
  35. package/dist/controllers/activityController.js.map +1 -1
  36. package/dist/controllers/authController.js +5 -4
  37. package/dist/controllers/authController.js.map +1 -1
  38. package/dist/controllers/bearerKeyController.js +7 -6
  39. package/dist/controllers/bearerKeyController.js.map +1 -1
  40. package/dist/controllers/betterAuthController.js +2 -1
  41. package/dist/controllers/betterAuthController.js.map +1 -1
  42. package/dist/controllers/builtinPromptController.js +13 -5
  43. package/dist/controllers/builtinPromptController.js.map +1 -1
  44. package/dist/controllers/builtinResourceController.js +14 -6
  45. package/dist/controllers/builtinResourceController.js.map +1 -1
  46. package/dist/controllers/changelogController.js +5 -2
  47. package/dist/controllers/changelogController.js.map +1 -1
  48. package/dist/controllers/cloudController.js +11 -10
  49. package/dist/controllers/cloudController.js.map +1 -1
  50. package/dist/controllers/configController.js +4 -3
  51. package/dist/controllers/configController.js.map +1 -1
  52. package/dist/controllers/contextCostController.js +3 -2
  53. package/dist/controllers/contextCostController.js.map +1 -1
  54. package/dist/controllers/groupController.js +2 -1
  55. package/dist/controllers/groupController.js.map +1 -1
  56. package/dist/controllers/healthController.js +2 -1
  57. package/dist/controllers/healthController.js.map +1 -1
  58. package/dist/controllers/hostedInternalController.js +2 -1
  59. package/dist/controllers/hostedInternalController.js.map +1 -1
  60. package/dist/controllers/logController.js +5 -4
  61. package/dist/controllers/logController.js.map +1 -1
  62. package/dist/controllers/mcpbController.js +17 -7
  63. package/dist/controllers/mcpbController.js.map +1 -1
  64. package/dist/controllers/oauthCallbackController.js +28 -27
  65. package/dist/controllers/oauthCallbackController.js.map +1 -1
  66. package/dist/controllers/oauthClientController.js +7 -6
  67. package/dist/controllers/oauthClientController.js.map +1 -1
  68. package/dist/controllers/oauthDynamicRegistrationController.js +22 -4
  69. package/dist/controllers/oauthDynamicRegistrationController.js.map +1 -1
  70. package/dist/controllers/oauthServerController.js +96 -10
  71. package/dist/controllers/oauthServerController.js.map +1 -1
  72. package/dist/controllers/openApiController.js +7 -6
  73. package/dist/controllers/openApiController.js.map +1 -1
  74. package/dist/controllers/promptController.js +2 -1
  75. package/dist/controllers/promptController.js.map +1 -1
  76. package/dist/controllers/registryController.js +4 -3
  77. package/dist/controllers/registryController.js.map +1 -1
  78. package/dist/controllers/serverController.js +46 -34
  79. package/dist/controllers/serverController.js.map +1 -1
  80. package/dist/controllers/templateController.js +2 -1
  81. package/dist/controllers/templateController.js.map +1 -1
  82. package/dist/controllers/toolController.js +2 -1
  83. package/dist/controllers/toolController.js.map +1 -1
  84. package/dist/dao/DaoFactory.js +3 -2
  85. package/dist/dao/DaoFactory.js.map +1 -1
  86. package/dist/dao/ServerDao.js.map +1 -1
  87. package/dist/dao/UserConfigDaoDbImpl.js.map +1 -1
  88. package/dist/dao/UserDao.js.map +1 -1
  89. package/dist/dao/base/JsonFileBaseDao.js +3 -2
  90. package/dist/dao/base/JsonFileBaseDao.js.map +1 -1
  91. package/dist/dao/examples.js +35 -34
  92. package/dist/dao/examples.js.map +1 -1
  93. package/dist/db/connection.js +59 -58
  94. package/dist/db/connection.js.map +1 -1
  95. package/dist/db/index.js +2 -1
  96. package/dist/db/index.js.map +1 -1
  97. package/dist/db/repositories/ServerRepository.js +3 -3
  98. package/dist/db/repositories/ServerRepository.js.map +1 -1
  99. package/dist/db/repositories/SystemConfigRepository.js +2 -1
  100. package/dist/db/repositories/SystemConfigRepository.js.map +1 -1
  101. package/dist/db/repositories/UserConfigRepository.js.map +1 -1
  102. package/dist/db/repositories/VectorEmbeddingRepository.js +6 -5
  103. package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -1
  104. package/dist/index.js +28 -19
  105. package/dist/index.js.map +1 -1
  106. package/dist/middlewares/auth.js +4 -3
  107. package/dist/middlewares/auth.js.map +1 -1
  108. package/dist/middlewares/index.js +2 -1
  109. package/dist/middlewares/index.js.map +1 -1
  110. package/dist/middlewares/userContext.js +7 -6
  111. package/dist/middlewares/userContext.js.map +1 -1
  112. package/dist/models/OAuth.js +7 -6
  113. package/dist/models/OAuth.js.map +1 -1
  114. package/dist/models/User.js +13 -12
  115. package/dist/models/User.js.map +1 -1
  116. package/dist/routes/index.js +9 -9
  117. package/dist/routes/index.js.map +1 -1
  118. package/dist/scripts/dao-demo.js +28 -27
  119. package/dist/scripts/dao-demo.js.map +1 -1
  120. package/dist/server.js +40 -30
  121. package/dist/server.js.map +1 -1
  122. package/dist/services/activityLoggingService.js +3 -2
  123. package/dist/services/activityLoggingService.js.map +1 -1
  124. package/dist/services/betterAuthConfig.js +1 -4
  125. package/dist/services/betterAuthConfig.js.map +1 -1
  126. package/dist/services/betterAuthSession.js +8 -7
  127. package/dist/services/betterAuthSession.js.map +1 -1
  128. package/dist/services/changelogService.js +5 -2
  129. package/dist/services/changelogService.js.map +1 -1
  130. package/dist/services/cloudService.js +10 -9
  131. package/dist/services/cloudService.js.map +1 -1
  132. package/dist/services/contextCostService.js +6 -2
  133. package/dist/services/contextCostService.js.map +1 -1
  134. package/dist/services/groupService.js +8 -7
  135. package/dist/services/groupService.js.map +1 -1
  136. package/dist/services/hostedAuthService.js +3 -2
  137. package/dist/services/hostedAuthService.js.map +1 -1
  138. package/dist/services/hostedControlPlaneClient.js.map +1 -1
  139. package/dist/services/hostedEventSubscriber.js +9 -8
  140. package/dist/services/hostedEventSubscriber.js.map +1 -1
  141. package/dist/services/hostedRuntimeCatalogNames.js +1 -3
  142. package/dist/services/hostedRuntimeCatalogNames.js.map +1 -1
  143. package/dist/services/keepAliveService.js +7 -6
  144. package/dist/services/keepAliveService.js.map +1 -1
  145. package/dist/services/marketService.js +2 -1
  146. package/dist/services/marketService.js.map +1 -1
  147. package/dist/services/mcpOAuthProvider.js +22 -21
  148. package/dist/services/mcpOAuthProvider.js.map +1 -1
  149. package/dist/services/mcpService.js +136 -123
  150. package/dist/services/mcpService.js.map +1 -1
  151. package/dist/services/oauthClientRegistration.js +30 -29
  152. package/dist/services/oauthClientRegistration.js.map +1 -1
  153. package/dist/services/oauthServerService.js +22 -17
  154. package/dist/services/oauthServerService.js.map +1 -1
  155. package/dist/services/oauthService.js +16 -15
  156. package/dist/services/oauthService.js.map +1 -1
  157. package/dist/services/oauthSettingsStore.js +4 -3
  158. package/dist/services/oauthSettingsStore.js.map +1 -1
  159. package/dist/services/openApiGeneratorService.js +1 -3
  160. package/dist/services/openApiGeneratorService.js.map +1 -1
  161. package/dist/services/registry.js +2 -1
  162. package/dist/services/registry.js.map +1 -1
  163. package/dist/services/requestContextService.js.map +1 -1
  164. package/dist/services/smartRoutingService.js +6 -5
  165. package/dist/services/smartRoutingService.js.map +1 -1
  166. package/dist/services/sseService.js +66 -55
  167. package/dist/services/sseService.js.map +1 -1
  168. package/dist/services/templateService.js +57 -12
  169. package/dist/services/templateService.js.map +1 -1
  170. package/dist/services/toolResultCompressionService.js +8 -5
  171. package/dist/services/toolResultCompressionService.js.map +1 -1
  172. package/dist/services/upstreamOAuthDisconnectService.js +9 -6
  173. package/dist/services/upstreamOAuthDisconnectService.js.map +1 -1
  174. package/dist/services/userService.js +5 -4
  175. package/dist/services/userService.js.map +1 -1
  176. package/dist/services/vectorSearchService.js +126 -112
  177. package/dist/services/vectorSearchService.js.map +1 -1
  178. package/dist/utils/abortIsolatingFetch.js +31 -0
  179. package/dist/utils/abortIsolatingFetch.js.map +1 -0
  180. package/dist/utils/basePath.js +13 -0
  181. package/dist/utils/basePath.js.map +1 -0
  182. package/dist/utils/cacheUtils.js +5 -4
  183. package/dist/utils/cacheUtils.js.map +1 -1
  184. package/dist/utils/corsOrigin.js +42 -0
  185. package/dist/utils/corsOrigin.js.map +1 -0
  186. package/dist/utils/dbRetry.js +2 -5
  187. package/dist/utils/dbRetry.js.map +1 -1
  188. package/dist/utils/frontendShell.js +89 -0
  189. package/dist/utils/frontendShell.js.map +1 -0
  190. package/dist/utils/i18n.js.map +1 -1
  191. package/dist/utils/logger.js +170 -0
  192. package/dist/utils/logger.js.map +1 -0
  193. package/dist/utils/migration.js +51 -50
  194. package/dist/utils/migration.js.map +1 -1
  195. package/dist/utils/oauthConsentResource.js +45 -0
  196. package/dist/utils/oauthConsentResource.js.map +1 -0
  197. package/dist/utils/parameterConversion.js +2 -1
  198. package/dist/utils/parameterConversion.js.map +1 -1
  199. package/dist/utils/path.js +9 -8
  200. package/dist/utils/path.js.map +1 -1
  201. package/dist/utils/proxyTrust.js.map +1 -1
  202. package/dist/utils/rateLimit.js +8 -0
  203. package/dist/utils/rateLimit.js.map +1 -1
  204. package/dist/utils/requireAdmin.js +15 -0
  205. package/dist/utils/requireAdmin.js.map +1 -0
  206. package/dist/utils/serverConfigPersistence.js.map +1 -1
  207. package/dist/utils/serverShutdown.js +3 -2
  208. package/dist/utils/serverShutdown.js.map +1 -1
  209. package/dist/utils/smartRouting.js +4 -3
  210. package/dist/utils/smartRouting.js.map +1 -1
  211. package/dist/utils/ssrf.js +19 -6
  212. package/dist/utils/ssrf.js.map +1 -1
  213. package/dist/utils/tokenCost.js.map +1 -1
  214. package/dist/utils/tokenTruncation.js +9 -4
  215. package/dist/utils/tokenTruncation.js.map +1 -1
  216. package/dist/utils/version.js +3 -2
  217. package/dist/utils/version.js.map +1 -1
  218. package/frontend/dist/assets/{ActivityPage-U9om5C9X.js → ActivityPage-C6m1hGLq.js} +2 -2
  219. package/frontend/dist/assets/{ActivityPage-U9om5C9X.js.map → ActivityPage-C6m1hGLq.js.map} +1 -1
  220. package/frontend/dist/assets/{ConfirmDialog-CYfXEuyU.js → ConfirmDialog-BCMNzi21.js} +2 -2
  221. package/frontend/dist/assets/{ConfirmDialog-CYfXEuyU.js.map → ConfirmDialog-BCMNzi21.js.map} +1 -1
  222. package/frontend/dist/assets/{Dashboard-DGqpU4bd.js → Dashboard-DFKfjPff.js} +2 -2
  223. package/frontend/dist/assets/{Dashboard-DGqpU4bd.js.map → Dashboard-DFKfjPff.js.map} +1 -1
  224. package/frontend/dist/assets/{DeleteDialog-DNe-zTEl.js → DeleteDialog-D9ycSRvn.js} +2 -2
  225. package/frontend/dist/assets/{DeleteDialog-DNe-zTEl.js.map → DeleteDialog-D9ycSRvn.js.map} +1 -1
  226. package/frontend/dist/assets/{EndpointCopy-DuGmhiMq.js → EndpointCopy-CP_Fb1To.js} +2 -2
  227. package/frontend/dist/assets/{EndpointCopy-DuGmhiMq.js.map → EndpointCopy-CP_Fb1To.js.map} +1 -1
  228. package/frontend/dist/assets/{GroupsPage-Dhqy02FY.js → GroupsPage-Cwfm5q-a.js} +3 -3
  229. package/frontend/dist/assets/{GroupsPage-Dhqy02FY.js.map → GroupsPage-Cwfm5q-a.js.map} +1 -1
  230. package/frontend/dist/assets/{LoginPage-BXRn47pC.js → LoginPage-CnF44h_n.js} +2 -2
  231. package/frontend/dist/assets/LoginPage-CnF44h_n.js.map +1 -0
  232. package/frontend/dist/assets/{LogsPage-CiO6LZEJ.js → LogsPage-BFIpICsM.js} +2 -2
  233. package/frontend/dist/assets/{LogsPage-CiO6LZEJ.js.map → LogsPage-BFIpICsM.js.map} +1 -1
  234. package/frontend/dist/assets/{MarketPage-BEdWfj0u.js → MarketPage-Du-NqiEl.js} +2 -2
  235. package/frontend/dist/assets/{MarketPage-BEdWfj0u.js.map → MarketPage-Du-NqiEl.js.map} +1 -1
  236. package/frontend/dist/assets/OAuthConsentPage-zqXUvKMF.js +2 -0
  237. package/frontend/dist/assets/OAuthConsentPage-zqXUvKMF.js.map +1 -0
  238. package/frontend/dist/assets/{Pagination-DLSuQ8hw.js → Pagination-Dwko3g48.js} +2 -2
  239. package/frontend/dist/assets/{Pagination-DLSuQ8hw.js.map → Pagination-Dwko3g48.js.map} +1 -1
  240. package/frontend/dist/assets/{PromptsPage-BG6oWgAk.js → PromptsPage-Cm8ykiI4.js} +2 -2
  241. package/frontend/dist/assets/{PromptsPage-BG6oWgAk.js.map → PromptsPage-Cm8ykiI4.js.map} +1 -1
  242. package/frontend/dist/assets/{ResourcesPage-BqJUKqnV.js → ResourcesPage-UMyO6mQ4.js} +2 -2
  243. package/frontend/dist/assets/{ResourcesPage-BqJUKqnV.js.map → ResourcesPage-UMyO6mQ4.js.map} +1 -1
  244. package/frontend/dist/assets/{ServersPage-CHbXHEcG.js → ServersPage-B0RoM8ez.js} +8 -8
  245. package/frontend/dist/assets/ServersPage-B0RoM8ez.js.map +1 -0
  246. package/frontend/dist/assets/{SettingsPage-B6yl-U9T.js → SettingsPage-BTB-36-n.js} +2 -2
  247. package/frontend/dist/assets/{SettingsPage-B6yl-U9T.js.map → SettingsPage-BTB-36-n.js.map} +1 -1
  248. package/frontend/dist/assets/{StatusDot-Bz7sBh0t.js → StatusDot-BAMXeT2x.js} +2 -2
  249. package/frontend/dist/assets/{StatusDot-Bz7sBh0t.js.map → StatusDot-BAMXeT2x.js.map} +1 -1
  250. package/frontend/dist/assets/{ToggleGroup-60voS_0U.js → ToggleGroup-Cfgt5lJo.js} +2 -2
  251. package/frontend/dist/assets/{ToggleGroup-60voS_0U.js.map → ToggleGroup-Cfgt5lJo.js.map} +1 -1
  252. package/frontend/dist/assets/{UsersPage-Dzzo9CC-.js → UsersPage-DlzYf7Su.js} +2 -2
  253. package/frontend/dist/assets/{UsersPage-Dzzo9CC-.js.map → UsersPage-DlzYf7Su.js.map} +1 -1
  254. package/frontend/dist/assets/{contextCost-CIOdvJNu.js → contextCost-kp2vZYp7.js} +2 -2
  255. package/frontend/dist/assets/{contextCost-CIOdvJNu.js.map → contextCost-kp2vZYp7.js.map} +1 -1
  256. package/frontend/dist/assets/{framework-vendor-I9Y6AgD5.js → framework-vendor-BHAQX05P.js} +3 -3
  257. package/frontend/dist/assets/{framework-vendor-I9Y6AgD5.js.map → framework-vendor-BHAQX05P.js.map} +1 -1
  258. package/frontend/dist/assets/{i18n-vendor-y9bLzIeh.js → i18n-vendor-CMcB7XUR.js} +2 -2
  259. package/frontend/dist/assets/{i18n-vendor-y9bLzIeh.js.map → i18n-vendor-CMcB7XUR.js.map} +1 -1
  260. package/frontend/dist/assets/{icons-vendor-hw0ScL8G.js → icons-vendor-HZHHWeTa.js} +65 -60
  261. package/frontend/dist/assets/icons-vendor-HZHHWeTa.js.map +1 -0
  262. package/frontend/dist/assets/index-CvXw771N.js +3 -0
  263. package/frontend/dist/assets/index-CvXw771N.js.map +1 -0
  264. package/frontend/dist/assets/{resourceService-DIIsi_li.js → resourceService-D2QmlFby.js} +2 -2
  265. package/frontend/dist/assets/{resourceService-DIIsi_li.js.map → resourceService-D2QmlFby.js.map} +1 -1
  266. package/frontend/dist/assets/useSettingsData-CeCvZ2nU.js +2 -0
  267. package/frontend/dist/assets/{useSettingsData-C84qj7ge.js.map → useSettingsData-CeCvZ2nU.js.map} +1 -1
  268. package/frontend/dist/assets/{variableDetection-Y9ymMI80.js → variableDetection-DKPiHkxr.js} +2 -2
  269. package/frontend/dist/assets/{variableDetection-Y9ymMI80.js.map → variableDetection-DKPiHkxr.js.map} +1 -1
  270. package/frontend/dist/index.html +4 -4
  271. package/package.json +2 -2
  272. package/frontend/dist/assets/LoginPage-BXRn47pC.js.map +0 -1
  273. package/frontend/dist/assets/ServersPage-CHbXHEcG.js.map +0 -1
  274. package/frontend/dist/assets/icons-vendor-hw0ScL8G.js.map +0 -1
  275. package/frontend/dist/assets/index-Ca9HKIrV.js +0 -3
  276. package/frontend/dist/assets/index-Ca9HKIrV.js.map +0 -1
  277. package/frontend/dist/assets/useSettingsData-C84qj7ge.js +0 -2
@@ -1,5 +1,5 @@
1
1
  import { getRepositoryFactory } from '../db/index.js';
2
- import { getAppDataSource, isDatabaseConnected, initializeDatabase, reconnectDatabase } from '../db/connection.js';
2
+ import { getAppDataSource, isDatabaseConnected, initializeDatabase, reconnectDatabase, } from '../db/connection.js';
3
3
  import { getServerDao } from '../dao/index.js';
4
4
  import { getSmartRoutingConfig } from '../utils/smartRouting.js';
5
5
  import { filterModelVisibleTools } from '../utils/mcpApps.js';
@@ -7,9 +7,13 @@ import { toFloat32Array } from '../utils/base64.js';
7
7
  import { truncateToTokenLimit, truncateWithHeuristic, getModelDefaultTokenLimit, } from '../utils/tokenTruncation.js';
8
8
  import { safeStringify, summarizeErrorForLogging } from '../utils/serialization.js';
9
9
  import logService from './logService.js';
10
- import { createHash } from 'node:crypto';
10
+ import { scryptSync } from 'node:crypto';
11
11
  import OpenAI from 'openai';
12
12
  import axios from 'axios';
13
+ import { logger } from '../utils/logger.js';
14
+ // Stable salt for the toolset cache key derivation. Not secret material — it
15
+ // only domain-separates the derivation so identical inputs remain deterministic.
16
+ const TOOLSET_HASH_KEY = 'mcphub:toolset-embedding-cache:v1';
13
17
  const maskApiKey = (apiKey) => {
14
18
  if (!apiKey) {
15
19
  return 'missing';
@@ -223,7 +227,9 @@ const extractRetryAfterMs = (error) => {
223
227
  return undefined;
224
228
  };
225
229
  const applyConfiguredBasePacingDelay = (basePacingDelayMs) => {
226
- const normalizedBaseDelay = typeof basePacingDelayMs === 'number' && !Number.isNaN(basePacingDelayMs) && basePacingDelayMs >= 0
230
+ const normalizedBaseDelay = typeof basePacingDelayMs === 'number' &&
231
+ !Number.isNaN(basePacingDelayMs) &&
232
+ basePacingDelayMs >= 0
227
233
  ? Math.floor(basePacingDelayMs)
228
234
  : SAFE_BASE_PACING_DELAY_MS;
229
235
  const previousBaseDelay = configuredBasePacingDelayMs;
@@ -249,7 +255,7 @@ const increaseAdaptivePacingDelay = (status) => {
249
255
  adaptivePacingDelayMs = Math.min(SAFE_MAX_PACING_DELAY_MS, adaptivePacingDelayMs + SAFE_PACING_DELAY_STEP_MS);
250
256
  lastPacingIncreaseAt = Date.now();
251
257
  if (adaptivePacingDelayMs !== previousDelay) {
252
- console.warn(`[Embedding][Throttle] Increased pacing delay to ${adaptivePacingDelayMs}ms after status=${status ?? 'unknown'}`);
258
+ logger.warn(`[Embedding][Throttle] Increased pacing delay to ${adaptivePacingDelayMs}ms after status=${status ?? 'unknown'}`);
253
259
  }
254
260
  };
255
261
  const executeWithRetry = async (operation, context) => {
@@ -279,15 +285,15 @@ const executeWithRetry = async (operation, context) => {
279
285
  if (retryAfterMs !== undefined && retryAfterMs > 0) {
280
286
  // Server specified an explicit wait — honor it regardless of accumulated time.
281
287
  waitMs = retryAfterMs;
282
- console.warn(`[Embedding][Retry] provider=${context.provider}, model=${context.model || 'unknown'}, baseURL=${context.baseURL || 'default'}, status=${status}, attempt=${attempt}, respecting Retry-After header: ${waitMs}ms`);
288
+ logger.warn(`[Embedding][Retry] provider=${context.provider}, model=${context.model || 'unknown'}, baseURL=${context.baseURL || 'default'}, status=${status}, attempt=${attempt}, respecting Retry-After header: ${waitMs}ms`);
283
289
  }
284
290
  else {
285
291
  // No Retry-After header: use 63 second cooldown and apply the 5-minute safety budget.
286
292
  waitMs = 63 * 1000;
287
- console.warn(`[Embedding][Retry] provider=${context.provider}, model=${context.model || 'unknown'}, baseURL=${context.baseURL || 'default'}, status=${status}, attempt=${attempt}, applying 63s rate-limit cooldown (no Retry-After header found)`);
293
+ logger.warn(`[Embedding][Retry] provider=${context.provider}, model=${context.model || 'unknown'}, baseURL=${context.baseURL || 'default'}, status=${status}, attempt=${attempt}, applying 63s rate-limit cooldown (no Retry-After header found)`);
288
294
  if (totalRetryTimeMs + waitMs > MAX_TOTAL_RETRY_TIME_MS) {
289
295
  const remainingMs = MAX_TOTAL_RETRY_TIME_MS - totalRetryTimeMs;
290
- console.warn(`[Embedding][Retry] Max retry time limit reached (no Retry-After). totalTime=${totalRetryTimeMs}ms, nextWait=${waitMs}ms, remaining=${remainingMs}ms, limit=${MAX_TOTAL_RETRY_TIME_MS}ms. Throwing error.`);
296
+ logger.warn(`[Embedding][Retry] Max retry time limit reached (no Retry-After). totalTime=${totalRetryTimeMs}ms, nextWait=${waitMs}ms, remaining=${remainingMs}ms, limit=${MAX_TOTAL_RETRY_TIME_MS}ms. Throwing error.`);
291
297
  throw error;
292
298
  }
293
299
  }
@@ -298,14 +304,14 @@ const executeWithRetry = async (operation, context) => {
298
304
  // Fixed exponential sequence: 4s, 8s, 16s, 30s, 60s, 120s, 240s — exactly 7 attempts.
299
305
  // No time budget imposed; all 7 attempts will be made regardless of total elapsed time.
300
306
  if (exponentialAttempt >= RETRY_EXPONENTIAL_SEQUENCE_MS.length) {
301
- console.warn(`[Embedding][Retry] Exhausted all ${RETRY_EXPONENTIAL_SEQUENCE_MS.length} exponential backoff attempts. provider=${context.provider}, model=${context.model || 'unknown'}, status=${status}. Throwing error.`);
307
+ logger.warn(`[Embedding][Retry] Exhausted all ${RETRY_EXPONENTIAL_SEQUENCE_MS.length} exponential backoff attempts. provider=${context.provider}, model=${context.model || 'unknown'}, status=${status}. Throwing error.`);
302
308
  throw error;
303
309
  }
304
310
  waitMs = withJitter(RETRY_EXPONENTIAL_SEQUENCE_MS[exponentialAttempt]);
305
- console.warn(`[Embedding][Retry] provider=${context.provider}, model=${context.model || 'unknown'}, baseURL=${context.baseURL || 'default'}, status=${status}, attempt=${attempt} (exponential ${exponentialAttempt + 1}/${RETRY_EXPONENTIAL_SEQUENCE_MS.length}), waiting=${waitMs}ms`);
311
+ logger.warn(`[Embedding][Retry] provider=${context.provider}, model=${context.model || 'unknown'}, baseURL=${context.baseURL || 'default'}, status=${status}, attempt=${attempt} (exponential ${exponentialAttempt + 1}/${RETRY_EXPONENTIAL_SEQUENCE_MS.length}), waiting=${waitMs}ms`);
306
312
  exponentialAttempt++;
307
313
  }
308
- console.log(`[Embedding][Retry] Attempt ${attempt} failed. Waiting ${waitMs}ms before retry...`);
314
+ logger.log(`[Embedding][Retry] Attempt ${attempt} failed. Waiting ${waitMs}ms before retry...`);
309
315
  await sleep(waitMs);
310
316
  attempt++;
311
317
  }
@@ -322,7 +328,7 @@ const withEmbeddingQueue = (operation) => {
322
328
  const pacingDelayMs = getAdaptivePacingDelayMs();
323
329
  const waitMs = lastEmbeddingCallAt === 0 ? 0 : Math.max(0, pacingDelayMs - elapsed);
324
330
  if (waitMs > 0) {
325
- console.log(`[Embedding][Queue] Pacing wait ${waitMs}ms before next API call`);
331
+ logger.log(`[Embedding][Queue] Pacing wait ${waitMs}ms before next API call`);
326
332
  await sleep(waitMs);
327
333
  }
328
334
  lastEmbeddingCallAt = Date.now();
@@ -334,11 +340,11 @@ const withEmbeddingQueue = (operation) => {
334
340
  };
335
341
  const scheduleFullEmbeddingResync = (reason) => {
336
342
  if (fullResyncScheduled || fullResyncInProgress) {
337
- console.log(`[Embedding] Full embeddings resync already in progress/scheduled. reason=${reason}`);
343
+ logger.log(`[Embedding] Full embeddings resync already in progress/scheduled. reason=${reason}`);
338
344
  return;
339
345
  }
340
346
  fullResyncScheduled = true;
341
- console.warn(`[Embedding] Scheduling full embeddings resync. reason=${reason}`);
347
+ logger.warn(`[Embedding] Scheduling full embeddings resync. reason=${reason}`);
342
348
  setTimeout(async () => {
343
349
  if (fullResyncInProgress) {
344
350
  fullResyncScheduled = false;
@@ -350,7 +356,7 @@ const scheduleFullEmbeddingResync = (reason) => {
350
356
  await syncAllServerToolsEmbeddings();
351
357
  }
352
358
  catch (error) {
353
- console.error('[EMBED_SYNC_ERROR] Full embeddings resync failed', { reason, error });
359
+ logger.error('[EMBED_SYNC_ERROR] Full embeddings resync failed', { reason, error });
354
360
  }
355
361
  finally {
356
362
  fullResyncInProgress = false;
@@ -400,7 +406,7 @@ export async function createVectorIndex(dataSource, dimensions, tableName = 'vec
400
406
  CREATE INDEX ${indexName}
401
407
  ON ${tableName} USING hnsw (${columnName} vector_cosine_ops);
402
408
  `);
403
- console.log(`Created HNSW index for ${dimensions}-dimensional vectors.`);
409
+ logger.log(`Created HNSW index for ${dimensions}-dimensional vectors.`);
404
410
  return {
405
411
  success: true,
406
412
  indexType: 'hnsw',
@@ -409,14 +415,14 @@ export async function createVectorIndex(dataSource, dimensions, tableName = 'vec
409
415
  }
410
416
  catch (error) {
411
417
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
412
- console.warn(`HNSW index creation failed: ${errorMessage}`);
418
+ logger.warn(`HNSW index creation failed: ${errorMessage}`);
413
419
  // Fallback to IVFFlat if HNSW fails (e.g., older pgvector version)
414
420
  try {
415
421
  await dataSource.query(`
416
422
  CREATE INDEX ${indexName}
417
423
  ON ${tableName} USING ivfflat (${columnName} vector_cosine_ops) WITH (lists = 100);
418
424
  `);
419
- console.log(`Created IVFFlat index for ${dimensions}-dimensional vectors (fallback).`);
425
+ logger.log(`Created IVFFlat index for ${dimensions}-dimensional vectors (fallback).`);
420
426
  return {
421
427
  success: true,
422
428
  indexType: 'ivfflat',
@@ -425,7 +431,7 @@ export async function createVectorIndex(dataSource, dimensions, tableName = 'vec
425
431
  }
426
432
  catch (ivfError) {
427
433
  const ivfErrorMessage = ivfError instanceof Error ? ivfError.message : 'Unknown error';
428
- console.warn(`IVFFlat index creation also failed: ${ivfErrorMessage}`);
434
+ logger.warn(`IVFFlat index creation also failed: ${ivfErrorMessage}`);
429
435
  return {
430
436
  success: false,
431
437
  indexType: null,
@@ -442,7 +448,7 @@ export async function createVectorIndex(dataSource, dimensions, tableName = 'vec
442
448
  CREATE INDEX ${indexName}
443
449
  ON ${tableName} USING hnsw ((${columnName}::halfvec(${dimensions})) halfvec_cosine_ops);
444
450
  `);
445
- console.log(`Created HNSW index with halfvec casting for ${dimensions}-dimensional vectors.`);
451
+ logger.log(`Created HNSW index with halfvec casting for ${dimensions}-dimensional vectors.`);
446
452
  return {
447
453
  success: true,
448
454
  indexType: 'hnsw-halfvec',
@@ -455,28 +461,28 @@ export async function createVectorIndex(dataSource, dimensions, tableName = 'vec
455
461
  errorMessage.includes('type does not exist') ||
456
462
  errorMessage.includes('operator class');
457
463
  if (isHalfvecNotSupported) {
458
- console.warn('');
459
- console.warn('═══════════════════════════════════════════════════════════════════════════');
460
- console.warn(' ⚠️ HIGH-DIMENSIONAL EMBEDDING INDEX WARNING');
461
- console.warn('═══════════════════════════════════════════════════════════════════════════');
462
- console.warn(` Your embeddings have ${dimensions} dimensions, which requires halfvec support.`);
463
- console.warn('');
464
- console.warn(' pgvector dimension limits:');
465
- console.warn(` - vector type: max ${VECTOR_MAX_DIMENSIONS} dimensions`);
466
- console.warn(` - halfvec type: max ${HALFVEC_MAX_DIMENSIONS} dimensions (pgvector 0.7.0+)`);
467
- console.warn('');
468
- console.warn(' RECOMMENDATIONS:');
469
- console.warn(' 1. Upgrade pgvector to >= 0.7.0 for halfvec support');
470
- console.warn(' 2. Or use a smaller embedding model:');
471
- console.warn(' - text-embedding-3-small (1536 dimensions) instead of text-embedding-3-large');
472
- console.warn(' - bge-m3 (1024 dimensions)');
473
- console.warn('');
474
- console.warn(' Vector search will work but may be slower without an optimized index.');
475
- console.warn('═══════════════════════════════════════════════════════════════════════════');
476
- console.warn('');
464
+ logger.warn('');
465
+ logger.warn('═══════════════════════════════════════════════════════════════════════════');
466
+ logger.warn(' ⚠️ HIGH-DIMENSIONAL EMBEDDING INDEX WARNING');
467
+ logger.warn('═══════════════════════════════════════════════════════════════════════════');
468
+ logger.warn(` Your embeddings have ${dimensions} dimensions, which requires halfvec support.`);
469
+ logger.warn('');
470
+ logger.warn(' pgvector dimension limits:');
471
+ logger.warn(` - vector type: max ${VECTOR_MAX_DIMENSIONS} dimensions`);
472
+ logger.warn(` - halfvec type: max ${HALFVEC_MAX_DIMENSIONS} dimensions (pgvector 0.7.0+)`);
473
+ logger.warn('');
474
+ logger.warn(' RECOMMENDATIONS:');
475
+ logger.warn(' 1. Upgrade pgvector to >= 0.7.0 for halfvec support');
476
+ logger.warn(' 2. Or use a smaller embedding model:');
477
+ logger.warn(' - text-embedding-3-small (1536 dimensions) instead of text-embedding-3-large');
478
+ logger.warn(' - bge-m3 (1024 dimensions)');
479
+ logger.warn('');
480
+ logger.warn(' Vector search will work but may be slower without an optimized index.');
481
+ logger.warn('═══════════════════════════════════════════════════════════════════════════');
482
+ logger.warn('');
477
483
  }
478
484
  else {
479
- console.warn(`HNSW halfvec index creation failed: ${errorMessage}`);
485
+ logger.warn(`HNSW halfvec index creation failed: ${errorMessage}`);
480
486
  }
481
487
  return {
482
488
  success: false,
@@ -486,24 +492,24 @@ export async function createVectorIndex(dataSource, dimensions, tableName = 'vec
486
492
  }
487
493
  }
488
494
  // Strategy 3: For dimensions > 4000, no index is supported
489
- console.warn('');
490
- console.warn('═══════════════════════════════════════════════════════════════════════════');
491
- console.warn(' ⚠️ EMBEDDING DIMENSIONS EXCEED INDEX LIMITS');
492
- console.warn('═══════════════════════════════════════════════════════════════════════════');
493
- console.warn(` Your embeddings have ${dimensions} dimensions, which exceeds all limits:`);
494
- console.warn(` - vector type: max ${VECTOR_MAX_DIMENSIONS} dimensions`);
495
- console.warn(` - halfvec type: max ${HALFVEC_MAX_DIMENSIONS} dimensions`);
496
- console.warn('');
497
- console.warn(' RECOMMENDATIONS:');
498
- console.warn(' 1. Use a smaller embedding model:');
499
- console.warn(' - text-embedding-3-small (1536 dimensions)');
500
- console.warn(' - text-embedding-3-large (3072 dimensions) with halfvec');
501
- console.warn(' - bge-m3 (1024 dimensions)');
502
- console.warn(' 2. Or use dimensionality reduction (PCA) to reduce vector size');
503
- console.warn('');
504
- console.warn(' Vector search will work but will be slow without an index.');
505
- console.warn('═══════════════════════════════════════════════════════════════════════════');
506
- console.warn('');
495
+ logger.warn('');
496
+ logger.warn('═══════════════════════════════════════════════════════════════════════════');
497
+ logger.warn(' ⚠️ EMBEDDING DIMENSIONS EXCEED INDEX LIMITS');
498
+ logger.warn('═══════════════════════════════════════════════════════════════════════════');
499
+ logger.warn(` Your embeddings have ${dimensions} dimensions, which exceeds all limits:`);
500
+ logger.warn(` - vector type: max ${VECTOR_MAX_DIMENSIONS} dimensions`);
501
+ logger.warn(` - halfvec type: max ${HALFVEC_MAX_DIMENSIONS} dimensions`);
502
+ logger.warn('');
503
+ logger.warn(' RECOMMENDATIONS:');
504
+ logger.warn(' 1. Use a smaller embedding model:');
505
+ logger.warn(' - text-embedding-3-small (1536 dimensions)');
506
+ logger.warn(' - text-embedding-3-large (3072 dimensions) with halfvec');
507
+ logger.warn(' - bge-m3 (1024 dimensions)');
508
+ logger.warn(' 2. Or use dimensionality reduction (PCA) to reduce vector size');
509
+ logger.warn('');
510
+ logger.warn(' Vector search will work but will be slow without an index.');
511
+ logger.warn('═══════════════════════════════════════════════════════════════════════════');
512
+ logger.warn('');
507
513
  return {
508
514
  success: false,
509
515
  indexType: null,
@@ -568,7 +574,7 @@ async function generateEmbedding(text) {
568
574
  if (provider === 'azure_openai') {
569
575
  const azureConfig = getAzureOpenAIConfig(smartRoutingConfig);
570
576
  if (!azureConfig.endpoint || !azureConfig.apiKey) {
571
- console.warn('Azure OpenAI endpoint/key not configured. Using fallback embedding method.');
577
+ logger.warn('Azure OpenAI endpoint/key not configured. Using fallback embedding method.');
572
578
  return generateFallbackEmbedding(text);
573
579
  }
574
580
  try {
@@ -580,7 +586,7 @@ async function generateEmbedding(text) {
580
586
  }
581
587
  catch (error) {
582
588
  const status = extractErrorStatus(error);
583
- console.warn('Azure OpenAI embeddings request failed after retries', {
589
+ logger.warn('Azure OpenAI embeddings request failed after retries', {
584
590
  status: status ?? 'unknown',
585
591
  endpoint: azureConfig.endpoint || 'missing',
586
592
  deployment: azureConfig.embeddingDeployment || 'missing',
@@ -594,7 +600,7 @@ async function generateEmbedding(text) {
594
600
  const openai = await getOpenAIClient();
595
601
  // Check if API key is configured
596
602
  if (!openai.apiKey) {
597
- console.warn('OpenAI API key is not configured. Using fallback embedding method.');
603
+ logger.warn('OpenAI API key is not configured. Using fallback embedding method.');
598
604
  return generateFallbackEmbedding(text);
599
605
  }
600
606
  // Truncate text to the model's token limit using precise tokenization.
@@ -610,12 +616,12 @@ async function generateEmbedding(text) {
610
616
  truncatedText = await truncateToTokenLimit(text, maxTokens, config.embeddingModel, config.apiKey);
611
617
  }
612
618
  catch (truncationError) {
613
- console.warn(`Token truncation failed for model ${config.embeddingModel}: ${truncationError?.message ?? String(truncationError)}. Falling back to character-based truncation.`);
619
+ logger.warn(`Token truncation failed for model ${config.embeddingModel}: ${truncationError?.message ?? String(truncationError)}. Falling back to character-based truncation.`);
614
620
  // As a fallback, use the shared conservative character-based heuristic (~3 chars/token)
615
621
  // to prevent oversized text from causing a failure in the embedding API call.
616
622
  truncatedText = truncateWithHeuristic(text, maxTokens);
617
623
  }
618
- console.debug(`[Embedding] Truncation: ${text.length} → ${truncatedText.length} chars (${Date.now() - _truncateStart}ms, maxTokens=${maxTokens})`);
624
+ logger.debug(`[Embedding] Truncation: ${text.length} → ${truncatedText.length} chars (${Date.now() - _truncateStart}ms, maxTokens=${maxTokens})`);
619
625
  // Determine encoding format based on configuration
620
626
  const encodingFormatSetting = smartRoutingConfig.embeddingEncodingFormat || 'auto';
621
627
  let encodingFormat;
@@ -633,7 +639,7 @@ async function generateEmbedding(text) {
633
639
  };
634
640
  if (process.env.DEBUG === 'true') {
635
641
  const debugCurl = buildEmbeddingsDebugCurl(config.baseURL, embeddingPayload);
636
- console.log(`[Embedding] HTTP request details: ${JSON.stringify({
642
+ logger.log(`[Embedding] HTTP request details: ${JSON.stringify({
637
643
  url: `${(config.baseURL || 'https://api.openai.com/v1').replace(/\/+$/, '')}/embeddings`,
638
644
  method: 'POST',
639
645
  headers: {
@@ -642,9 +648,9 @@ async function generateEmbedding(text) {
642
648
  },
643
649
  payload: embeddingPayload,
644
650
  }, null, 2)}`);
645
- console.log(`[Embedding] Reproducible curl (copy/paste and replace <YOUR_API_KEY>):\n${debugCurl}`);
651
+ logger.log(`[Embedding] Reproducible curl (copy/paste and replace <YOUR_API_KEY>):\n${debugCurl}`);
646
652
  }
647
- console.debug(`[Embedding] API request → model=${config.embeddingModel}, encoding_format=${encodingFormat}, input_length=${truncatedText.length} chars | input_preview: "${truncatedText.substring(0, 200).replace(/\s+/g, ' ')}"`);
653
+ logger.debug(`[Embedding] API request → model=${config.embeddingModel}, encoding_format=${encodingFormat}, input_length=${truncatedText.length} chars | input_preview: "${truncatedText.substring(0, 200).replace(/\s+/g, ' ')}"`);
648
654
  const _requestStart = Date.now();
649
655
  try {
650
656
  // Call OpenAI-compatible embeddings API with conservative retry/backoff policy.
@@ -657,7 +663,7 @@ async function generateEmbedding(text) {
657
663
  model: config.embeddingModel,
658
664
  baseURL: config.baseURL,
659
665
  }));
660
- console.debug(`[Embedding] API response OK in ${Date.now() - _requestStart}ms`);
666
+ logger.debug(`[Embedding] API response OK in ${Date.now() - _requestStart}ms`);
661
667
  if (encodingFormat === 'base64' && typeof response.data[0].embedding === 'string') {
662
668
  const embeddingBase64Str = response.data[0].embedding;
663
669
  return toFloat32Array(embeddingBase64Str);
@@ -667,7 +673,7 @@ async function generateEmbedding(text) {
667
673
  }
668
674
  catch (error) {
669
675
  const status = extractErrorStatus(error);
670
- console.warn('OpenAI-compatible embeddings request failed after retries', {
676
+ logger.warn('OpenAI-compatible embeddings request failed after retries', {
671
677
  status: status ?? 'unknown',
672
678
  baseURL: config.baseURL || 'default',
673
679
  model: config.embeddingModel || 'default',
@@ -801,7 +807,15 @@ const buildToolSetHash = (tools) => {
801
807
  inputSchema: tool.inputSchema || null,
802
808
  }))
803
809
  .sort((a, b) => a.name.localeCompare(b.name));
804
- return createHash('sha256').update(stableHashSerialize(normalized)).digest('hex');
810
+ // Derive the cache key with a memory-hard KDF (scrypt) rather than a bare
811
+ // digest: inputs may embed configuration-derived content, so a deliberately
812
+ // expensive keyed derivation is the appropriate construction. Parameters
813
+ // are tuned down (~2ms) because this runs on tool-set refreshes only.
814
+ return scryptSync(stableHashSerialize(normalized), TOOLSET_HASH_KEY, 32, {
815
+ N: 2048,
816
+ r: 8,
817
+ p: 1,
818
+ }).toString('hex');
805
819
  };
806
820
  const buildServerSearchableText = (serverName, description) => [serverName, description || ''].filter(Boolean).join(' ');
807
821
  const parseEmbeddingMetadata = (metadata) => {
@@ -813,7 +827,7 @@ const parseEmbeddingMetadata = (metadata) => {
813
827
  return JSON.parse(metadata);
814
828
  }
815
829
  catch (error) {
816
- console.error('Error parsing vector embedding metadata string', safeStringify({ error }));
830
+ logger.error('Error parsing vector embedding metadata string', safeStringify({ error }));
817
831
  return null;
818
832
  }
819
833
  }
@@ -865,7 +879,7 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
865
879
  }
866
880
  // Ensure database is initialized before starting
867
881
  if (!isDatabaseConnected()) {
868
- console.log('Database not initialized, initializing...');
882
+ logger.log('Database not initialized, initializing...');
869
883
  await initializeDatabase();
870
884
  }
871
885
  const config = await getOpenAIConfig();
@@ -891,7 +905,7 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
891
905
  const skipCheckRepo = getRepositoryFactory('vectorEmbeddings')();
892
906
  const existingCount = await skipCheckRepo.countByServerNameAndModel(serverName, persistedEmbeddingModel);
893
907
  if (existingCount !== tools.length) {
894
- console.log(`[Embedding] [${serverName}] Generating embeddings: existing=${existingCount}, expected=${tools.length} (model=${persistedEmbeddingModel}, hash=${expectedToolSetHash.substring(0, 12)})`);
908
+ logger.log(`[Embedding] [${serverName}] Generating embeddings: existing=${existingCount}, expected=${tools.length} (model=${persistedEmbeddingModel}, hash=${expectedToolSetHash.substring(0, 12)})`);
895
909
  }
896
910
  else {
897
911
  const existingIdentities = await skipCheckRepo.getToolIdentityByServerNameAndModel(serverName, persistedEmbeddingModel);
@@ -909,14 +923,14 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
909
923
  serverEmbStatus.text_content === serverSearchableText &&
910
924
  serverEmbStatus.hasEmbedding === true;
911
925
  if (hasExactContentIds && hasMatchingToolSetHash && hasCurrentServerEmbedding) {
912
- console.log(`[Embedding] [${serverName}] Skipping — tool set already up-to-date (model=${persistedEmbeddingModel}, hash=${expectedToolSetHash.substring(0, 12)})`);
926
+ logger.log(`[Embedding] [${serverName}] Skipping — tool set already up-to-date (model=${persistedEmbeddingModel}, hash=${expectedToolSetHash.substring(0, 12)})`);
913
927
  return;
914
928
  }
915
- console.log(`[Embedding] [${serverName}] Generating embeddings: existing=${existingCount}, expected=${tools.length} (model=${persistedEmbeddingModel}, hash=${expectedToolSetHash.substring(0, 12)})`);
929
+ logger.log(`[Embedding] [${serverName}] Generating embeddings: existing=${existingCount}, expected=${tools.length} (model=${persistedEmbeddingModel}, hash=${expectedToolSetHash.substring(0, 12)})`);
916
930
  }
917
931
  }
918
932
  catch (skipCheckError) {
919
- console.warn(`[Embedding] [${serverName}] Skip check failed, proceeding with full sync: ${skipCheckError?.message ?? skipCheckError}`);
933
+ logger.warn(`[Embedding] [${serverName}] Skip check failed, proceeding with full sync: ${skipCheckError?.message ?? skipCheckError}`);
920
934
  }
921
935
  }
922
936
  // ── Phase 1: Generate all embeddings in memory (no DB access) ──────────────
@@ -946,7 +960,7 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
946
960
  ]
947
961
  .filter(Boolean)
948
962
  .join(' ');
949
- console.debug(`[Embedding] [${serverName}] Tool ${_toolIdx + 1}/${tools.length}: "${tool.name}" | raw text: ${searchableText.length} chars | preview: "${searchableText.substring(0, 200).replace(/\s+/g, ' ')}"`);
963
+ logger.debug(`[Embedding] [${serverName}] Tool ${_toolIdx + 1}/${tools.length}: "${tool.name}" | raw text: ${searchableText.length} chars | preview: "${searchableText.substring(0, 200).replace(/\s+/g, ' ')}"`);
950
964
  try {
951
965
  const embedding = await generateEmbedding(searchableText);
952
966
  toolEmbeddings.push({ tool, searchableText, embedding });
@@ -954,7 +968,7 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
954
968
  }
955
969
  catch (error) {
956
970
  const status = extractErrorStatus(error);
957
- console.warn('[EMBED_SYNC_ERROR] Failed while embedding tool', {
971
+ logger.warn('[EMBED_SYNC_ERROR] Failed while embedding tool', {
958
972
  serverName,
959
973
  toolName: tool.name,
960
974
  status: status ?? 'unknown',
@@ -970,7 +984,7 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
970
984
  }
971
985
  catch (error) {
972
986
  const status = extractErrorStatus(error);
973
- console.warn('[EMBED_SYNC_ERROR] Failed while embedding server metadata', {
987
+ logger.warn('[EMBED_SYNC_ERROR] Failed while embedding server metadata', {
974
988
  serverName,
975
989
  status: status ?? 'unknown',
976
990
  error: summarizeErrorForLogging(error),
@@ -982,7 +996,7 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
982
996
  // Probe the connection before writing; reconnect if it went stale during the
983
997
  // (potentially long) embedding-generation phase above.
984
998
  if (!isDatabaseConnected()) {
985
- console.info('Database connection lost during embedding generation, reinitializing...');
999
+ logger.info('Database connection lost during embedding generation, reinitializing...');
986
1000
  await initializeDatabase();
987
1001
  }
988
1002
  else {
@@ -990,7 +1004,7 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
990
1004
  await getAppDataSource().query('SELECT 1');
991
1005
  }
992
1006
  catch {
993
- console.warn('DB connection stale after embedding generation for server %s — reconnecting...', serverName);
1007
+ logger.warn('DB connection stale after embedding generation for server %s — reconnecting...', serverName);
994
1008
  await reconnectDatabase();
995
1009
  }
996
1010
  }
@@ -1016,7 +1030,7 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
1016
1030
  const currentContentIds = toolEmbeddings.map(({ tool }) => `${serverName}:${tool.name}`);
1017
1031
  const staleCount = await vectorRepository.deleteStaleToolEmbeddings(serverName, currentContentIds, persistedEmbeddingModel);
1018
1032
  if (staleCount > 0) {
1019
- console.log(`[Embedding] [${serverName}] Removed ${staleCount} stale tool embedding(s)`);
1033
+ logger.log(`[Embedding] [${serverName}] Removed ${staleCount} stale tool embedding(s)`);
1020
1034
  }
1021
1035
  }
1022
1036
  await vectorRepository.saveEmbedding('server', serverName, serverSearchableText, serverEmbedding, {
@@ -1027,13 +1041,13 @@ export const saveToolsAsVectorEmbeddings = async (serverName, tools, options = {
1027
1041
  if (vectorDimensionsReset) {
1028
1042
  scheduleFullEmbeddingResync(`Vector dimensions changed while syncing server "${serverName}"`);
1029
1043
  }
1030
- console.log('Saved tool embeddings', safeStringify({ serverName, toolCount: tools.length }));
1044
+ logger.log('Saved tool embeddings', safeStringify({ serverName, toolCount: tools.length }));
1031
1045
  }
1032
1046
  catch (error) {
1033
1047
  if (shouldReport && !progressErrorEmitted) {
1034
1048
  emitProgress(lastProgressCurrent, 'error');
1035
1049
  }
1036
- console.error('Error saving tool embeddings', safeStringify({ serverName, error }));
1050
+ logger.error('Error saving tool embeddings', safeStringify({ serverName, error }));
1037
1051
  throw error;
1038
1052
  }
1039
1053
  };
@@ -1114,7 +1128,7 @@ export const searchToolsByVector = async (query, limit = 10, threshold = 0.7, se
1114
1128
  .sort((a, b) => b.similarity - a.similarity);
1115
1129
  }
1116
1130
  catch (error) {
1117
- console.error('Error searching tools by vector', safeStringify({ query, limit, threshold, error }));
1131
+ logger.error('Error searching tools by vector', safeStringify({ query, limit, threshold, error }));
1118
1132
  return [];
1119
1133
  }
1120
1134
  };
@@ -1148,7 +1162,7 @@ export const getAllVectorizedTools = async (serverNames) => {
1148
1162
  }
1149
1163
  }
1150
1164
  catch (error) {
1151
- console.warn('Could not determine vector dimensions from database', {
1165
+ logger.warn('Could not determine vector dimensions from database', {
1152
1166
  error: error?.message,
1153
1167
  });
1154
1168
  }
@@ -1186,7 +1200,7 @@ export const getAllVectorizedTools = async (serverNames) => {
1186
1200
  };
1187
1201
  }
1188
1202
  catch (error) {
1189
- console.error('Error parsing vector embedding metadata string', safeStringify({ error }));
1203
+ logger.error('Error parsing vector embedding metadata string', safeStringify({ error }));
1190
1204
  return {
1191
1205
  serverName: 'unknown',
1192
1206
  toolName: 'unknown',
@@ -1204,7 +1218,7 @@ export const getAllVectorizedTools = async (serverNames) => {
1204
1218
  });
1205
1219
  }
1206
1220
  catch (error) {
1207
- console.error('Error getting all vectorized tools', safeStringify({ error, serverNames }));
1221
+ logger.error('Error getting all vectorized tools', safeStringify({ error, serverNames }));
1208
1222
  return [];
1209
1223
  }
1210
1224
  };
@@ -1216,22 +1230,22 @@ export const removeServerToolEmbeddings = async (serverName) => {
1216
1230
  try {
1217
1231
  const smartRoutingConfig = await getSmartRoutingConfig();
1218
1232
  if (!smartRoutingConfig.dbUrl && !process.env.DB_URL) {
1219
- console.warn('Skipping embedding cleanup because DB URL is not configured', {
1233
+ logger.warn('Skipping embedding cleanup because DB URL is not configured', {
1220
1234
  serverName,
1221
1235
  });
1222
1236
  return;
1223
1237
  }
1224
1238
  // Ensure database is initialized before using repository
1225
1239
  if (!isDatabaseConnected()) {
1226
- console.info('Database not initialized, initializing...');
1240
+ logger.info('Database not initialized, initializing...');
1227
1241
  await initializeDatabase();
1228
1242
  }
1229
1243
  const vectorRepository = getRepositoryFactory('vectorEmbeddings')();
1230
1244
  const removedCount = await vectorRepository.deleteByServerName(serverName);
1231
- console.log('Removed server embeddings', safeStringify({ serverName, removedCount }));
1245
+ logger.log('Removed server embeddings', safeStringify({ serverName, removedCount }));
1232
1246
  }
1233
1247
  catch (error) {
1234
- console.error('Error removing server embeddings', safeStringify({ serverName, error }));
1248
+ logger.error('Error removing server embeddings', safeStringify({ serverName, error }));
1235
1249
  }
1236
1250
  };
1237
1251
  /**
@@ -1240,7 +1254,7 @@ export const removeServerToolEmbeddings = async (serverName) => {
1240
1254
  */
1241
1255
  export const syncAllServerToolsEmbeddings = async () => {
1242
1256
  try {
1243
- console.log('Starting synchronization of all server tool embeddings');
1257
+ logger.log('Starting synchronization of all server tool embeddings');
1244
1258
  // Import getServersInfo to get all server information
1245
1259
  const { getServersInfo } = await import('./mcpService.js');
1246
1260
  const servers = await getServersInfo();
@@ -1249,7 +1263,7 @@ export const syncAllServerToolsEmbeddings = async () => {
1249
1263
  for (const server of servers) {
1250
1264
  if (server.status === 'connected' && server.tools && server.tools.length > 0) {
1251
1265
  try {
1252
- console.log('Syncing tool embeddings for server', {
1266
+ logger.log('Syncing tool embeddings for server', {
1253
1267
  serverName: server.name,
1254
1268
  toolCount: server.tools.length,
1255
1269
  });
@@ -1258,30 +1272,30 @@ export const syncAllServerToolsEmbeddings = async () => {
1258
1272
  serversSynced++;
1259
1273
  }
1260
1274
  catch (error) {
1261
- console.warn(`[EMBED_SYNC_ERROR] Failed to sync tool embeddings for server "${server.name}"`);
1262
- console.error('Failed to sync tool embeddings for server', safeStringify({
1275
+ logger.warn(`[EMBED_SYNC_ERROR] Failed to sync tool embeddings for server "${server.name}"`);
1276
+ logger.error('Failed to sync tool embeddings for server', safeStringify({
1263
1277
  serverName: server.name,
1264
1278
  error,
1265
1279
  }));
1266
1280
  }
1267
1281
  }
1268
1282
  else if (server.status === 'connected' && (!server.tools || server.tools.length === 0)) {
1269
- console.log('Connected server has no tools to sync', safeStringify({ serverName: server.name }));
1283
+ logger.log('Connected server has no tools to sync', safeStringify({ serverName: server.name }));
1270
1284
  }
1271
1285
  else {
1272
- console.log('Skipping server during tool embedding sync', {
1286
+ logger.log('Skipping server during tool embedding sync', {
1273
1287
  serverName: server.name,
1274
1288
  status: server.status,
1275
1289
  });
1276
1290
  }
1277
1291
  }
1278
- console.log('Completed smart routing tool embedding sync', {
1292
+ logger.log('Completed smart routing tool embedding sync', {
1279
1293
  totalToolsSynced,
1280
1294
  serversSynced,
1281
1295
  });
1282
1296
  }
1283
1297
  catch (error) {
1284
- console.error('Error during smart routing tool embedding synchronization', { error });
1298
+ logger.error('Error during smart routing tool embedding synchronization', { error });
1285
1299
  throw error;
1286
1300
  }
1287
1301
  };
@@ -1294,7 +1308,7 @@ async function checkDatabaseVectorDimensions(dimensionsNeeded) {
1294
1308
  try {
1295
1309
  // First check if database is initialized
1296
1310
  if (!getAppDataSource().isInitialized) {
1297
- console.info('Database not initialized, initializing...');
1311
+ logger.info('Database not initialized, initializing...');
1298
1312
  await initializeDatabase();
1299
1313
  }
1300
1314
  // Check current vector dimension in the database
@@ -1311,7 +1325,7 @@ async function checkDatabaseVectorDimensions(dimensionsNeeded) {
1311
1325
  `);
1312
1326
  }
1313
1327
  catch (error) {
1314
- console.warn('Could not get vector type info, falling back to atttypmod query');
1328
+ logger.warn('Could not get vector type info, falling back to atttypmod query');
1315
1329
  }
1316
1330
  // Fallback to original query
1317
1331
  const result = await getAppDataSource().query(`
@@ -1360,19 +1374,19 @@ async function checkDatabaseVectorDimensions(dimensionsNeeded) {
1360
1374
  }
1361
1375
  }
1362
1376
  catch (error) {
1363
- console.warn('Could not check vector dimensions from actual records', { error });
1377
+ logger.warn('Could not check vector dimensions from actual records', { error });
1364
1378
  }
1365
1379
  // If no dimensions are set or they don't match what we need, handle the mismatch
1366
1380
  if (currentDimensions === 0 || currentDimensions !== dimensionsNeeded) {
1367
- console.log('Vector dimensions mismatch detected', {
1381
+ logger.log('Vector dimensions mismatch detected', {
1368
1382
  currentDimensions,
1369
1383
  dimensionsNeeded,
1370
1384
  });
1371
1385
  if (currentDimensions === 0) {
1372
- console.log('Setting up vector dimensions for the first time...');
1386
+ logger.log('Setting up vector dimensions for the first time...');
1373
1387
  }
1374
1388
  else {
1375
- console.log('Dimension mismatch detected. Clearing existing incompatible vector data...');
1389
+ logger.log('Dimension mismatch detected. Clearing existing incompatible vector data...');
1376
1390
  // Clear all existing vector embeddings with mismatched dimensions
1377
1391
  await clearMismatchedVectorData(dimensionsNeeded);
1378
1392
  }
@@ -1387,14 +1401,14 @@ async function checkDatabaseVectorDimensions(dimensionsNeeded) {
1387
1401
  await getAppDataSource().query(`DROP INDEX IF EXISTS idx_vector_embeddings_embedding;`);
1388
1402
  }
1389
1403
  catch (dropError) {
1390
- console.warn('Could not drop existing vector index before ALTER', {
1404
+ logger.warn('Could not drop existing vector index before ALTER', {
1391
1405
  error: dropError?.message,
1392
1406
  });
1393
1407
  }
1394
1408
  // Alter the column type with the new dimensions
1395
1409
  // Use halfvec for dimensions > 2000, vector otherwise
1396
1410
  const vectorType = dimensionsNeeded <= VECTOR_MAX_DIMENSIONS ? 'vector' : 'halfvec';
1397
- console.log('Using vector storage type for configured dimensions', {
1411
+ logger.log('Using vector storage type for configured dimensions', {
1398
1412
  vectorType,
1399
1413
  dimensionsNeeded,
1400
1414
  });
@@ -1405,9 +1419,9 @@ async function checkDatabaseVectorDimensions(dimensionsNeeded) {
1405
1419
  // Create appropriate vector index using the helper function
1406
1420
  const result = await createVectorIndex(getAppDataSource(), dimensionsNeeded);
1407
1421
  if (!result.success) {
1408
- console.log('Continuing without optimized vector index...');
1422
+ logger.log('Continuing without optimized vector index...');
1409
1423
  }
1410
- console.log('Successfully configured vector dimensions', { dimensionsNeeded });
1424
+ logger.log('Successfully configured vector dimensions', { dimensionsNeeded });
1411
1425
  // Only signal that a full resync is needed when existing data was cleared due
1412
1426
  // to a real dimension change. When currentDimensions === 0 it is a first-time
1413
1427
  // setup — there are no stale embeddings to re-generate.
@@ -1416,7 +1430,7 @@ async function checkDatabaseVectorDimensions(dimensionsNeeded) {
1416
1430
  return false;
1417
1431
  }
1418
1432
  catch (error) {
1419
- console.error('Error checking or updating vector dimensions', { error });
1433
+ logger.error('Error checking or updating vector dimensions', { error });
1420
1434
  throw new Error(`Vector dimension check failed: ${error?.message || 'Unknown error'}`);
1421
1435
  }
1422
1436
  }
@@ -1427,16 +1441,16 @@ async function checkDatabaseVectorDimensions(dimensionsNeeded) {
1427
1441
  */
1428
1442
  async function clearMismatchedVectorData(expectedDimensions) {
1429
1443
  try {
1430
- console.log(`Clearing vector embeddings with dimensions different from ${expectedDimensions}...`);
1444
+ logger.log(`Clearing vector embeddings with dimensions different from ${expectedDimensions}...`);
1431
1445
  // Delete all embeddings that don't match the expected dimensions
1432
1446
  await getAppDataSource().query(`
1433
1447
  DELETE FROM vector_embeddings
1434
1448
  WHERE dimensions != $1
1435
1449
  `, [expectedDimensions]);
1436
- console.log('Successfully cleared mismatched vector embeddings');
1450
+ logger.log('Successfully cleared mismatched vector embeddings');
1437
1451
  }
1438
1452
  catch (error) {
1439
- console.error('Error clearing mismatched vector data:', error);
1453
+ logger.error('Error clearing mismatched vector data:', error);
1440
1454
  throw error;
1441
1455
  }
1442
1456
  }