@loop_ouroboros/mcp-hub-lite 1.0.1 → 1.1.0
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/CHANGELOG.md +47 -0
- package/dist/client/assets/{HomeView-Cr1jX73N.js → HomeView-Bu2joUvW.js} +1 -1
- package/dist/client/assets/ResourceDetailView-BvrhDCD1.js +1 -0
- package/dist/client/assets/ResourceDetailView-DUJZbegl.css +1 -0
- package/dist/client/assets/ResourcesView-Cc8RHtia.css +1 -0
- package/dist/client/assets/ResourcesView-LjqioF_s.js +1 -0
- package/dist/client/assets/ServerDashboard-BfLeFDGw.css +1 -0
- package/dist/client/assets/ServerDashboard-FhHJFvUi.js +1 -0
- package/dist/client/assets/ServerDetail-BKV-M4qT.js +2 -0
- package/dist/client/assets/ServerDetail-CtnNKJGx.css +1 -0
- package/dist/client/assets/{ServerListView-Bws09jNR.css → ServerListView-B-bPljsO.css} +1 -1
- package/dist/client/assets/ServerListView-BXgtDyt3.js +36 -0
- package/dist/client/assets/ServerStatusTags.vue_vue_type_script_setup_true_lang-D-ooYNdN.js +1 -0
- package/dist/client/assets/SettingsView-CMFG91Z4.js +1 -0
- package/dist/client/assets/SettingsView-GkBOKL0V.css +1 -0
- package/dist/client/assets/ToolCallDialog-Bf4Xe4gH.js +1 -0
- package/dist/client/assets/ToolsView-DFpha1z0.js +1 -0
- package/dist/client/assets/_baseClone-Bp9Rjwd7.js +1 -0
- package/dist/client/assets/el-form-item-B4LbJ6OO.css +1 -0
- package/dist/client/assets/el-form-item-DdSUWYsl.js +12 -0
- package/dist/client/assets/el-input-99gMrutP.js +1 -0
- package/dist/client/assets/el-input-BH4BZKnG.css +1 -0
- package/dist/client/assets/{el-loading-Csv24uBk.js → el-loading-CIQ5pD5u.js} +1 -1
- package/dist/client/assets/el-overlay-BVM6msGX.js +1 -0
- package/dist/client/assets/{el-select-C0U_l4IZ.css → el-overlay-CBvdpA69.css} +1 -1
- package/dist/client/assets/{ResourceDetailView-BdOaL_-o.css → el-radio-group-B0bauIRR.css} +1 -1
- package/dist/client/assets/el-radio-group-DhXWy7ry.js +1 -0
- package/dist/client/assets/el-skeleton-item-BLY1jEuR.css +1 -0
- package/dist/client/assets/el-skeleton-item-DJz-Us12.js +1 -0
- package/dist/client/assets/el-switch-BBrS-_6y.css +1 -0
- package/dist/client/assets/el-switch-Bu8AQ5uM.js +1 -0
- package/dist/client/assets/el-tab-pane-BnGMaV56.js +1 -0
- package/dist/client/assets/el-table-column-BMWOaLS_.js +1 -0
- package/dist/client/assets/el-table-column-BdvRS9Y2.css +1 -0
- package/dist/client/assets/index-C2V-ZGji.js +1 -0
- package/dist/client/assets/{index-BsDWtoIl.css → index-DpH6ZSbs.css} +1 -1
- package/dist/client/assets/index-vhkqgpmN.js +2 -0
- package/dist/client/assets/omit-CqPQN3XP.js +1 -0
- package/dist/client/assets/{raf-DDfJOMYh.js → raf-C2wXzaVU.js} +1 -1
- package/dist/client/assets/{vue-vendor-6ny5zj9i.js → vue-vendor-BLHLXXJK.js} +1 -1
- package/dist/client/index.html +3 -3
- package/dist/server/shared/models/resource.model.d.ts +2 -1
- package/dist/server/shared/models/resource.model.d.ts.map +1 -1
- package/dist/server/shared/models/server.model.d.ts +363 -5
- package/dist/server/shared/models/server.model.d.ts.map +1 -1
- package/dist/server/shared/models/server.model.js +220 -1
- package/dist/server/shared/models/session.model.d.ts +2 -56
- package/dist/server/shared/models/session.model.d.ts.map +1 -1
- package/dist/server/shared/models/session.model.js +2 -55
- package/dist/server/shared/models/tool.model.d.ts +4 -2
- package/dist/server/shared/models/tool.model.d.ts.map +1 -1
- package/dist/server/shared/types/client.types.d.ts +4 -32
- package/dist/server/shared/types/client.types.d.ts.map +1 -1
- package/dist/server/shared/types/client.types.js +3 -2
- package/dist/server/shared/types/index.d.ts +3 -3
- package/dist/server/shared/types/index.d.ts.map +1 -1
- package/dist/server/shared/types/index.js +3 -3
- package/dist/server/shared/types/session-context.types.d.ts +35 -0
- package/dist/server/shared/types/session-context.types.d.ts.map +1 -0
- package/dist/server/shared/types/session-context.types.js +5 -0
- package/dist/server/shared/types/websocket.types.d.ts +17 -10
- package/dist/server/shared/types/websocket.types.d.ts.map +1 -1
- package/dist/server/src/api/mcp/debug-response-wrapper.d.ts.map +1 -1
- package/dist/server/src/api/mcp/debug-response-wrapper.js +26 -1
- package/dist/server/src/api/mcp/gateway.d.ts +1 -3
- package/dist/server/src/api/mcp/gateway.d.ts.map +1 -1
- package/dist/server/src/api/mcp/gateway.js +34 -61
- package/dist/server/src/api/mcp/session-context-extractor.d.ts +5 -5
- package/dist/server/src/api/mcp/session-context-extractor.d.ts.map +1 -1
- package/dist/server/src/api/mcp/session-context-extractor.js +15 -39
- package/dist/server/src/api/web/clients.js +2 -2
- package/dist/server/src/api/web/hub-tools.d.ts +2 -2
- package/dist/server/src/api/web/hub-tools.d.ts.map +1 -1
- package/dist/server/src/api/web/hub-tools.js +3 -54
- package/dist/server/src/api/web/mcp-status.d.ts +1 -1
- package/dist/server/src/api/web/mcp-status.d.ts.map +1 -1
- package/dist/server/src/api/web/mcp-status.js +71 -30
- package/dist/server/src/api/web/resources.d.ts.map +1 -1
- package/dist/server/src/api/web/resources.js +28 -22
- package/dist/server/src/api/web/search.d.ts +2 -16
- package/dist/server/src/api/web/search.d.ts.map +1 -1
- package/dist/server/src/api/web/search.js +24 -45
- package/dist/server/src/api/web/servers.d.ts +3 -3
- package/dist/server/src/api/web/servers.d.ts.map +1 -1
- package/dist/server/src/api/web/servers.js +70 -25
- package/dist/server/src/api/web/sessions.js +1 -1
- package/dist/server/src/api/ws/ws-handler.d.ts.map +1 -1
- package/dist/server/src/api/ws/ws-handler.js +4 -2
- package/dist/server/src/app.d.ts.map +1 -1
- package/dist/server/src/app.js +0 -4
- package/dist/server/src/cli/commands/list.js +2 -2
- package/dist/server/src/cli/commands/status.d.ts.map +1 -1
- package/dist/server/src/cli/commands/status.js +41 -30
- package/dist/server/src/cli/index.d.ts.map +1 -1
- package/dist/server/src/cli/index.js +2 -1
- package/dist/server/src/cli/server.d.ts +11 -2
- package/dist/server/src/cli/server.d.ts.map +1 -1
- package/dist/server/src/config/config-change-logger.d.ts +22 -0
- package/dist/server/src/config/config-change-logger.d.ts.map +1 -1
- package/dist/server/src/config/config-change-logger.js +135 -11
- package/dist/server/src/config/config-loader.d.ts +6 -5
- package/dist/server/src/config/config-loader.d.ts.map +1 -1
- package/dist/server/src/config/config-loader.js +54 -16
- package/dist/server/src/config/config-manager.d.ts +51 -43
- package/dist/server/src/config/config-manager.d.ts.map +1 -1
- package/dist/server/src/config/config-manager.js +84 -66
- package/dist/server/src/config/config-migrator.d.ts +82 -0
- package/dist/server/src/config/config-migrator.d.ts.map +1 -0
- package/dist/server/src/config/config-migrator.js +348 -0
- package/dist/server/src/config/config-saver.d.ts +2 -0
- package/dist/server/src/config/config-saver.d.ts.map +1 -1
- package/dist/server/src/config/config-saver.js +8 -2
- package/dist/server/src/config/config.schema.d.ts +10 -102
- package/dist/server/src/config/config.schema.d.ts.map +1 -1
- package/dist/server/src/config/config.schema.js +15 -98
- package/dist/server/src/config/path-validator.d.ts +27 -0
- package/dist/server/src/config/path-validator.d.ts.map +1 -0
- package/dist/server/src/config/path-validator.js +53 -0
- package/dist/server/src/config/server-config-manager.d.ts +37 -31
- package/dist/server/src/config/server-config-manager.d.ts.map +1 -1
- package/dist/server/src/config/server-config-manager.js +222 -66
- package/dist/server/src/config/type-converter.d.ts.map +1 -1
- package/dist/server/src/config/type-converter.js +3 -2
- package/dist/server/src/index.js +1 -1
- package/dist/server/src/models/event.model.d.ts +17 -10
- package/dist/server/src/models/event.model.d.ts.map +1 -1
- package/dist/server/src/models/server.model.d.ts +17 -3
- package/dist/server/src/models/server.model.d.ts.map +1 -1
- package/dist/server/src/models/server.model.js +2 -1
- package/dist/server/src/models/system-tools.constants.d.ts +10 -27
- package/dist/server/src/models/system-tools.constants.d.ts.map +1 -1
- package/dist/server/src/models/system-tools.constants.js +4 -8
- package/dist/server/src/pid/manager.d.ts.map +1 -1
- package/dist/server/src/pid/manager.js +2 -1
- package/dist/server/src/server/dev-server.js +34 -20
- package/dist/server/src/server/runner.d.ts.map +1 -1
- package/dist/server/src/server/runner.js +41 -26
- package/dist/server/src/services/client-tracker.service.d.ts +3 -128
- package/dist/server/src/services/client-tracker.service.d.ts.map +1 -1
- package/dist/server/src/services/client-tracker.service.js +4 -200
- package/dist/server/src/services/connection/connection-manager.d.ts +85 -103
- package/dist/server/src/services/connection/connection-manager.d.ts.map +1 -1
- package/dist/server/src/services/connection/connection-manager.js +286 -241
- package/dist/server/src/services/connection/tool-cache.d.ts +27 -25
- package/dist/server/src/services/connection/tool-cache.d.ts.map +1 -1
- package/dist/server/src/services/connection/tool-cache.js +50 -55
- package/dist/server/src/services/gateway/gateway.service.d.ts +2 -0
- package/dist/server/src/services/gateway/gateway.service.d.ts.map +1 -1
- package/dist/server/src/services/gateway/gateway.service.js +15 -19
- package/dist/server/src/services/gateway/global-transport.d.ts +10 -0
- package/dist/server/src/services/gateway/global-transport.d.ts.map +1 -0
- package/dist/server/src/services/gateway/global-transport.js +42 -0
- package/dist/server/src/services/gateway/request-handlers/call-tool-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/call-tool-handler.js +67 -65
- package/dist/server/src/services/gateway/request-handlers/index.d.ts +1 -1
- package/dist/server/src/services/gateway/request-handlers/index.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/index.js +1 -1
- package/dist/server/src/services/gateway/request-handlers/initialize-handler.d.ts +1 -4
- package/dist/server/src/services/gateway/request-handlers/initialize-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/initialize-handler.js +16 -55
- package/dist/server/src/services/gateway/request-handlers/initialize.constants.d.ts +35 -0
- package/dist/server/src/services/gateway/request-handlers/initialize.constants.d.ts.map +1 -0
- package/dist/server/src/services/gateway/request-handlers/initialize.constants.js +44 -0
- package/dist/server/src/services/gateway/request-handlers/resources-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/resources-handler.js +5 -4
- package/dist/server/src/services/gateway/request-handlers/system-tools-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/system-tools-handler.js +32 -77
- package/dist/server/src/services/gateway/request-handlers/tools-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/tools-handler.js +4 -3
- package/dist/server/src/services/gateway/tool-list-generator.d.ts.map +1 -1
- package/dist/server/src/services/gateway/tool-list-generator.js +37 -16
- package/dist/server/src/services/gateway/types.d.ts +2 -1
- package/dist/server/src/services/gateway/types.d.ts.map +1 -1
- package/dist/server/src/services/hub-manager.service.d.ts +32 -238
- package/dist/server/src/services/hub-manager.service.d.ts.map +1 -1
- package/dist/server/src/services/hub-manager.service.js +89 -267
- package/dist/server/src/services/hub-tools/index.d.ts +1 -3
- package/dist/server/src/services/hub-tools/index.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/index.js +1 -2
- package/dist/server/src/services/hub-tools/instance-matcher.d.ts +62 -0
- package/dist/server/src/services/hub-tools/instance-matcher.d.ts.map +1 -0
- package/dist/server/src/services/hub-tools/instance-matcher.js +132 -0
- package/dist/server/src/services/hub-tools/instance-selector.d.ts +29 -0
- package/dist/server/src/services/hub-tools/instance-selector.d.ts.map +1 -0
- package/dist/server/src/services/hub-tools/instance-selector.js +103 -0
- package/dist/server/src/services/hub-tools/resource-generator.d.ts +25 -5
- package/dist/server/src/services/hub-tools/resource-generator.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/resource-generator.js +259 -64
- package/dist/server/src/services/hub-tools/server-selector.d.ts +26 -13
- package/dist/server/src/services/hub-tools/server-selector.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/server-selector.js +44 -37
- package/dist/server/src/services/hub-tools/system-tool-definitions.d.ts +1 -4
- package/dist/server/src/services/hub-tools/system-tool-definitions.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/system-tool-definitions.js +17 -80
- package/dist/server/src/services/hub-tools/tool-search.d.ts +7 -7
- package/dist/server/src/services/hub-tools/tool-search.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/tool-search.js +10 -4
- package/dist/server/src/services/hub-tools/types.d.ts +2 -2
- package/dist/server/src/services/hub-tools/types.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools.service.d.ts +43 -72
- package/dist/server/src/services/hub-tools.service.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools.service.js +185 -110
- package/dist/server/src/services/search/search-cache.d.ts +0 -19
- package/dist/server/src/services/search/search-cache.d.ts.map +1 -1
- package/dist/server/src/services/search/search-cache.js +0 -24
- package/dist/server/src/services/search/search-core.service.d.ts +5 -5
- package/dist/server/src/services/search/search-core.service.js +11 -11
- package/dist/server/src/services/session/session-manager.d.ts +12 -256
- package/dist/server/src/services/session/session-manager.d.ts.map +1 -1
- package/dist/server/src/services/session/session-manager.js +23 -583
- package/dist/server/src/services/session-tracker.service.d.ts +124 -0
- package/dist/server/src/services/session-tracker.service.d.ts.map +1 -0
- package/dist/server/src/services/session-tracker.service.js +176 -0
- package/dist/server/src/services/system-tool-handler.d.ts.map +1 -1
- package/dist/server/src/services/system-tool-handler.js +7 -17
- package/dist/server/src/utils/composite-key.d.ts +29 -0
- package/dist/server/src/utils/composite-key.d.ts.map +1 -0
- package/dist/server/src/utils/composite-key.js +39 -0
- package/dist/server/src/utils/error-handler.d.ts.map +1 -1
- package/dist/server/src/utils/error-handler.js +3 -2
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/server/src/utils/index.js +2 -0
- package/dist/server/src/utils/instance-id.d.ts +22 -0
- package/dist/server/src/utils/instance-id.d.ts.map +1 -0
- package/dist/server/src/utils/instance-id.js +59 -0
- package/dist/server/src/utils/json-utils.d.ts +4 -4
- package/dist/server/src/utils/json-utils.d.ts.map +1 -1
- package/dist/server/src/utils/json-utils.js +10 -4
- package/dist/server/src/utils/logger/dev-logger.d.ts +2 -1
- package/dist/server/src/utils/logger/dev-logger.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-colors.d.ts +1 -0
- package/dist/server/src/utils/logger/log-colors.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-colors.js +2 -1
- package/dist/server/src/utils/logger/log-context.d.ts +1 -0
- package/dist/server/src/utils/logger/log-context.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-formatter.d.ts +28 -0
- package/dist/server/src/utils/logger/log-formatter.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-formatter.js +287 -5
- package/dist/server/src/utils/logger/log-modules.d.ts +15 -12
- package/dist/server/src/utils/logger/log-modules.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-modules.js +8 -8
- package/dist/server/src/utils/logger/log-output.d.ts +2 -2
- package/dist/server/src/utils/logger/log-output.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-output.js +27 -6
- package/dist/server/src/utils/logger/logger.d.ts +13 -0
- package/dist/server/src/utils/logger/logger.d.ts.map +1 -1
- package/dist/server/src/utils/logger/logger.js +42 -7
- package/dist/server/src/utils/parameter-validator.d.ts +10 -0
- package/dist/server/src/utils/parameter-validator.d.ts.map +1 -0
- package/dist/server/src/utils/parameter-validator.js +53 -0
- package/dist/server/src/utils/process-tree.d.ts +49 -0
- package/dist/server/src/utils/process-tree.d.ts.map +1 -0
- package/dist/server/src/utils/process-tree.js +285 -0
- package/dist/server/src/utils/request-context.d.ts +12 -30
- package/dist/server/src/utils/request-context.d.ts.map +1 -1
- package/dist/server/src/utils/request-context.js +10 -30
- package/dist/server/src/utils/sort-utils.d.ts +40 -0
- package/dist/server/src/utils/sort-utils.d.ts.map +1 -0
- package/dist/server/src/utils/sort-utils.js +131 -0
- package/dist/server/src/utils/tool-args-parser.d.ts +0 -4
- package/dist/server/src/utils/tool-args-parser.d.ts.map +1 -1
- package/dist/server/src/utils/tool-args-parser.js +0 -7
- package/dist/server/src/utils/transports/sse-transport.d.ts +16 -1
- package/dist/server/src/utils/transports/sse-transport.d.ts.map +1 -1
- package/dist/server/src/utils/transports/sse-transport.js +55 -9
- package/dist/server/src/utils/transports/stdio-transport.d.ts +24 -53
- package/dist/server/src/utils/transports/stdio-transport.d.ts.map +1 -1
- package/dist/server/src/utils/transports/stdio-transport.js +66 -247
- package/dist/server/src/utils/transports/streamable-http-transport.d.ts +24 -1
- package/dist/server/src/utils/transports/streamable-http-transport.d.ts.map +1 -1
- package/dist/server/src/utils/transports/streamable-http-transport.js +68 -8
- package/dist/server/src/utils/transports/transport-factory.d.ts +9 -4
- package/dist/server/src/utils/transports/transport-factory.d.ts.map +1 -1
- package/dist/server/src/utils/transports/transport-factory.js +33 -13
- package/dist/server/src/utils/transports/transport.interface.d.ts +6 -0
- package/dist/server/src/utils/transports/transport.interface.d.ts.map +1 -1
- package/dist/server/src/utils/version.d.ts +11 -0
- package/dist/server/src/utils/version.d.ts.map +1 -0
- package/dist/server/src/utils/version.js +57 -0
- package/dist/server/tests/contract/mcp-protocol/initialize.test.js +24 -24
- package/dist/server/tests/contract/mcp-protocol/tools-call.test.js +49 -45
- package/dist/server/tests/contract/mcp-protocol/tools-list.test.js +35 -36
- package/dist/server/tests/evaluation/evaluation.test.js +10 -9
- package/dist/server/tests/integration/api/gateway.test.js +24 -39
- package/dist/server/tests/integration/gateway/fault-tolerance.test.js +65 -25
- package/dist/server/tests/integration/gateway/mcp-connection.test.js +53 -61
- package/dist/server/tests/server.test.js +27 -16
- package/dist/server/tests/temp/temp-run-docling.d.ts +2 -0
- package/dist/server/tests/temp/temp-run-docling.d.ts.map +1 -0
- package/dist/server/tests/temp/temp-run-docling.js +53 -0
- package/dist/server/tests/temp/test-stack.d.ts +6 -0
- package/dist/server/tests/temp/test-stack.d.ts.map +1 -0
- package/dist/server/tests/temp/test-stack.js +40 -0
- package/dist/server/tests/types/test-helpers.d.ts +1 -2
- package/dist/server/tests/types/test-helpers.d.ts.map +1 -1
- package/dist/server/tests/unit/config/config-loader-automatic-migration.test.d.ts +2 -0
- package/dist/server/tests/unit/config/config-loader-automatic-migration.test.d.ts.map +1 -0
- package/dist/server/tests/unit/config/config-loader-automatic-migration.test.js +199 -0
- package/dist/server/tests/unit/config/config-migrator.test.d.ts +2 -0
- package/dist/server/tests/unit/config/config-migrator.test.d.ts.map +1 -0
- package/dist/server/tests/unit/config/config-migrator.test.js +316 -0
- package/dist/server/tests/unit/config/config-saver.test.d.ts +2 -0
- package/dist/server/tests/unit/config/config-saver.test.d.ts.map +1 -0
- package/dist/server/tests/unit/config/config-saver.test.js +200 -0
- package/dist/server/tests/unit/config/config.schema.test.d.ts +2 -0
- package/dist/server/tests/unit/config/config.schema.test.d.ts.map +1 -0
- package/dist/server/tests/unit/config/config.schema.test.js +347 -0
- package/dist/server/tests/unit/server/runner.test.js +86 -62
- package/dist/server/tests/unit/services/connection/connection-manager.test.d.ts +2 -0
- package/dist/server/tests/unit/services/connection/connection-manager.test.d.ts.map +1 -0
- package/dist/server/tests/unit/services/connection/connection-manager.test.js +112 -0
- package/dist/server/tests/unit/services/hub-manager-service.test.js +112 -46
- package/dist/server/tests/unit/services/hub-manager.test.js +25 -15
- package/dist/server/tests/unit/services/hub-tools/instance-selector.test.d.ts +2 -0
- package/dist/server/tests/unit/services/hub-tools/instance-selector.test.d.ts.map +1 -0
- package/dist/server/tests/unit/services/hub-tools/instance-selector.test.js +195 -0
- package/dist/server/tests/unit/services/hub-tools/server-selector.test.d.ts +2 -0
- package/dist/server/tests/unit/services/hub-tools/server-selector.test.d.ts.map +1 -0
- package/dist/server/tests/unit/services/hub-tools/server-selector.test.js +190 -0
- package/dist/server/tests/unit/services/hub-tools.service.test.js +560 -334
- package/dist/server/tests/unit/services/instance-matcher.test.d.ts +2 -0
- package/dist/server/tests/unit/services/instance-matcher.test.d.ts.map +1 -0
- package/dist/server/tests/unit/services/instance-matcher.test.js +256 -0
- package/dist/server/tests/unit/services/session-manager.test.js +26 -436
- package/dist/server/tests/unit/utils/config.test.js +88 -186
- package/dist/server/tests/unit/utils/json-utils.test.js +107 -13
- package/dist/server/tests/unit/utils/logger-formatter.test.d.ts +2 -0
- package/dist/server/tests/unit/utils/logger-formatter.test.d.ts.map +1 -0
- package/dist/server/tests/unit/utils/logger-formatter.test.js +66 -0
- package/dist/server/tests/unit/utils/logger.test.js +101 -0
- package/dist/server/tests/unit/utils/parameter-validator.test.d.ts +2 -0
- package/dist/server/tests/unit/utils/parameter-validator.test.d.ts.map +1 -0
- package/dist/server/tests/unit/utils/parameter-validator.test.js +63 -0
- package/dist/server/tests/unit/utils/process-tree.test.d.ts +2 -0
- package/dist/server/tests/unit/utils/process-tree.test.d.ts.map +1 -0
- package/dist/server/tests/unit/utils/process-tree.test.js +129 -0
- package/dist/server/tests/unit/utils/request-context.test.js +9 -28
- package/dist/server/tests/unit/utils/sort-utils.test.d.ts +2 -0
- package/dist/server/tests/unit/utils/sort-utils.test.d.ts.map +1 -0
- package/dist/server/tests/unit/utils/sort-utils.test.js +220 -0
- package/dist/server/tests/unit/utils/transport-factory.test.d.ts +2 -0
- package/dist/server/tests/unit/utils/transport-factory.test.d.ts.map +1 -0
- package/dist/server/tests/unit/utils/transport-factory.test.js +55 -0
- package/package.json +1 -1
- package/dist/client/assets/ResourceDetailView-BQ49hk0c.js +0 -1
- package/dist/client/assets/ResourcesView-BYZfWtia.js +0 -1
- package/dist/client/assets/ResourcesView-CjMklkyv.css +0 -1
- package/dist/client/assets/ServerDashboard-7_8Og9JJ.css +0 -1
- package/dist/client/assets/ServerDashboard-DHcxwKeh.js +0 -2
- package/dist/client/assets/ServerListView-DralUL71.js +0 -30
- package/dist/client/assets/ServerStatusTags.vue_vue_type_script_setup_true_lang-BHiTFM7-.js +0 -1
- package/dist/client/assets/SessionsView-BCGRTqem.js +0 -1
- package/dist/client/assets/SettingsView-BLfxa6PZ.js +0 -1
- package/dist/client/assets/ToolCallDialog-DQ0OQ1mD.js +0 -1
- package/dist/client/assets/ToolsView-BLB6x3tC.js +0 -1
- package/dist/client/assets/_baseClone-Bo5mBgsT.js +0 -1
- package/dist/client/assets/el-form-item-BVMLpmVC.css +0 -1
- package/dist/client/assets/el-form-item-BmeJKVSi.js +0 -12
- package/dist/client/assets/el-input-CeZiq23m.js +0 -1
- package/dist/client/assets/el-input-CmuHb8HS.css +0 -1
- package/dist/client/assets/el-overlay-B2ZKM6Up.css +0 -1
- package/dist/client/assets/el-overlay-iw_hrrlC.js +0 -1
- package/dist/client/assets/el-select-B73uRP_Y.js +0 -1
- package/dist/client/assets/el-tab-pane-BgOTBn4X.js +0 -1
- package/dist/client/assets/el-table-column-Ld4GSD3x.js +0 -1
- package/dist/client/assets/el-table-column-T_mV9jNw.css +0 -1
- package/dist/client/assets/el-tag-DYmSo8Bx.js +0 -1
- package/dist/client/assets/el-tag-DjxZVOpb.css +0 -1
- package/dist/client/assets/index-COYaYRbH.js +0 -1
- package/dist/client/assets/index-Cfcvxyee.js +0 -2
- package/dist/client/assets/index-PhuI36Zi.js +0 -1
- package/dist/client/assets/omit-7EL6VJO4.js +0 -1
- package/dist/client/assets/vnode-upjuIlvm.js +0 -1
|
@@ -3,35 +3,19 @@ import { gateway } from '../gateway.service.js';
|
|
|
3
3
|
import { logger, LOG_MODULES, formatMcpMessageForLogging, logNotificationMessage } from '../../utils/logger.js';
|
|
4
4
|
import { configManager } from '../../config/config-manager.js';
|
|
5
5
|
import { formatDuration } from '../../utils/format-utils.js';
|
|
6
|
-
import { SessionStateSchema, createEmptySessionStore } from '../../../shared/models/session.model.js';
|
|
7
|
-
import { clientTrackerService } from '../client-tracker.service.js';
|
|
8
6
|
import { getSessionDebugSetting, getMcpCommDebugSetting } from '../../utils/json-utils.js';
|
|
9
|
-
import * as fs from 'fs';
|
|
10
|
-
import path from 'path';
|
|
11
|
-
import os from 'os';
|
|
12
7
|
/**
|
|
13
|
-
*
|
|
8
|
+
* Lightweight MCP Session Manager with in-memory session management only.
|
|
14
9
|
*
|
|
15
|
-
* This service manages MCP sessions with
|
|
16
|
-
*
|
|
10
|
+
* This service manages MCP sessions with basic in-memory storage and automatic
|
|
11
|
+
* cleanup of stale sessions. It provides session isolation through unique
|
|
17
12
|
* server and transport instances per session while maintaining shared resources
|
|
18
13
|
* for efficiency.
|
|
19
14
|
*
|
|
20
|
-
* Key features
|
|
21
|
-
* -
|
|
22
|
-
* - Dirty tracking with 5-second batch flushing to minimize I/O operations
|
|
15
|
+
* Key features:
|
|
16
|
+
* - In-memory session storage only (no persistence)
|
|
23
17
|
* - Automatic cleanup of stale sessions based on configurable timeout (default 30 minutes)
|
|
24
|
-
* -
|
|
25
|
-
* - Client metadata integration from client tracker service
|
|
26
|
-
* - Environment variable controlled debugging (SESSION_DEBUG)
|
|
27
|
-
*
|
|
28
|
-
* Session storage structure:
|
|
29
|
-
* ```
|
|
30
|
-
* ~/.mcp-hub-lite/
|
|
31
|
-
* └── sessions/
|
|
32
|
-
* ├── index.json # Session index file
|
|
33
|
-
* └── {sessionId}.json # Individual session state files
|
|
34
|
-
* ```
|
|
18
|
+
* - Session ID generation for internal use
|
|
35
19
|
*
|
|
36
20
|
* @example
|
|
37
21
|
* ```typescript
|
|
@@ -40,15 +24,10 @@ import os from 'os';
|
|
|
40
24
|
* // Use session.server and session.transport for MCP communication
|
|
41
25
|
* ```
|
|
42
26
|
*
|
|
43
|
-
* @since
|
|
27
|
+
* @since 2.0.0
|
|
44
28
|
*/
|
|
45
29
|
export class McpSessionManager {
|
|
46
30
|
sessions = new Map();
|
|
47
|
-
sessionStates = new Map();
|
|
48
|
-
dirtySessions = new Set();
|
|
49
|
-
sessionsPath;
|
|
50
|
-
flushTimeout = null; // Replace with one-time delay
|
|
51
|
-
isInitialized = false;
|
|
52
31
|
get SESSION_TIMEOUT() {
|
|
53
32
|
return configManager.getConfig().security.sessionTimeout;
|
|
54
33
|
}
|
|
@@ -56,428 +35,15 @@ export class McpSessionManager {
|
|
|
56
35
|
return configManager.getConfig().security.sessionFlushInterval;
|
|
57
36
|
}
|
|
58
37
|
constructor() {
|
|
59
|
-
// Initialize sessions directory path
|
|
60
|
-
const configPath = process.env.MCP_HUB_CONFIG_PATH ||
|
|
61
|
-
path.join(os.homedir(), '.mcp-hub-lite', 'config', '.mcp-hub.json');
|
|
62
|
-
const mcpHubDir = path.dirname(path.dirname(configPath)); // Get ~/.mcp-hub-lite directory
|
|
63
|
-
this.sessionsPath = path.join(mcpHubDir, 'sessions');
|
|
64
|
-
logger.info(`Using sessions directory: ${this.sessionsPath}`, LOG_MODULES.SESSION_MANAGER);
|
|
65
38
|
// Start cleanup interval
|
|
66
39
|
setInterval(() => this.cleanup(), this.CLEANUP_INTERVAL);
|
|
67
|
-
// Register graceful shutdown handler
|
|
68
|
-
this.registerShutdownHandler();
|
|
69
|
-
// Initialize by restoring sessions
|
|
70
|
-
this.restoreSessions().catch((error) => {
|
|
71
|
-
logger.error('Failed to restore sessions during initialization:', error, LOG_MODULES.SESSION_MANAGER);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Registers process shutdown handlers for graceful session cleanup.
|
|
76
|
-
*
|
|
77
|
-
* This method sets up event listeners for SIGTERM and SIGINT signals to ensure
|
|
78
|
-
* that all dirty sessions are flushed to disk before the process terminates.
|
|
79
|
-
* This prevents data loss during unexpected shutdowns or service restarts.
|
|
80
|
-
*
|
|
81
|
-
* The shutdown handler performs a final flush of all dirty sessions and
|
|
82
|
-
* clears any pending flush timeouts to ensure clean termination.
|
|
83
|
-
*
|
|
84
|
-
* @returns {void}
|
|
85
|
-
*
|
|
86
|
-
* @example
|
|
87
|
-
* ```typescript
|
|
88
|
-
* // Called automatically in constructor
|
|
89
|
-
* sessionManager.registerShutdownHandler();
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
registerShutdownHandler() {
|
|
93
|
-
const gracefulShutdown = async () => {
|
|
94
|
-
logger.info('Shutting down, flushing dirty sessions...', LOG_MODULES.SESSION_MANAGER);
|
|
95
|
-
try {
|
|
96
|
-
await this.flushDirtySessions();
|
|
97
|
-
}
|
|
98
|
-
catch (error) {
|
|
99
|
-
logger.error('Error during shutdown flush:', error, LOG_MODULES.SESSION_MANAGER);
|
|
100
|
-
}
|
|
101
|
-
if (this.flushTimeout) {
|
|
102
|
-
clearTimeout(this.flushTimeout);
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
process.on('SIGTERM', gracefulShutdown);
|
|
106
|
-
process.on('SIGINT', gracefulShutdown);
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Marks a session as dirty, indicating it needs to be persisted to disk.
|
|
110
|
-
*
|
|
111
|
-
* This method adds the session ID to the dirty sessions set and initiates
|
|
112
|
-
* a delayed batch flush operation with a 5-second timeout. This optimization
|
|
113
|
-
* prevents excessive I/O operations by batching multiple session updates
|
|
114
|
-
* that occur in quick succession.
|
|
115
|
-
*
|
|
116
|
-
* When the SESSION_DEBUG environment variable is set, detailed logging
|
|
117
|
-
* is enabled for debugging session persistence behavior.
|
|
118
|
-
*
|
|
119
|
-
* @param {string} sessionId - Unique identifier of the session to mark as dirty
|
|
120
|
-
* @returns {void}
|
|
121
|
-
*
|
|
122
|
-
* @example
|
|
123
|
-
* ```typescript
|
|
124
|
-
* sessionManager.markAsDirty('my-session-id');
|
|
125
|
-
* // Session will be flushed to disk within 5 seconds
|
|
126
|
-
* ```
|
|
127
|
-
*/
|
|
128
|
-
markAsDirty(sessionId) {
|
|
129
|
-
this.dirtySessions.add(sessionId);
|
|
130
|
-
if (getSessionDebugSetting()) {
|
|
131
|
-
logger.debug(`Session marked as dirty: ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
132
|
-
}
|
|
133
|
-
// Set one-time delayed flush to avoid frequent writes (configurable delay, batch processing)
|
|
134
|
-
if (!this.flushTimeout) {
|
|
135
|
-
const flushInterval = configManager.getConfig().security.sessionFlushInterval || 5000;
|
|
136
|
-
this.flushTimeout = setTimeout(() => {
|
|
137
|
-
this.flushDirtySessions();
|
|
138
|
-
this.flushTimeout = null;
|
|
139
|
-
}, flushInterval);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Loads the complete session store from disk, including all individual session files.
|
|
144
|
-
*
|
|
145
|
-
* This method reads the sessions index file and loads each individual session state
|
|
146
|
-
* file, validating each session state against the SessionStateSchema. Invalid
|
|
147
|
-
* session states are skipped with warning logs, ensuring robust recovery from
|
|
148
|
-
* corrupted data.
|
|
149
|
-
*
|
|
150
|
-
* The method creates the sessions directory and index file if they don't exist,
|
|
151
|
-
* providing a clean initialization path for first-time usage.
|
|
152
|
-
*
|
|
153
|
-
* @returns {Promise<SessionStore>} Complete session store with all valid sessions
|
|
154
|
-
* @throws {Error} If critical I/O operations fail (non-recoverable errors)
|
|
155
|
-
*
|
|
156
|
-
* @example
|
|
157
|
-
* ```typescript
|
|
158
|
-
* const store = await sessionManager.loadSessionStore();
|
|
159
|
-
* console.log(`Loaded ${Object.keys(store.sessions).length} sessions`);
|
|
160
|
-
* ```
|
|
161
|
-
*/
|
|
162
|
-
async loadSessionStore() {
|
|
163
|
-
try {
|
|
164
|
-
if (!fs.existsSync(this.sessionsPath)) {
|
|
165
|
-
if (getSessionDebugSetting()) {
|
|
166
|
-
logger.debug('Sessions directory not found, creating new one', LOG_MODULES.SESSION_MANAGER);
|
|
167
|
-
}
|
|
168
|
-
fs.mkdirSync(this.sessionsPath, { recursive: true });
|
|
169
|
-
return createEmptySessionStore();
|
|
170
|
-
}
|
|
171
|
-
const indexPath = path.join(this.sessionsPath, 'index.json');
|
|
172
|
-
if (!fs.existsSync(indexPath)) {
|
|
173
|
-
if (getSessionDebugSetting()) {
|
|
174
|
-
logger.debug('Sessions index file not found, creating new one', LOG_MODULES.SESSION_MANAGER);
|
|
175
|
-
}
|
|
176
|
-
return createEmptySessionStore();
|
|
177
|
-
}
|
|
178
|
-
const indexContent = fs.readFileSync(indexPath, 'utf-8');
|
|
179
|
-
const index = JSON.parse(indexContent);
|
|
180
|
-
if (!index.sessions || !Array.isArray(index.sessions)) {
|
|
181
|
-
logger.error('Invalid sessions index file, creating new one', LOG_MODULES.SESSION_MANAGER);
|
|
182
|
-
return createEmptySessionStore();
|
|
183
|
-
}
|
|
184
|
-
const store = createEmptySessionStore();
|
|
185
|
-
for (const sessionId of index.sessions) {
|
|
186
|
-
const sessionPath = path.join(this.sessionsPath, `${sessionId}.json`);
|
|
187
|
-
if (fs.existsSync(sessionPath)) {
|
|
188
|
-
try {
|
|
189
|
-
const sessionContent = fs.readFileSync(sessionPath, 'utf-8');
|
|
190
|
-
const sessionState = JSON.parse(sessionContent);
|
|
191
|
-
const validated = SessionStateSchema.parse(sessionState);
|
|
192
|
-
store.sessions[sessionId] = validated;
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
logger.warn(`Failed to load session ${sessionId}:`, error, LOG_MODULES.SESSION_MANAGER);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (getSessionDebugSetting()) {
|
|
200
|
-
logger.debug(`Loaded ${Object.keys(store.sessions).length} sessions from store`, LOG_MODULES.SESSION_MANAGER);
|
|
201
|
-
}
|
|
202
|
-
return store;
|
|
203
|
-
}
|
|
204
|
-
catch (error) {
|
|
205
|
-
logger.error('Failed to load sessions store:', error, LOG_MODULES.SESSION_MANAGER);
|
|
206
|
-
return createEmptySessionStore();
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Saves the complete session store to disk, writing individual session files and index.
|
|
211
|
-
*
|
|
212
|
-
* This method persists all session states by writing individual JSON files for each
|
|
213
|
-
* session and updating the sessions index file. The operation is atomic at the
|
|
214
|
-
* file level, ensuring data integrity even if the process is interrupted.
|
|
215
|
-
*
|
|
216
|
-
* @param {SessionStore} store - Complete session store to persist
|
|
217
|
-
* @returns {Promise<void>} Resolves when all files are successfully written
|
|
218
|
-
* @throws {Error} If any file write operations fail
|
|
219
|
-
*
|
|
220
|
-
* @example
|
|
221
|
-
* ```typescript
|
|
222
|
-
* await sessionManager.saveSessionStore(mySessionStore);
|
|
223
|
-
* console.log('Session store saved successfully');
|
|
224
|
-
* ```
|
|
225
|
-
*/
|
|
226
|
-
async saveSessionStore(store) {
|
|
227
|
-
try {
|
|
228
|
-
if (!fs.existsSync(this.sessionsPath)) {
|
|
229
|
-
fs.mkdirSync(this.sessionsPath, { recursive: true });
|
|
230
|
-
}
|
|
231
|
-
// Save individual session files
|
|
232
|
-
for (const [sessionId, state] of Object.entries(store.sessions)) {
|
|
233
|
-
const sessionPath = path.join(this.sessionsPath, `${sessionId}.json`);
|
|
234
|
-
fs.writeFileSync(sessionPath, JSON.stringify(state, null, 2));
|
|
235
|
-
}
|
|
236
|
-
// Save index file
|
|
237
|
-
const indexPath = path.join(this.sessionsPath, 'index.json');
|
|
238
|
-
fs.writeFileSync(indexPath, JSON.stringify({
|
|
239
|
-
sessions: Object.keys(store.sessions)
|
|
240
|
-
}, null, 2));
|
|
241
|
-
}
|
|
242
|
-
catch (error) {
|
|
243
|
-
logger.error('Failed to save sessions store:', error, LOG_MODULES.SESSION_MANAGER);
|
|
244
|
-
throw error;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Restores all sessions from disk during service startup.
|
|
249
|
-
*
|
|
250
|
-
* This method is called automatically during initialization to recover session states
|
|
251
|
-
* from persistent storage. It loads the session store, validates each session state,
|
|
252
|
-
* and populates the in-memory session state cache. Invalid sessions are skipped
|
|
253
|
-
* with warning logs to ensure robust startup even with corrupted data.
|
|
254
|
-
*
|
|
255
|
-
* The method ensures idempotent execution by checking the initialization flag,
|
|
256
|
-
* preventing multiple restoration attempts.
|
|
257
|
-
*
|
|
258
|
-
* @returns {Promise<void>} Resolves when all valid sessions are restored
|
|
259
|
-
*
|
|
260
|
-
* @example
|
|
261
|
-
* ```typescript
|
|
262
|
-
* await sessionManager.restoreSessions();
|
|
263
|
-
* console.log('Sessions restored from disk');
|
|
264
|
-
* ```
|
|
265
|
-
*/
|
|
266
|
-
async restoreSessions() {
|
|
267
|
-
if (this.isInitialized) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
try {
|
|
271
|
-
logger.info('Restoring sessions from disk...', LOG_MODULES.SESSION_MANAGER);
|
|
272
|
-
const store = await this.loadSessionStore();
|
|
273
|
-
let restoredCount = 0;
|
|
274
|
-
let expiredCount = 0;
|
|
275
|
-
const now = Date.now();
|
|
276
|
-
for (const [sessionId, state] of Object.entries(store.sessions)) {
|
|
277
|
-
try {
|
|
278
|
-
// Validate individual session state
|
|
279
|
-
const validatedState = SessionStateSchema.parse(state);
|
|
280
|
-
// Check if session has expired
|
|
281
|
-
if (now - validatedState.lastAccessedAt > this.SESSION_TIMEOUT) {
|
|
282
|
-
expiredCount++;
|
|
283
|
-
if (getSessionDebugSetting()) {
|
|
284
|
-
logger.debug(`Expired session: ${sessionId} (last accessed ${formatDuration(now - validatedState.lastAccessedAt)} ago)`, LOG_MODULES.SESSION_MANAGER);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
else {
|
|
288
|
-
restoredCount++;
|
|
289
|
-
}
|
|
290
|
-
// Always restore to memory - cleanup() will handle deletion
|
|
291
|
-
this.sessionStates.set(sessionId, validatedState);
|
|
292
|
-
if (getSessionDebugSetting()) {
|
|
293
|
-
logger.debug(`Restored session state: ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
catch (error) {
|
|
297
|
-
logger.warn(`Skipping invalid session state for ${sessionId}:`, error, LOG_MODULES.SESSION_MANAGER);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
this.isInitialized = true;
|
|
301
|
-
logger.info(`Successfully restored ${restoredCount} valid, ${expiredCount} expired session(s)`, LOG_MODULES.SESSION_MANAGER);
|
|
302
|
-
// Immediately run cleanup on startup to clean up any expired sessions
|
|
303
|
-
this.cleanup();
|
|
304
|
-
}
|
|
305
|
-
catch (error) {
|
|
306
|
-
logger.error('Failed to restore sessions:', error, LOG_MODULES.SESSION_MANAGER);
|
|
307
|
-
// Continue with empty state rather than failing
|
|
308
|
-
this.isInitialized = true;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Flushes all dirty sessions to disk in a single batch operation.
|
|
313
|
-
*
|
|
314
|
-
* This method collects all sessions marked as dirty, loads the current session store,
|
|
315
|
-
* updates it with the dirty sessions, and saves the complete store back to disk.
|
|
316
|
-
* This batch approach minimizes I/O operations and ensures data consistency.
|
|
317
|
-
*
|
|
318
|
-
* The method includes comprehensive error handling to prevent partial writes and
|
|
319
|
-
* maintains detailed logging for debugging and monitoring purposes.
|
|
320
|
-
*
|
|
321
|
-
* @returns {Promise<void>} Resolves when all dirty sessions are successfully flushed
|
|
322
|
-
*
|
|
323
|
-
* @example
|
|
324
|
-
* ```typescript
|
|
325
|
-
* await sessionManager.flushDirtySessions();
|
|
326
|
-
* console.log('All dirty sessions flushed to disk');
|
|
327
|
-
* ```
|
|
328
|
-
*/
|
|
329
|
-
async flushDirtySessions() {
|
|
330
|
-
if (this.dirtySessions.size === 0) {
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
try {
|
|
334
|
-
logger.info(`Flushing ${this.dirtySessions.size} dirty session(s) to disk`, LOG_MODULES.SESSION_MANAGER);
|
|
335
|
-
// Load current store
|
|
336
|
-
const currentStore = await this.loadSessionStore();
|
|
337
|
-
const newStore = {
|
|
338
|
-
...currentStore,
|
|
339
|
-
sessions: { ...currentStore.sessions }
|
|
340
|
-
};
|
|
341
|
-
// Process all dirty sessions
|
|
342
|
-
for (const sessionId of this.dirtySessions) {
|
|
343
|
-
const sessionState = this.sessionStates.get(sessionId);
|
|
344
|
-
if (sessionState) {
|
|
345
|
-
// Session exists - update it
|
|
346
|
-
newStore.sessions[sessionId] = sessionState;
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
// Session does not exist - remove it
|
|
350
|
-
delete newStore.sessions[sessionId];
|
|
351
|
-
// Also remove the individual session file
|
|
352
|
-
const sessionPath = path.join(this.sessionsPath, `${sessionId}.json`);
|
|
353
|
-
if (fs.existsSync(sessionPath)) {
|
|
354
|
-
fs.unlinkSync(sessionPath);
|
|
355
|
-
logger.debug(`Deleted session file: ${sessionId}.json`, LOG_MODULES.SESSION_MANAGER);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
await this.saveSessionStore(newStore);
|
|
360
|
-
const flushedCount = this.dirtySessions.size;
|
|
361
|
-
this.dirtySessions.clear();
|
|
362
|
-
logger.info(`Successfully flushed ${flushedCount} session(s)`, LOG_MODULES.SESSION_MANAGER);
|
|
363
|
-
}
|
|
364
|
-
catch (error) {
|
|
365
|
-
logger.error('Failed to flush dirty sessions:', error, LOG_MODULES.SESSION_MANAGER);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Updates session metadata by retrieving client information from the client tracker service.
|
|
370
|
-
*
|
|
371
|
-
* This method fetches current client information including name, version, working directory,
|
|
372
|
-
* and project context from the client tracker service and returns a partial session state
|
|
373
|
-
* update object containing only the relevant metadata fields.
|
|
374
|
-
*
|
|
375
|
-
* @param {string} sessionId - Unique identifier of the session to update
|
|
376
|
-
* @returns {Partial<SessionState>} Partial session state with updated client metadata
|
|
377
|
-
*
|
|
378
|
-
* @example
|
|
379
|
-
* ```typescript
|
|
380
|
-
* const metadata = sessionManager.updateSessionMetadataFromClient('my-session-id');
|
|
381
|
-
* console.log('Updated client metadata:', metadata);
|
|
382
|
-
* ```
|
|
383
|
-
*/
|
|
384
|
-
updateSessionMetadataFromClient(sessionId) {
|
|
385
|
-
const clientInfo = clientTrackerService.getClient(sessionId);
|
|
386
|
-
return {
|
|
387
|
-
clientName: clientInfo?.clientName,
|
|
388
|
-
clientVersion: clientInfo?.clientVersion,
|
|
389
|
-
protocolVersion: clientInfo?.protocolVersion,
|
|
390
|
-
cwd: clientInfo?.cwd,
|
|
391
|
-
project: clientInfo?.project,
|
|
392
|
-
userAgent: clientInfo?.userAgent,
|
|
393
|
-
ip: clientInfo?.ip
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* Creates or updates a session state with current metadata and timestamps.
|
|
398
|
-
*
|
|
399
|
-
* This method merges existing session state (if any) with current client metadata
|
|
400
|
-
* from the client tracker service, updates access timestamps, and ensures proper
|
|
401
|
-
* session state structure. The updated state is stored in memory and marked as dirty
|
|
402
|
-
* for persistence.
|
|
403
|
-
*
|
|
404
|
-
* @param {string} sessionId - Unique identifier of the session to create or update
|
|
405
|
-
* @returns {SessionState} Complete updated session state object
|
|
406
|
-
*
|
|
407
|
-
* @example
|
|
408
|
-
* ```typescript
|
|
409
|
-
* const state = sessionManager.upsertSessionState('my-session-id');
|
|
410
|
-
* console.log('Session state updated:', state);
|
|
411
|
-
* ```
|
|
412
|
-
*/
|
|
413
|
-
upsertSessionState(sessionId) {
|
|
414
|
-
const existing = this.sessionStates.get(sessionId);
|
|
415
|
-
const now = Date.now();
|
|
416
|
-
const clientMetadata = this.updateSessionMetadataFromClient(sessionId);
|
|
417
|
-
const state = {
|
|
418
|
-
sessionId,
|
|
419
|
-
clientName: clientMetadata.clientName || existing?.clientName,
|
|
420
|
-
clientVersion: clientMetadata.clientVersion || existing?.clientVersion,
|
|
421
|
-
protocolVersion: clientMetadata.protocolVersion || existing?.protocolVersion,
|
|
422
|
-
cwd: clientMetadata.cwd || existing?.cwd,
|
|
423
|
-
project: clientMetadata.project || existing?.project,
|
|
424
|
-
userAgent: clientMetadata.userAgent || existing?.userAgent,
|
|
425
|
-
ip: clientMetadata.ip || existing?.ip,
|
|
426
|
-
createdAt: existing?.createdAt || now,
|
|
427
|
-
lastAccessedAt: now,
|
|
428
|
-
metadata: existing?.metadata || {}
|
|
429
|
-
};
|
|
430
|
-
this.sessionStates.set(sessionId, state);
|
|
431
|
-
this.markAsDirty(sessionId);
|
|
432
|
-
return state;
|
|
433
|
-
}
|
|
434
|
-
/**
|
|
435
|
-
* Updates session metadata explicitly with provided key-value pairs.
|
|
436
|
-
*
|
|
437
|
-
* This method merges the provided metadata object with existing session metadata,
|
|
438
|
-
* updates the last accessed timestamp, and marks the session as dirty for persistence.
|
|
439
|
-
* It's useful for storing custom session-specific information that needs to be persisted.
|
|
440
|
-
*
|
|
441
|
-
* @param {string} sessionId - Unique identifier of the session to update
|
|
442
|
-
* @param {Record<string, unknown>} metadata - Key-value pairs to merge into session metadata
|
|
443
|
-
* @returns {Promise<void>} Resolves when metadata is updated and marked for persistence
|
|
444
|
-
*
|
|
445
|
-
* @example
|
|
446
|
-
* ```typescript
|
|
447
|
-
* await sessionManager.updateSessionMetadata('my-session-id', {
|
|
448
|
-
* userPreferences: { theme: 'dark' },
|
|
449
|
-
* lastProject: 'my-project'
|
|
450
|
-
* });
|
|
451
|
-
* ```
|
|
452
|
-
*/
|
|
453
|
-
async updateSessionMetadata(sessionId, metadata) {
|
|
454
|
-
const existing = this.sessionStates.get(sessionId);
|
|
455
|
-
if (existing) {
|
|
456
|
-
const now = Date.now();
|
|
457
|
-
const updated = {
|
|
458
|
-
...existing,
|
|
459
|
-
lastAccessedAt: now,
|
|
460
|
-
metadata: {
|
|
461
|
-
...existing.metadata,
|
|
462
|
-
...metadata
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
this.sessionStates.set(sessionId, updated);
|
|
466
|
-
this.markAsDirty(sessionId);
|
|
467
|
-
if (getSessionDebugSetting()) {
|
|
468
|
-
logger.debug(`Updated metadata for session: ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
40
|
}
|
|
472
41
|
/**
|
|
473
42
|
* Retrieves an existing session or creates a new one if it doesn't exist.
|
|
474
43
|
*
|
|
475
44
|
* This method provides access to active sessions, creating new ones on demand with
|
|
476
45
|
* proper initialization based on the requireInitialize parameter. It updates session
|
|
477
|
-
* access timestamps
|
|
478
|
-
*
|
|
479
|
-
* The method includes optimization to prevent excessive timestamp updates for rapid
|
|
480
|
-
* successive requests by only updating when at least 100ms have passed since the last access.
|
|
46
|
+
* access timestamps.
|
|
481
47
|
*
|
|
482
48
|
* @param {string} sessionId - Unique identifier of the session to retrieve or create
|
|
483
49
|
* @param {boolean} [requireInitialize=true] - Whether to require MCP protocol initialization
|
|
@@ -487,48 +53,28 @@ export class McpSessionManager {
|
|
|
487
53
|
* ```typescript
|
|
488
54
|
* // Get or create session with default initialization
|
|
489
55
|
* const session = await sessionManager.getSession('my-session-id');
|
|
490
|
-
*
|
|
491
|
-
* // Get or create session without requiring initialization (for restored sessions)
|
|
492
|
-
* const restoredSession = await sessionManager.getSession('restored-session-id', false);
|
|
493
56
|
* ```
|
|
494
57
|
*/
|
|
495
58
|
async getSession(sessionId, requireInitialize = true) {
|
|
496
59
|
if (getSessionDebugSetting()) {
|
|
497
|
-
const hasSessionState = this.sessionStates.has(sessionId);
|
|
498
60
|
const hasSessionObject = this.sessions.has(sessionId);
|
|
499
|
-
logger.debug(`getSession called for ${sessionId} (requireInitialize: ${requireInitialize}).
|
|
61
|
+
logger.debug(`getSession called for ${sessionId} (requireInitialize: ${requireInitialize}). Object exists: ${hasSessionObject}`, LOG_MODULES.SESSION_MANAGER);
|
|
500
62
|
}
|
|
501
63
|
let session = this.sessions.get(sessionId);
|
|
502
|
-
|
|
503
|
-
const hasSessionState = this.sessionStates.has(sessionId);
|
|
504
|
-
const hasSessionObject = this.sessions.has(sessionId);
|
|
505
|
-
if (hasSessionState && !hasSessionObject) {
|
|
506
|
-
// Session state exists but session object is missing - recreate session
|
|
507
|
-
if (getSessionDebugSetting()) {
|
|
508
|
-
logger.debug(`Session state exists but session object missing for ${sessionId}, recreating...`, LOG_MODULES.SESSION_MANAGER);
|
|
509
|
-
}
|
|
510
|
-
session = await this.createSession(sessionId, requireInitialize);
|
|
511
|
-
this.sessions.set(sessionId, session);
|
|
512
|
-
}
|
|
513
|
-
else if (!session) {
|
|
64
|
+
if (!session) {
|
|
514
65
|
// Normal case: create new session
|
|
515
66
|
session = await this.createSession(sessionId, requireInitialize);
|
|
516
67
|
this.sessions.set(sessionId, session);
|
|
517
68
|
}
|
|
518
69
|
else {
|
|
519
|
-
//
|
|
520
|
-
// This fixes the "Session not found" error when transport has lost session context
|
|
521
|
-
const hasRestoredState = this.sessionStates.has(sessionId);
|
|
522
|
-
const shouldManuallyInitialize = !requireInitialize || hasRestoredState;
|
|
523
|
-
// Always ensure sessionId is set on transport, regardless of initialization status
|
|
524
|
-
// This fixes the "Session not found" error for non-initialization requests
|
|
70
|
+
// Ensure transport session state is correctly initialized
|
|
525
71
|
const webTransport = session.transport
|
|
526
72
|
._webStandardTransport;
|
|
527
73
|
if (webTransport) {
|
|
528
74
|
const currentSessionId = webTransport.sessionId;
|
|
529
75
|
const isInitialized = webTransport._initialized;
|
|
530
76
|
if (getSessionDebugSetting()) {
|
|
531
|
-
logger.debug(`Transport state check - Expected: ${sessionId} (initialized: ${
|
|
77
|
+
logger.debug(`Transport state check - Expected: ${sessionId} (initialized: ${!requireInitialize}), Actual: ${currentSessionId} (initialized: ${isInitialized})`, LOG_MODULES.SESSION_MANAGER);
|
|
532
78
|
}
|
|
533
79
|
if (webTransport.sessionId !== sessionId) {
|
|
534
80
|
logger.warn(`Session ID mismatch detected for ${sessionId}. Resetting transport sessionId.`, LOG_MODULES.SESSION_MANAGER);
|
|
@@ -537,7 +83,7 @@ export class McpSessionManager {
|
|
|
537
83
|
webTransport._session = sessionId;
|
|
538
84
|
}
|
|
539
85
|
}
|
|
540
|
-
if (
|
|
86
|
+
if (!requireInitialize && !webTransport._initialized) {
|
|
541
87
|
logger.warn(`Session initialization state mismatch detected for ${sessionId}. Setting initialized flag.`, LOG_MODULES.SESSION_MANAGER);
|
|
542
88
|
webTransport._initialized = true;
|
|
543
89
|
}
|
|
@@ -546,56 +92,14 @@ export class McpSessionManager {
|
|
|
546
92
|
const now = Date.now();
|
|
547
93
|
const timeDiff = Math.abs(now - session.lastAccessed);
|
|
548
94
|
// Only update lastAccessed if meaningful time has passed
|
|
549
|
-
// This prevents excessive updates for rapid successive requests
|
|
550
95
|
if (timeDiff >= 100) {
|
|
551
96
|
session.lastAccessed = now;
|
|
552
|
-
// Also update and persist session state
|
|
553
|
-
this.upsertSessionState(sessionId);
|
|
554
97
|
}
|
|
555
98
|
if (getSessionDebugSetting()) {
|
|
556
99
|
logger.debug(`Returning session for ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
557
100
|
}
|
|
558
101
|
return session;
|
|
559
102
|
}
|
|
560
|
-
/**
|
|
561
|
-
* Retrieves all persisted session states for API exposure.
|
|
562
|
-
*
|
|
563
|
-
* This method returns an array of all current session states, providing a complete
|
|
564
|
-
* snapshot of all active sessions and their metadata. It's primarily used by the
|
|
565
|
-
* web API to expose session information to clients.
|
|
566
|
-
*
|
|
567
|
-
* @returns {SessionState[]} Array of all current session states
|
|
568
|
-
*
|
|
569
|
-
* @example
|
|
570
|
-
* ```typescript
|
|
571
|
-
* const allStates = sessionManager.getAllSessionStates();
|
|
572
|
-
* console.log(`Total active sessions: ${allStates.length}`);
|
|
573
|
-
* ```
|
|
574
|
-
*/
|
|
575
|
-
getAllSessionStates() {
|
|
576
|
-
return Array.from(this.sessionStates.values());
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Retrieves a specific session state by session ID for API exposure.
|
|
580
|
-
*
|
|
581
|
-
* This method returns the current state of a specific session or undefined if
|
|
582
|
-
* the session doesn't exist. It's primarily used by the web API to provide
|
|
583
|
-
* detailed information about individual sessions.
|
|
584
|
-
*
|
|
585
|
-
* @param {string} sessionId - Unique identifier of the session to retrieve
|
|
586
|
-
* @returns {SessionState | undefined} Session state object or undefined if not found
|
|
587
|
-
*
|
|
588
|
-
* @example
|
|
589
|
-
* ```typescript
|
|
590
|
-
* const state = sessionManager.getSessionState('my-session-id');
|
|
591
|
-
* if (state) {
|
|
592
|
-
* console.log('Session client:', state.clientName);
|
|
593
|
-
* }
|
|
594
|
-
* ```
|
|
595
|
-
*/
|
|
596
|
-
getSessionState(sessionId) {
|
|
597
|
-
return this.sessionStates.get(sessionId);
|
|
598
|
-
}
|
|
599
103
|
/**
|
|
600
104
|
* Checks if a session object exists in the active sessions map.
|
|
601
105
|
*
|
|
@@ -606,11 +110,9 @@ export class McpSessionManager {
|
|
|
606
110
|
return this.sessions.has(sessionId);
|
|
607
111
|
}
|
|
608
112
|
/**
|
|
609
|
-
* Deletes a session
|
|
113
|
+
* Deletes a session from memory.
|
|
610
114
|
*
|
|
611
|
-
* This method gracefully closes the session's MCP server
|
|
612
|
-
* and ensures it's removed from persistent storage by marking it as dirty and
|
|
613
|
-
* performing an immediate flush. It returns true if the session existed and was deleted.
|
|
115
|
+
* This method gracefully closes the session's MCP server and removes it from memory.
|
|
614
116
|
*
|
|
615
117
|
* @param {string} sessionId - Unique identifier of the session to delete
|
|
616
118
|
* @returns {Promise<boolean>} True if session existed and was deleted, false otherwise
|
|
@@ -633,30 +135,15 @@ export class McpSessionManager {
|
|
|
633
135
|
logger.error(`Error closing session ${sessionId}:`, e, LOG_MODULES.SESSION_MANAGER);
|
|
634
136
|
}
|
|
635
137
|
this.sessions.delete(sessionId);
|
|
138
|
+
return true;
|
|
636
139
|
}
|
|
637
|
-
|
|
638
|
-
if (existed) {
|
|
639
|
-
this.sessionStates.delete(sessionId);
|
|
640
|
-
// Mark as dirty to remove from persistence
|
|
641
|
-
this.markAsDirty(sessionId);
|
|
642
|
-
// Flush immediately to remove from disk
|
|
643
|
-
await this.flushDirtySessions();
|
|
644
|
-
}
|
|
645
|
-
return existed;
|
|
140
|
+
return false;
|
|
646
141
|
}
|
|
647
142
|
/**
|
|
648
143
|
* Creates a new MCP session with proper initialization and transport setup.
|
|
649
144
|
*
|
|
650
145
|
* This method sets up a complete MCP session including server, transport, and
|
|
651
|
-
* communication logging.
|
|
652
|
-
* with special logic for skipping initialization when appropriate.
|
|
653
|
-
*
|
|
654
|
-
* Key features:
|
|
655
|
-
* - Creates StreamableHTTPServerTransport with custom session ID generation
|
|
656
|
-
* - Sets up comprehensive message logging for debugging
|
|
657
|
-
* - Handles restored sessions by manually initializing transport state
|
|
658
|
-
* - Integrates with client tracker service for metadata
|
|
659
|
-
* - Creates/updates session state and marks as dirty for persistence
|
|
146
|
+
* communication logging.
|
|
660
147
|
*
|
|
661
148
|
* @param {string} sessionId - Unique identifier for the new session
|
|
662
149
|
* @param {boolean} [requireInitialize=true] - Whether to require MCP protocol initialization
|
|
@@ -686,46 +173,26 @@ export class McpSessionManager {
|
|
|
686
173
|
}
|
|
687
174
|
});
|
|
688
175
|
// Directly set sessionId property to avoid validateSession failure
|
|
689
|
-
// because WebStandardStreamableHTTPServerTransport only calls sessionIdGenerator during initialize
|
|
690
176
|
const webTransport = transport._webStandardTransport;
|
|
691
177
|
if (webTransport) {
|
|
692
178
|
webTransport.sessionId = sessionId;
|
|
693
|
-
// Do not set _initialized = true here because it will cause initialize request to fail
|
|
694
|
-
// _initialized flag will be set as needed in the shouldManuallyInitialize logic
|
|
695
179
|
if (getSessionDebugSetting()) {
|
|
696
180
|
logger.debug(`Directly set sessionId on transport: ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
697
181
|
}
|
|
698
182
|
}
|
|
699
|
-
//
|
|
700
|
-
|
|
701
|
-
if (restoredState) {
|
|
702
|
-
logger.info(`Reusing restored session state for: ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
703
|
-
}
|
|
704
|
-
// For restored sessions or when explicitly requested to skip initialization, manually set the initialized flag
|
|
705
|
-
// This allows sending requests like tools/list directly without needing to initialize first
|
|
706
|
-
const shouldManuallyInitialize = !requireInitialize || !!restoredState;
|
|
707
|
-
if (getSessionDebugSetting()) {
|
|
708
|
-
logger.debug(`shouldManuallyInitialize: ${shouldManuallyInitialize} (!requireInitialize: ${!requireInitialize} || restored: ${!!restoredState})`, LOG_MODULES.SESSION_MANAGER);
|
|
709
|
-
}
|
|
710
|
-
if (shouldManuallyInitialize) {
|
|
183
|
+
// For sessions that need to skip initialization, manually set the initialized flag
|
|
184
|
+
if (!requireInitialize) {
|
|
711
185
|
const webTransport = transport._webStandardTransport;
|
|
712
186
|
if (webTransport) {
|
|
713
187
|
webTransport.sessionId = sessionId;
|
|
714
188
|
webTransport._initialized = true;
|
|
715
|
-
// Ensure session property is also set if it exists
|
|
716
189
|
if (webTransport._session !== undefined) {
|
|
717
190
|
webTransport._session = sessionId;
|
|
718
191
|
}
|
|
719
192
|
if (getSessionDebugSetting()) {
|
|
720
|
-
logger.debug(`Manually initialized transport for session: ${sessionId} (skipInitialize: ${!requireInitialize}
|
|
721
|
-
logger.debug(`Transport state after manual init - sessionId: ${webTransport.sessionId}, _initialized: ${webTransport._initialized}, _session: ${webTransport._session}`, LOG_MODULES.SESSION_MANAGER);
|
|
193
|
+
logger.debug(`Manually initialized transport for session: ${sessionId} (skipInitialize: ${!requireInitialize}`, LOG_MODULES.SESSION_MANAGER);
|
|
722
194
|
}
|
|
723
195
|
}
|
|
724
|
-
else {
|
|
725
|
-
logger.error(`Failed to get _webStandardTransport from transport!`, LOG_MODULES.SESSION_MANAGER);
|
|
726
|
-
// Even if we can't manually initialize, continue with normal initialization
|
|
727
|
-
// The transport will be initialized when the first request arrives
|
|
728
|
-
}
|
|
729
196
|
}
|
|
730
197
|
// Always set up message handler for notifications/message
|
|
731
198
|
transport.onmessage = (message) => {
|
|
@@ -755,14 +222,9 @@ export class McpSessionManager {
|
|
|
755
222
|
const server = gateway.createConnectionServer();
|
|
756
223
|
// Ensure server is fully connected before returning session
|
|
757
224
|
await server.connect(transport);
|
|
758
|
-
// Note: StreamableHTTPServerTransport's onsessioninitialized callback is triggered
|
|
759
|
-
// when the first actual request (GET /mcp) arrives, not during connect().
|
|
760
|
-
// Therefore, we don't need to wait for this event - the transport is ready to receive requests.
|
|
761
225
|
if (getSessionDebugSetting()) {
|
|
762
226
|
logger.debug(`StreamableHTTPServerTransport ready for session: ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
763
227
|
}
|
|
764
|
-
// Create/update session state
|
|
765
|
-
this.upsertSessionState(sessionId);
|
|
766
228
|
logger.info(`MCP session created successfully: ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
767
229
|
const session = {
|
|
768
230
|
server,
|
|
@@ -775,14 +237,11 @@ export class McpSessionManager {
|
|
|
775
237
|
/**
|
|
776
238
|
* Cleans up stale sessions based on the configured session timeout.
|
|
777
239
|
*
|
|
778
|
-
* This method is called periodically
|
|
240
|
+
* This method is called periodically to identify and close
|
|
779
241
|
* sessions that haven't been accessed within the configured timeout period
|
|
780
242
|
* (default 30 minutes). It gracefully closes MCP servers and removes sessions
|
|
781
243
|
* from memory to prevent resource leaks.
|
|
782
244
|
*
|
|
783
|
-
* The method logs detailed information about cleaned sessions and maintains
|
|
784
|
-
* active session count for monitoring purposes.
|
|
785
|
-
*
|
|
786
245
|
* @returns {void}
|
|
787
246
|
*
|
|
788
247
|
* @example
|
|
@@ -808,27 +267,8 @@ export class McpSessionManager {
|
|
|
808
267
|
this.sessions.delete(sessionId);
|
|
809
268
|
}
|
|
810
269
|
}
|
|
811
|
-
// Cleanup persisted session states
|
|
812
|
-
const expiredSessionIds = [];
|
|
813
|
-
for (const [sessionId, session] of this.sessionStates.entries()) {
|
|
814
|
-
if (now - session.lastAccessedAt > this.SESSION_TIMEOUT) {
|
|
815
|
-
expiredSessionIds.push(sessionId);
|
|
816
|
-
cleanedCount++;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
for (const sessionId of expiredSessionIds) {
|
|
820
|
-
this.sessionStates.delete(sessionId);
|
|
821
|
-
this.markAsDirty(sessionId);
|
|
822
|
-
logger.debug(`Marking expired session for deletion: ${sessionId}`, LOG_MODULES.SESSION_MANAGER);
|
|
823
|
-
}
|
|
824
|
-
// Immediately flush to delete session files from disk
|
|
825
|
-
if (expiredSessionIds.length > 0) {
|
|
826
|
-
this.flushDirtySessions().catch((error) => {
|
|
827
|
-
logger.error('Failed to flush expired sessions:', error, LOG_MODULES.SESSION_MANAGER);
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
270
|
if (cleanedCount > 0) {
|
|
831
|
-
logger.info(`Cleaned up ${cleanedCount} stale sessions. Active sessions: ${this.sessions.size}
|
|
271
|
+
logger.info(`Cleaned up ${cleanedCount} stale sessions. Active sessions: ${this.sessions.size}`, LOG_MODULES.SESSION_MANAGER);
|
|
832
272
|
}
|
|
833
273
|
}
|
|
834
274
|
}
|