specmem-hardwicksoftware 3.5.99
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 +299 -0
- package/LICENSE.md +6406 -0
- package/README.md +539 -0
- package/bin/AegisTheme.cjs +1022 -0
- package/bin/AnsiRenderer.cjs +1055 -0
- package/bin/BoxRenderer.cjs +605 -0
- package/bin/ClaudeLiveScreen.cjs +1299 -0
- package/bin/DashboardModules.cjs +733 -0
- package/bin/LiveScreenCapture.cjs +1012 -0
- package/bin/MemoryBrowserScreen.cjs +1595 -0
- package/bin/TabManager.cjs +1414 -0
- package/bin/checkAgentStatus-fix.patch +30 -0
- package/bin/mcp-socket-client.cjs +462 -0
- package/bin/screen-utils.cjs +106 -0
- package/bin/specmem-autoclaude.cjs +663 -0
- package/bin/specmem-cleanup.cjs +421 -0
- package/bin/specmem-cli.cjs +794 -0
- package/bin/specmem-console-teamcomms-class.cjs +428 -0
- package/bin/specmem-console.cjs +8104 -0
- package/bin/specmem-statusbar.cjs +530 -0
- package/bootstrap.cjs +5065 -0
- package/claude-hooks/agent-chooser-hook.js +179 -0
- package/claude-hooks/agent-chooser-inject.js +121 -0
- package/claude-hooks/agent-loading-hook.js +990 -0
- package/claude-hooks/agent-output-fader.cjs +542 -0
- package/claude-hooks/agent-output-interceptor.js +193 -0
- package/claude-hooks/agent-type-matcher.js +419 -0
- package/claude-hooks/auto-bypass.py +74 -0
- package/claude-hooks/background-completion-silencer.js +134 -0
- package/claude-hooks/bash-auto-background.js +182 -0
- package/claude-hooks/build-cedict-dictionary.mjs +167 -0
- package/claude-hooks/bullshit-radar.cjs +323 -0
- package/claude-hooks/cedict-codes.json +270 -0
- package/claude-hooks/cedict-extracted.json +22632 -0
- package/claude-hooks/claude-watchdog.sh +401 -0
- package/claude-hooks/context-dedup.cjs +144 -0
- package/claude-hooks/context-yeeter.cjs +244 -0
- package/claude-hooks/debug-suffix.cjs +15 -0
- package/claude-hooks/debug2.cjs +7 -0
- package/claude-hooks/drilldown-enforcer.js +242 -0
- package/claude-hooks/english-morphology-standalone.cjs +149 -0
- package/claude-hooks/english-morphology.cjs +152 -0
- package/claude-hooks/extract-translations.mjs +193 -0
- package/claude-hooks/file-claim-enforcer.cjs +293 -0
- package/claude-hooks/file-claim-enforcer.js +293 -0
- package/claude-hooks/find-collisions.cjs +39 -0
- package/claude-hooks/fix-abbreviations.cjs +60 -0
- package/claude-hooks/fix-collisions.cjs +60 -0
- package/claude-hooks/fix-decompressor.cjs +79 -0
- package/claude-hooks/fix-suffixes.cjs +66 -0
- package/claude-hooks/grammar-engine.cjs +159 -0
- package/claude-hooks/input-aware-improver.js +231 -0
- package/claude-hooks/is-agent.cjs +64 -0
- package/claude-hooks/mega-test.cjs +213 -0
- package/claude-hooks/merge-dictionaries.mjs +207 -0
- package/claude-hooks/merged-codes.cjs +22675 -0
- package/claude-hooks/merged-codes.json +22676 -0
- package/claude-hooks/output-cleaner.cjs +388 -0
- package/claude-hooks/post-write-memory-hook.cjs +430 -0
- package/claude-hooks/quick-test.cjs +24 -0
- package/claude-hooks/quick-test2.cjs +24 -0
- package/claude-hooks/remove-bad-codes.cjs +23 -0
- package/claude-hooks/search-reminder-hook.js +90 -0
- package/claude-hooks/semantic-test.cjs +93 -0
- package/claude-hooks/settings.json +445 -0
- package/claude-hooks/smart-context-hook.cjs +547 -0
- package/claude-hooks/smart-context-hook.js +539 -0
- package/claude-hooks/smart-search-interceptor.js +364 -0
- package/claude-hooks/socket-connect-helper.cjs +235 -0
- package/claude-hooks/specmem/sockets/session-start.lock +1 -0
- package/claude-hooks/specmem-context-hook.cjs +357 -0
- package/claude-hooks/specmem-context-hook.js +357 -0
- package/claude-hooks/specmem-drilldown-hook.cjs +480 -0
- package/claude-hooks/specmem-drilldown-hook.js +480 -0
- package/claude-hooks/specmem-drilldown-setter.js +210 -0
- package/claude-hooks/specmem-paths.cjs +213 -0
- package/claude-hooks/specmem-precompact.js +183 -0
- package/claude-hooks/specmem-session-init.sh +33 -0
- package/claude-hooks/specmem-session-start.cjs +498 -0
- package/claude-hooks/specmem-stop-hook.cjs +73 -0
- package/claude-hooks/specmem-stop-hook.js +5 -0
- package/claude-hooks/specmem-team-comms.cjs +434 -0
- package/claude-hooks/specmem-team-member-inject.js +271 -0
- package/claude-hooks/specmem-unified-hook.py +670 -0
- package/claude-hooks/subagent-loading-hook.js +194 -0
- package/claude-hooks/sysprompt-squisher.cjs +167 -0
- package/claude-hooks/task-progress-hook.js +204 -0
- package/claude-hooks/team-comms-enforcer.cjs +585 -0
- package/claude-hooks/test-accuracy.cjs +27 -0
- package/claude-hooks/test-big.cjs +28 -0
- package/claude-hooks/test-inflectors.cjs +39 -0
- package/claude-hooks/test-pluralize.cjs +37 -0
- package/claude-hooks/test-quick.cjs +8 -0
- package/claude-hooks/test-wink.cjs +20 -0
- package/claude-hooks/token-compressor.cjs +940 -0
- package/claude-hooks/use-code-pointers.cjs +279 -0
- package/commands/COMMAND_TOOL_MAP.md +299 -0
- package/commands/specmem-agents.md +412 -0
- package/commands/specmem-autoclaude.md +295 -0
- package/commands/specmem-changes.md +247 -0
- package/commands/specmem-code.md +103 -0
- package/commands/specmem-configteammembercomms.md +322 -0
- package/commands/specmem-drilldown.md +208 -0
- package/commands/specmem-find.md +195 -0
- package/commands/specmem-getdashboard.md +243 -0
- package/commands/specmem-hooks.md +219 -0
- package/commands/specmem-pointers.md +149 -0
- package/commands/specmem-progress.md +287 -0
- package/commands/specmem-remember.md +123 -0
- package/commands/specmem-service.md +349 -0
- package/commands/specmem-stats.md +189 -0
- package/commands/specmem-team-member.md +409 -0
- package/commands/specmem-webdev.md +583 -0
- package/commands/specmem.md +363 -0
- package/dist/autoStart/index.d.ts +214 -0
- package/dist/autoStart/index.d.ts.map +1 -0
- package/dist/autoStart/index.js +883 -0
- package/dist/autoStart/index.js.map +1 -0
- package/dist/claude-sessions/contextRestorationParser.d.ts +74 -0
- package/dist/claude-sessions/contextRestorationParser.d.ts.map +1 -0
- package/dist/claude-sessions/contextRestorationParser.js +570 -0
- package/dist/claude-sessions/contextRestorationParser.js.map +1 -0
- package/dist/claude-sessions/index.d.ts +13 -0
- package/dist/claude-sessions/index.d.ts.map +1 -0
- package/dist/claude-sessions/index.js +11 -0
- package/dist/claude-sessions/index.js.map +1 -0
- package/dist/claude-sessions/sessionIntegration.d.ts +48 -0
- package/dist/claude-sessions/sessionIntegration.d.ts.map +1 -0
- package/dist/claude-sessions/sessionIntegration.js +146 -0
- package/dist/claude-sessions/sessionIntegration.js.map +1 -0
- package/dist/claude-sessions/sessionParser.d.ts +293 -0
- package/dist/claude-sessions/sessionParser.d.ts.map +1 -0
- package/dist/claude-sessions/sessionParser.js +1028 -0
- package/dist/claude-sessions/sessionParser.js.map +1 -0
- package/dist/claude-sessions/sessionWatcher.d.ts +139 -0
- package/dist/claude-sessions/sessionWatcher.d.ts.map +1 -0
- package/dist/claude-sessions/sessionWatcher.js +722 -0
- package/dist/claude-sessions/sessionWatcher.js.map +1 -0
- package/dist/cli/deploy-to-claude.d.ts +56 -0
- package/dist/cli/deploy-to-claude.d.ts.map +1 -0
- package/dist/cli/deploy-to-claude.js +576 -0
- package/dist/cli/deploy-to-claude.js.map +1 -0
- package/dist/code-explanations/explainCode.d.ts +86 -0
- package/dist/code-explanations/explainCode.d.ts.map +1 -0
- package/dist/code-explanations/explainCode.js +286 -0
- package/dist/code-explanations/explainCode.js.map +1 -0
- package/dist/code-explanations/feedback.d.ts +87 -0
- package/dist/code-explanations/feedback.d.ts.map +1 -0
- package/dist/code-explanations/feedback.js +212 -0
- package/dist/code-explanations/feedback.js.map +1 -0
- package/dist/code-explanations/getRelatedCode.d.ts +80 -0
- package/dist/code-explanations/getRelatedCode.d.ts.map +1 -0
- package/dist/code-explanations/getRelatedCode.js +262 -0
- package/dist/code-explanations/getRelatedCode.js.map +1 -0
- package/dist/code-explanations/index.d.ts +284 -0
- package/dist/code-explanations/index.d.ts.map +1 -0
- package/dist/code-explanations/index.js +249 -0
- package/dist/code-explanations/index.js.map +1 -0
- package/dist/code-explanations/linkCodeToPrompt.d.ts +79 -0
- package/dist/code-explanations/linkCodeToPrompt.d.ts.map +1 -0
- package/dist/code-explanations/linkCodeToPrompt.js +213 -0
- package/dist/code-explanations/linkCodeToPrompt.js.map +1 -0
- package/dist/code-explanations/recallExplanation.d.ts +88 -0
- package/dist/code-explanations/recallExplanation.d.ts.map +1 -0
- package/dist/code-explanations/recallExplanation.js +218 -0
- package/dist/code-explanations/recallExplanation.js.map +1 -0
- package/dist/code-explanations/schema.d.ts +32 -0
- package/dist/code-explanations/schema.d.ts.map +1 -0
- package/dist/code-explanations/schema.js +221 -0
- package/dist/code-explanations/schema.js.map +1 -0
- package/dist/code-explanations/semanticSearch.d.ts +75 -0
- package/dist/code-explanations/semanticSearch.d.ts.map +1 -0
- package/dist/code-explanations/semanticSearch.js +203 -0
- package/dist/code-explanations/semanticSearch.js.map +1 -0
- package/dist/code-explanations/types.d.ts +328 -0
- package/dist/code-explanations/types.d.ts.map +1 -0
- package/dist/code-explanations/types.js +122 -0
- package/dist/code-explanations/types.js.map +1 -0
- package/dist/codebase/codeAnalyzer.d.ts +272 -0
- package/dist/codebase/codeAnalyzer.d.ts.map +1 -0
- package/dist/codebase/codeAnalyzer.js +1353 -0
- package/dist/codebase/codeAnalyzer.js.map +1 -0
- package/dist/codebase/codebaseIndexer.d.ts +360 -0
- package/dist/codebase/codebaseIndexer.d.ts.map +1 -0
- package/dist/codebase/codebaseIndexer.js +1735 -0
- package/dist/codebase/codebaseIndexer.js.map +1 -0
- package/dist/codebase/codebaseTools.d.ts +853 -0
- package/dist/codebase/codebaseTools.d.ts.map +1 -0
- package/dist/codebase/codebaseTools.js +1279 -0
- package/dist/codebase/codebaseTools.js.map +1 -0
- package/dist/codebase/exclusions.d.ts +111 -0
- package/dist/codebase/exclusions.d.ts.map +1 -0
- package/dist/codebase/exclusions.js +771 -0
- package/dist/codebase/exclusions.js.map +1 -0
- package/dist/codebase/fileWatcher.d.ts +135 -0
- package/dist/codebase/fileWatcher.d.ts.map +1 -0
- package/dist/codebase/fileWatcher.js +309 -0
- package/dist/codebase/fileWatcher.js.map +1 -0
- package/dist/codebase/index.d.ts +33 -0
- package/dist/codebase/index.d.ts.map +1 -0
- package/dist/codebase/index.js +77 -0
- package/dist/codebase/index.js.map +1 -0
- package/dist/codebase/ingestion.d.ts +177 -0
- package/dist/codebase/ingestion.d.ts.map +1 -0
- package/dist/codebase/ingestion.js +690 -0
- package/dist/codebase/ingestion.js.map +1 -0
- package/dist/codebase/languageDetection.d.ts +75 -0
- package/dist/codebase/languageDetection.d.ts.map +1 -0
- package/dist/codebase/languageDetection.js +768 -0
- package/dist/codebase/languageDetection.js.map +1 -0
- package/dist/commands/codebaseCommands.d.ts +101 -0
- package/dist/commands/codebaseCommands.d.ts.map +1 -0
- package/dist/commands/codebaseCommands.js +911 -0
- package/dist/commands/codebaseCommands.js.map +1 -0
- package/dist/commands/commandHandler.d.ts +126 -0
- package/dist/commands/commandHandler.d.ts.map +1 -0
- package/dist/commands/commandHandler.js +296 -0
- package/dist/commands/commandHandler.js.map +1 -0
- package/dist/commands/commandLoader.d.ts +103 -0
- package/dist/commands/commandLoader.d.ts.map +1 -0
- package/dist/commands/commandLoader.js +223 -0
- package/dist/commands/commandLoader.js.map +1 -0
- package/dist/commands/contextCommands.d.ts +83 -0
- package/dist/commands/contextCommands.d.ts.map +1 -0
- package/dist/commands/contextCommands.js +512 -0
- package/dist/commands/contextCommands.js.map +1 -0
- package/dist/commands/index.d.ts +24 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +28 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/mcpResources.d.ts +50 -0
- package/dist/commands/mcpResources.d.ts.map +1 -0
- package/dist/commands/mcpResources.js +372 -0
- package/dist/commands/mcpResources.js.map +1 -0
- package/dist/commands/memoryCommands.d.ts +74 -0
- package/dist/commands/memoryCommands.d.ts.map +1 -0
- package/dist/commands/memoryCommands.js +609 -0
- package/dist/commands/memoryCommands.js.map +1 -0
- package/dist/commands/promptCommands.d.ts +91 -0
- package/dist/commands/promptCommands.d.ts.map +1 -0
- package/dist/commands/promptCommands.js +801 -0
- package/dist/commands/promptCommands.js.map +1 -0
- package/dist/commands/teamMemberCommands.d.ts +21 -0
- package/dist/commands/teamMemberCommands.d.ts.map +1 -0
- package/dist/commands/teamMemberCommands.js +137 -0
- package/dist/commands/teamMemberCommands.js.map +1 -0
- package/dist/comms/fileCommsTransport.d.ts +91 -0
- package/dist/comms/fileCommsTransport.d.ts.map +1 -0
- package/dist/comms/fileCommsTransport.js +244 -0
- package/dist/comms/fileCommsTransport.js.map +1 -0
- package/dist/comms/index.d.ts +7 -0
- package/dist/comms/index.d.ts.map +1 -0
- package/dist/comms/index.js +7 -0
- package/dist/comms/index.js.map +1 -0
- package/dist/config/apiKeyDetection.d.ts +41 -0
- package/dist/config/apiKeyDetection.d.ts.map +1 -0
- package/dist/config/apiKeyDetection.js +211 -0
- package/dist/config/apiKeyDetection.js.map +1 -0
- package/dist/config/autoConfig.d.ts +188 -0
- package/dist/config/autoConfig.d.ts.map +1 -0
- package/dist/config/autoConfig.js +850 -0
- package/dist/config/autoConfig.js.map +1 -0
- package/dist/config/configSync.d.ts +119 -0
- package/dist/config/configSync.d.ts.map +1 -0
- package/dist/config/configSync.js +878 -0
- package/dist/config/configSync.js.map +1 -0
- package/dist/config/embeddingTimeouts.d.ts +145 -0
- package/dist/config/embeddingTimeouts.d.ts.map +1 -0
- package/dist/config/embeddingTimeouts.js +255 -0
- package/dist/config/embeddingTimeouts.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +7 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/languageConfig.d.ts +68 -0
- package/dist/config/languageConfig.d.ts.map +1 -0
- package/dist/config/languageConfig.js +473 -0
- package/dist/config/languageConfig.js.map +1 -0
- package/dist/config/password.d.ts +145 -0
- package/dist/config/password.d.ts.map +1 -0
- package/dist/config/password.js +428 -0
- package/dist/config/password.js.map +1 -0
- package/dist/config.d.ts +338 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +1177 -0
- package/dist/config.js.map +1 -0
- package/dist/consolidation.d.ts +44 -0
- package/dist/consolidation.d.ts.map +1 -0
- package/dist/consolidation.js +447 -0
- package/dist/consolidation.js.map +1 -0
- package/dist/constants.d.ts +371 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +552 -0
- package/dist/constants.js.map +1 -0
- package/dist/coordination/TeamMemberRegistry.d.ts +192 -0
- package/dist/coordination/TeamMemberRegistry.d.ts.map +1 -0
- package/dist/coordination/TeamMemberRegistry.js +415 -0
- package/dist/coordination/TeamMemberRegistry.js.map +1 -0
- package/dist/coordination/events.d.ts +369 -0
- package/dist/coordination/events.d.ts.map +1 -0
- package/dist/coordination/events.js +232 -0
- package/dist/coordination/events.js.map +1 -0
- package/dist/coordination/handlers.d.ts +116 -0
- package/dist/coordination/handlers.d.ts.map +1 -0
- package/dist/coordination/handlers.js +400 -0
- package/dist/coordination/handlers.js.map +1 -0
- package/dist/coordination/index.d.ts +14 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +31 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/integration.d.ts +260 -0
- package/dist/coordination/integration.d.ts.map +1 -0
- package/dist/coordination/integration.js +472 -0
- package/dist/coordination/integration.js.map +1 -0
- package/dist/coordination/server.d.ts +266 -0
- package/dist/coordination/server.d.ts.map +1 -0
- package/dist/coordination/server.js +995 -0
- package/dist/coordination/server.js.map +1 -0
- package/dist/coordination/serviceProvider.d.ts +70 -0
- package/dist/coordination/serviceProvider.d.ts.map +1 -0
- package/dist/coordination/serviceProvider.js +273 -0
- package/dist/coordination/serviceProvider.js.map +1 -0
- package/dist/dashboard/api/claudeControl.d.ts +44 -0
- package/dist/dashboard/api/claudeControl.d.ts.map +1 -0
- package/dist/dashboard/api/claudeControl.js +650 -0
- package/dist/dashboard/api/claudeControl.js.map +1 -0
- package/dist/dashboard/api/claudeHistory.d.ts +4 -0
- package/dist/dashboard/api/claudeHistory.d.ts.map +1 -0
- package/dist/dashboard/api/claudeHistory.js +319 -0
- package/dist/dashboard/api/claudeHistory.js.map +1 -0
- package/dist/dashboard/api/dataExport.d.ts +23 -0
- package/dist/dashboard/api/dataExport.d.ts.map +1 -0
- package/dist/dashboard/api/dataExport.js +509 -0
- package/dist/dashboard/api/dataExport.js.map +1 -0
- package/dist/dashboard/api/fileManager.d.ts +39 -0
- package/dist/dashboard/api/fileManager.d.ts.map +1 -0
- package/dist/dashboard/api/fileManager.js +814 -0
- package/dist/dashboard/api/fileManager.js.map +1 -0
- package/dist/dashboard/api/hooks.d.ts +16 -0
- package/dist/dashboard/api/hooks.d.ts.map +1 -0
- package/dist/dashboard/api/hooks.js +342 -0
- package/dist/dashboard/api/hooks.js.map +1 -0
- package/dist/dashboard/api/hotReload.d.ts +14 -0
- package/dist/dashboard/api/hotReload.d.ts.map +1 -0
- package/dist/dashboard/api/hotReload.js +219 -0
- package/dist/dashboard/api/hotReload.js.map +1 -0
- package/dist/dashboard/api/liveSessionStream.d.ts +19 -0
- package/dist/dashboard/api/liveSessionStream.d.ts.map +1 -0
- package/dist/dashboard/api/liveSessionStream.js +430 -0
- package/dist/dashboard/api/liveSessionStream.js.map +1 -0
- package/dist/dashboard/api/memoryRecall.d.ts +20 -0
- package/dist/dashboard/api/memoryRecall.d.ts.map +1 -0
- package/dist/dashboard/api/memoryRecall.js +524 -0
- package/dist/dashboard/api/memoryRecall.js.map +1 -0
- package/dist/dashboard/api/promptSend.d.ts +33 -0
- package/dist/dashboard/api/promptSend.d.ts.map +1 -0
- package/dist/dashboard/api/promptSend.js +544 -0
- package/dist/dashboard/api/promptSend.js.map +1 -0
- package/dist/dashboard/api/settings.d.ts +10 -0
- package/dist/dashboard/api/settings.d.ts.map +1 -0
- package/dist/dashboard/api/settings.js +656 -0
- package/dist/dashboard/api/settings.js.map +1 -0
- package/dist/dashboard/api/setup.d.ts +21 -0
- package/dist/dashboard/api/setup.d.ts.map +1 -0
- package/dist/dashboard/api/setup.js +663 -0
- package/dist/dashboard/api/setup.js.map +1 -0
- package/dist/dashboard/api/specmemTools.d.ts +14 -0
- package/dist/dashboard/api/specmemTools.d.ts.map +1 -0
- package/dist/dashboard/api/specmemTools.js +1059 -0
- package/dist/dashboard/api/specmemTools.js.map +1 -0
- package/dist/dashboard/api/taskTeamMembers.d.ts +8 -0
- package/dist/dashboard/api/taskTeamMembers.d.ts.map +1 -0
- package/dist/dashboard/api/taskTeamMembers.js +136 -0
- package/dist/dashboard/api/taskTeamMembers.js.map +1 -0
- package/dist/dashboard/api/teamMemberDeploy.d.ts +15 -0
- package/dist/dashboard/api/teamMemberDeploy.d.ts.map +1 -0
- package/dist/dashboard/api/teamMemberDeploy.js +421 -0
- package/dist/dashboard/api/teamMemberDeploy.js.map +1 -0
- package/dist/dashboard/api/teamMemberHistory.d.ts +38 -0
- package/dist/dashboard/api/teamMemberHistory.d.ts.map +1 -0
- package/dist/dashboard/api/teamMemberHistory.js +583 -0
- package/dist/dashboard/api/teamMemberHistory.js.map +1 -0
- package/dist/dashboard/api/terminal.d.ts +12 -0
- package/dist/dashboard/api/terminal.d.ts.map +1 -0
- package/dist/dashboard/api/terminal.js +344 -0
- package/dist/dashboard/api/terminal.js.map +1 -0
- package/dist/dashboard/api/terminalInject.d.ts +17 -0
- package/dist/dashboard/api/terminalInject.d.ts.map +1 -0
- package/dist/dashboard/api/terminalInject.js +322 -0
- package/dist/dashboard/api/terminalInject.js.map +1 -0
- package/dist/dashboard/api/terminalStream.d.ts +12 -0
- package/dist/dashboard/api/terminalStream.d.ts.map +1 -0
- package/dist/dashboard/api/terminalStream.js +482 -0
- package/dist/dashboard/api/terminalStream.js.map +1 -0
- package/dist/dashboard/index.d.ts +7 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +7 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/ptyStreamer.d.ts +173 -0
- package/dist/dashboard/ptyStreamer.d.ts.map +1 -0
- package/dist/dashboard/ptyStreamer.js +661 -0
- package/dist/dashboard/ptyStreamer.js.map +1 -0
- package/dist/dashboard/public/DASHBOARD-README.md +378 -0
- package/dist/dashboard/public/INTEGRATION-GUIDE.md +395 -0
- package/dist/dashboard/public/codebase-config.html +1247 -0
- package/dist/dashboard/public/dashboard-v2.html +1942 -0
- package/dist/dashboard/public/data-export.html +819 -0
- package/dist/dashboard/public/example-page.html +164 -0
- package/dist/dashboard/public/file-explorer.html +1023 -0
- package/dist/dashboard/public/hooks.html +1103 -0
- package/dist/dashboard/public/index-improvements.css +499 -0
- package/dist/dashboard/public/index.html +5534 -0
- package/dist/dashboard/public/memory-controls.html +1959 -0
- package/dist/dashboard/public/memory-recall.html +1495 -0
- package/dist/dashboard/public/previews/skeleton-memory-graph.html +361 -0
- package/dist/dashboard/public/previews/skeleton-memory-list.html +366 -0
- package/dist/dashboard/public/previews/skeleton-search-results.html +609 -0
- package/dist/dashboard/public/previews/skeleton-stats-dashboard.html +556 -0
- package/dist/dashboard/public/prompt-console.html +2763 -0
- package/dist/dashboard/public/react-dist/assets/index-CkjobT5B.js +871 -0
- package/dist/dashboard/public/react-dist/assets/index-iRclxMst.css +1 -0
- package/dist/dashboard/public/react-dist/index.html +16 -0
- package/dist/dashboard/public/shared-header.js +325 -0
- package/dist/dashboard/public/shared-language-selector.js +626 -0
- package/dist/dashboard/public/shared-logger.js +66 -0
- package/dist/dashboard/public/shared-nav.js +325 -0
- package/dist/dashboard/public/shared-theme-blue.css +331 -0
- package/dist/dashboard/public/shared-theme.css +813 -0
- package/dist/dashboard/public/shared-toast.js +415 -0
- package/dist/dashboard/public/team-member-history.html +1291 -0
- package/dist/dashboard/public/team-member-spy.html +1199 -0
- package/dist/dashboard/public/team-members.html +3756 -0
- package/dist/dashboard/public/terminal-output.html +1013 -0
- package/dist/dashboard/public/terminal.html +372 -0
- package/dist/dashboard/sessionStore.d.ts +86 -0
- package/dist/dashboard/sessionStore.d.ts.map +1 -0
- package/dist/dashboard/sessionStore.js +262 -0
- package/dist/dashboard/sessionStore.js.map +1 -0
- package/dist/dashboard/standalone.d.ts +27 -0
- package/dist/dashboard/standalone.d.ts.map +1 -0
- package/dist/dashboard/standalone.js +380 -0
- package/dist/dashboard/standalone.js.map +1 -0
- package/dist/dashboard/webServer.d.ts +390 -0
- package/dist/dashboard/webServer.d.ts.map +1 -0
- package/dist/dashboard/webServer.js +4297 -0
- package/dist/dashboard/webServer.js.map +1 -0
- package/dist/dashboard/websocket/teamMemberStream.d.ts +87 -0
- package/dist/dashboard/websocket/teamMemberStream.d.ts.map +1 -0
- package/dist/dashboard/websocket/teamMemberStream.js +366 -0
- package/dist/dashboard/websocket/teamMemberStream.js.map +1 -0
- package/dist/dashboard/websocket/terminalStream.d.ts +130 -0
- package/dist/dashboard/websocket/terminalStream.d.ts.map +1 -0
- package/dist/dashboard/websocket/terminalStream.js +456 -0
- package/dist/dashboard/websocket/terminalStream.js.map +1 -0
- package/dist/database/embeddedPostgres.d.ts +187 -0
- package/dist/database/embeddedPostgres.d.ts.map +1 -0
- package/dist/database/embeddedPostgres.js +763 -0
- package/dist/database/embeddedPostgres.js.map +1 -0
- package/dist/database/index.d.ts +12 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +20 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/initEmbeddedPostgres.d.ts +124 -0
- package/dist/database/initEmbeddedPostgres.d.ts.map +1 -0
- package/dist/database/initEmbeddedPostgres.js +855 -0
- package/dist/database/initEmbeddedPostgres.js.map +1 -0
- package/dist/database.d.ts +256 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +1209 -0
- package/dist/database.js.map +1 -0
- package/dist/db/apiDataManager.d.ts +334 -0
- package/dist/db/apiDataManager.d.ts.map +1 -0
- package/dist/db/apiDataManager.js +631 -0
- package/dist/db/apiDataManager.js.map +1 -0
- package/dist/db/batchOperations.d.ts +154 -0
- package/dist/db/batchOperations.d.ts.map +1 -0
- package/dist/db/batchOperations.js +564 -0
- package/dist/db/batchOperations.js.map +1 -0
- package/dist/db/bigBrainMigrations.d.ts +48 -0
- package/dist/db/bigBrainMigrations.d.ts.map +1 -0
- package/dist/db/bigBrainMigrations.js +4266 -0
- package/dist/db/bigBrainMigrations.js.map +1 -0
- package/dist/db/connectionPoolGoBrrr.d.ts +94 -0
- package/dist/db/connectionPoolGoBrrr.d.ts.map +1 -0
- package/dist/db/connectionPoolGoBrrr.js +548 -0
- package/dist/db/connectionPoolGoBrrr.js.map +1 -0
- package/dist/db/dashboardQueries.d.ts +182 -0
- package/dist/db/dashboardQueries.d.ts.map +1 -0
- package/dist/db/dashboardQueries.js +821 -0
- package/dist/db/dashboardQueries.js.map +1 -0
- package/dist/db/deploymentBootstrap.d.ts +43 -0
- package/dist/db/deploymentBootstrap.d.ts.map +1 -0
- package/dist/db/deploymentBootstrap.js +329 -0
- package/dist/db/deploymentBootstrap.js.map +1 -0
- package/dist/db/dimensionService.d.ts +140 -0
- package/dist/db/dimensionService.d.ts.map +1 -0
- package/dist/db/dimensionService.js +261 -0
- package/dist/db/dimensionService.js.map +1 -0
- package/dist/db/embeddingOverflow.d.ts +69 -0
- package/dist/db/embeddingOverflow.d.ts.map +1 -0
- package/dist/db/embeddingOverflow.js +332 -0
- package/dist/db/embeddingOverflow.js.map +1 -0
- package/dist/db/embeddingOverflow.sql +221 -0
- package/dist/db/findThatShit.d.ts +145 -0
- package/dist/db/findThatShit.d.ts.map +1 -0
- package/dist/db/findThatShit.js +782 -0
- package/dist/db/findThatShit.js.map +1 -0
- package/dist/db/hotPathManager.d.ts +187 -0
- package/dist/db/hotPathManager.d.ts.map +1 -0
- package/dist/db/hotPathManager.js +504 -0
- package/dist/db/hotPathManager.js.map +1 -0
- package/dist/db/index.d.ts +85 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +219 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/memoryDrilldown.sql +99 -0
- package/dist/db/migrate.d.ts +3 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +97 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/migrateJsonToPostgres.d.ts +43 -0
- package/dist/db/migrateJsonToPostgres.d.ts.map +1 -0
- package/dist/db/migrateJsonToPostgres.js +465 -0
- package/dist/db/migrateJsonToPostgres.js.map +1 -0
- package/dist/db/nukeFromOrbit.d.ts +63 -0
- package/dist/db/nukeFromOrbit.d.ts.map +1 -0
- package/dist/db/nukeFromOrbit.js +499 -0
- package/dist/db/nukeFromOrbit.js.map +1 -0
- package/dist/db/processedTraining.sql +60 -0
- package/dist/db/projectNamespacing.d.ts +258 -0
- package/dist/db/projectNamespacing.d.ts.map +1 -0
- package/dist/db/projectNamespacing.js +920 -0
- package/dist/db/projectNamespacing.js.map +1 -0
- package/dist/db/projectNamespacing.sql +374 -0
- package/dist/db/projectSchemaInit.sql +271 -0
- package/dist/db/spatialMemory.d.ts +296 -0
- package/dist/db/spatialMemory.d.ts.map +1 -0
- package/dist/db/spatialMemory.js +818 -0
- package/dist/db/spatialMemory.js.map +1 -0
- package/dist/db/streamingQuery.d.ts +143 -0
- package/dist/db/streamingQuery.d.ts.map +1 -0
- package/dist/db/streamingQuery.js +350 -0
- package/dist/db/streamingQuery.js.map +1 -0
- package/dist/db/teamComms.sql +224 -0
- package/dist/db/yeetStuffInDb.d.ts +72 -0
- package/dist/db/yeetStuffInDb.d.ts.map +1 -0
- package/dist/db/yeetStuffInDb.js +473 -0
- package/dist/db/yeetStuffInDb.js.map +1 -0
- package/dist/embedding-providers/index.d.ts +10 -0
- package/dist/embedding-providers/index.d.ts.map +1 -0
- package/dist/embedding-providers/index.js +12 -0
- package/dist/embedding-providers/index.js.map +1 -0
- package/dist/embeddings/projectionLayer.d.ts +114 -0
- package/dist/embeddings/projectionLayer.d.ts.map +1 -0
- package/dist/embeddings/projectionLayer.js +345 -0
- package/dist/embeddings/projectionLayer.js.map +1 -0
- package/dist/events/Publisher.d.ts +193 -0
- package/dist/events/Publisher.d.ts.map +1 -0
- package/dist/events/Publisher.js +439 -0
- package/dist/events/Publisher.js.map +1 -0
- package/dist/events/config.d.ts +139 -0
- package/dist/events/config.d.ts.map +1 -0
- package/dist/events/config.js +266 -0
- package/dist/events/config.js.map +1 -0
- package/dist/events/index.d.ts +19 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +31 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/integration.d.ts +206 -0
- package/dist/events/integration.d.ts.map +1 -0
- package/dist/events/integration.js +348 -0
- package/dist/events/integration.js.map +1 -0
- package/dist/events/metrics.d.ts +147 -0
- package/dist/events/metrics.d.ts.map +1 -0
- package/dist/events/metrics.js +343 -0
- package/dist/events/metrics.js.map +1 -0
- package/dist/hooks/cli.d.ts +28 -0
- package/dist/hooks/cli.d.ts.map +1 -0
- package/dist/hooks/cli.js +118 -0
- package/dist/hooks/cli.js.map +1 -0
- package/dist/hooks/contextInjectionHook.d.ts +60 -0
- package/dist/hooks/contextInjectionHook.d.ts.map +1 -0
- package/dist/hooks/contextInjectionHook.js +294 -0
- package/dist/hooks/contextInjectionHook.js.map +1 -0
- package/dist/hooks/drilldownHook.d.ts +125 -0
- package/dist/hooks/drilldownHook.d.ts.map +1 -0
- package/dist/hooks/drilldownHook.js +181 -0
- package/dist/hooks/drilldownHook.js.map +1 -0
- package/dist/hooks/hookManager.d.ts +180 -0
- package/dist/hooks/hookManager.d.ts.map +1 -0
- package/dist/hooks/hookManager.js +782 -0
- package/dist/hooks/hookManager.js.map +1 -0
- package/dist/hooks/index.d.ts +62 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +66 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/lowContextHook.d.ts +71 -0
- package/dist/hooks/lowContextHook.d.ts.map +1 -0
- package/dist/hooks/lowContextHook.js +258 -0
- package/dist/hooks/lowContextHook.js.map +1 -0
- package/dist/hooks/simpleContextHook.d.ts +65 -0
- package/dist/hooks/simpleContextHook.d.ts.map +1 -0
- package/dist/hooks/simpleContextHook.js +194 -0
- package/dist/hooks/simpleContextHook.js.map +1 -0
- package/dist/hooks/teamFramingCli.d.ts +56 -0
- package/dist/hooks/teamFramingCli.d.ts.map +1 -0
- package/dist/hooks/teamFramingCli.js +264 -0
- package/dist/hooks/teamFramingCli.js.map +1 -0
- package/dist/hooks/teamMemberPrepromptHook.d.ts +150 -0
- package/dist/hooks/teamMemberPrepromptHook.d.ts.map +1 -0
- package/dist/hooks/teamMemberPrepromptHook.js +308 -0
- package/dist/hooks/teamMemberPrepromptHook.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4433 -0
- package/dist/index.js.map +1 -0
- package/dist/init/claudeConfigInjector.d.ts +116 -0
- package/dist/init/claudeConfigInjector.d.ts.map +1 -0
- package/dist/init/claudeConfigInjector.js +1154 -0
- package/dist/init/claudeConfigInjector.js.map +1 -0
- package/dist/installer/autoInstall.d.ts +72 -0
- package/dist/installer/autoInstall.d.ts.map +1 -0
- package/dist/installer/autoInstall.js +617 -0
- package/dist/installer/autoInstall.js.map +1 -0
- package/dist/installer/dbSetup.d.ts +84 -0
- package/dist/installer/dbSetup.d.ts.map +1 -0
- package/dist/installer/dbSetup.js +350 -0
- package/dist/installer/dbSetup.js.map +1 -0
- package/dist/installer/firstRun.d.ts +49 -0
- package/dist/installer/firstRun.d.ts.map +1 -0
- package/dist/installer/firstRun.js +207 -0
- package/dist/installer/firstRun.js.map +1 -0
- package/dist/installer/index.d.ts +10 -0
- package/dist/installer/index.d.ts.map +1 -0
- package/dist/installer/index.js +10 -0
- package/dist/installer/index.js.map +1 -0
- package/dist/installer/silentAutoInstall.d.ts +99 -0
- package/dist/installer/silentAutoInstall.d.ts.map +1 -0
- package/dist/installer/silentAutoInstall.js +491 -0
- package/dist/installer/silentAutoInstall.js.map +1 -0
- package/dist/installer/systemDeps.d.ts +54 -0
- package/dist/installer/systemDeps.d.ts.map +1 -0
- package/dist/installer/systemDeps.js +322 -0
- package/dist/installer/systemDeps.js.map +1 -0
- package/dist/mcp/cliNotifications.d.ts +133 -0
- package/dist/mcp/cliNotifications.d.ts.map +1 -0
- package/dist/mcp/cliNotifications.js +289 -0
- package/dist/mcp/cliNotifications.js.map +1 -0
- package/dist/mcp/embeddingServerManager.d.ts +307 -0
- package/dist/mcp/embeddingServerManager.d.ts.map +1 -0
- package/dist/mcp/embeddingServerManager.js +2081 -0
- package/dist/mcp/embeddingServerManager.js.map +1 -0
- package/dist/mcp/healthMonitor.d.ts +196 -0
- package/dist/mcp/healthMonitor.d.ts.map +1 -0
- package/dist/mcp/healthMonitor.js +685 -0
- package/dist/mcp/healthMonitor.js.map +1 -0
- package/dist/mcp/hotReloadManager.d.ts +101 -0
- package/dist/mcp/hotReloadManager.d.ts.map +1 -0
- package/dist/mcp/hotReloadManager.js +251 -0
- package/dist/mcp/hotReloadManager.js.map +1 -0
- package/dist/mcp/index.d.ts +16 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +22 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/mcpProtocolHandler.d.ts +64 -0
- package/dist/mcp/mcpProtocolHandler.d.ts.map +1 -0
- package/dist/mcp/mcpProtocolHandler.js +253 -0
- package/dist/mcp/mcpProtocolHandler.js.map +1 -0
- package/dist/mcp/miniCOTServerManager.d.ts +336 -0
- package/dist/mcp/miniCOTServerManager.d.ts.map +1 -0
- package/dist/mcp/miniCOTServerManager.js +1384 -0
- package/dist/mcp/miniCOTServerManager.js.map +1 -0
- package/dist/mcp/promptExecutor.d.ts +188 -0
- package/dist/mcp/promptExecutor.d.ts.map +1 -0
- package/dist/mcp/promptExecutor.js +469 -0
- package/dist/mcp/promptExecutor.js.map +1 -0
- package/dist/mcp/reloadBroadcast.d.ts +127 -0
- package/dist/mcp/reloadBroadcast.d.ts.map +1 -0
- package/dist/mcp/reloadBroadcast.js +275 -0
- package/dist/mcp/reloadBroadcast.js.map +1 -0
- package/dist/mcp/resilientTransport.d.ts +249 -0
- package/dist/mcp/resilientTransport.d.ts.map +1 -0
- package/dist/mcp/resilientTransport.js +931 -0
- package/dist/mcp/resilientTransport.js.map +1 -0
- package/dist/mcp/samplingHandler.d.ts +129 -0
- package/dist/mcp/samplingHandler.d.ts.map +1 -0
- package/dist/mcp/samplingHandler.js +276 -0
- package/dist/mcp/samplingHandler.js.map +1 -0
- package/dist/mcp/specMemServer.d.ts +305 -0
- package/dist/mcp/specMemServer.d.ts.map +1 -0
- package/dist/mcp/specMemServer.js +2048 -0
- package/dist/mcp/specMemServer.js.map +1 -0
- package/dist/mcp/toolRegistry.d.ts +122 -0
- package/dist/mcp/toolRegistry.d.ts.map +1 -0
- package/dist/mcp/toolRegistry.js +609 -0
- package/dist/mcp/toolRegistry.js.map +1 -0
- package/dist/mcp/tools/embeddingControl.d.ts +114 -0
- package/dist/mcp/tools/embeddingControl.d.ts.map +1 -0
- package/dist/mcp/tools/embeddingControl.js +222 -0
- package/dist/mcp/tools/embeddingControl.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +10 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +17 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/teamComms.d.ts +444 -0
- package/dist/mcp/tools/teamComms.d.ts.map +1 -0
- package/dist/mcp/tools/teamComms.js +1953 -0
- package/dist/mcp/tools/teamComms.js.map +1 -0
- package/dist/mcp/triggerSystem.d.ts +129 -0
- package/dist/mcp/triggerSystem.d.ts.map +1 -0
- package/dist/mcp/triggerSystem.js +363 -0
- package/dist/mcp/triggerSystem.js.map +1 -0
- package/dist/mcp/watcherIntegration.d.ts +77 -0
- package/dist/mcp/watcherIntegration.d.ts.map +1 -0
- package/dist/mcp/watcherIntegration.js +428 -0
- package/dist/mcp/watcherIntegration.js.map +1 -0
- package/dist/mcp/watcherToolWrappers.d.ts +89 -0
- package/dist/mcp/watcherToolWrappers.d.ts.map +1 -0
- package/dist/mcp/watcherToolWrappers.js +91 -0
- package/dist/mcp/watcherToolWrappers.js.map +1 -0
- package/dist/memorization/claudeCodeMigration.d.ts +34 -0
- package/dist/memorization/claudeCodeMigration.d.ts.map +1 -0
- package/dist/memorization/claudeCodeMigration.js +210 -0
- package/dist/memorization/claudeCodeMigration.js.map +1 -0
- package/dist/memorization/claudeCodeTracker.d.ts +147 -0
- package/dist/memorization/claudeCodeTracker.d.ts.map +1 -0
- package/dist/memorization/claudeCodeTracker.js +424 -0
- package/dist/memorization/claudeCodeTracker.js.map +1 -0
- package/dist/memorization/codeMemorizer.d.ts +158 -0
- package/dist/memorization/codeMemorizer.d.ts.map +1 -0
- package/dist/memorization/codeMemorizer.js +357 -0
- package/dist/memorization/codeMemorizer.js.map +1 -0
- package/dist/memorization/codeRecall.d.ts +156 -0
- package/dist/memorization/codeRecall.d.ts.map +1 -0
- package/dist/memorization/codeRecall.js +499 -0
- package/dist/memorization/codeRecall.js.map +1 -0
- package/dist/memorization/index.d.ts +55 -0
- package/dist/memorization/index.d.ts.map +1 -0
- package/dist/memorization/index.js +64 -0
- package/dist/memorization/index.js.map +1 -0
- package/dist/memorization/memorizationTools.d.ts +413 -0
- package/dist/memorization/memorizationTools.d.ts.map +1 -0
- package/dist/memorization/memorizationTools.js +513 -0
- package/dist/memorization/memorizationTools.js.map +1 -0
- package/dist/memorization/watcherIntegration.d.ts +100 -0
- package/dist/memorization/watcherIntegration.d.ts.map +1 -0
- package/dist/memorization/watcherIntegration.js +196 -0
- package/dist/memorization/watcherIntegration.js.map +1 -0
- package/dist/memory/humanLikeMemory.d.ts +206 -0
- package/dist/memory/humanLikeMemory.d.ts.map +1 -0
- package/dist/memory/humanLikeMemory.js +603 -0
- package/dist/memory/humanLikeMemory.js.map +1 -0
- package/dist/memory/index.d.ts +22 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +24 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/memoryEvolutionMigration.d.ts +36 -0
- package/dist/memory/memoryEvolutionMigration.d.ts.map +1 -0
- package/dist/memory/memoryEvolutionMigration.js +371 -0
- package/dist/memory/memoryEvolutionMigration.js.map +1 -0
- package/dist/memory/quadrantSearch.d.ts +221 -0
- package/dist/memory/quadrantSearch.d.ts.map +1 -0
- package/dist/memory/quadrantSearch.js +897 -0
- package/dist/memory/quadrantSearch.js.map +1 -0
- package/dist/middleware/apiVersioning.d.ts +83 -0
- package/dist/middleware/apiVersioning.d.ts.map +1 -0
- package/dist/middleware/apiVersioning.js +152 -0
- package/dist/middleware/apiVersioning.js.map +1 -0
- package/dist/middleware/compression.d.ts +48 -0
- package/dist/middleware/compression.d.ts.map +1 -0
- package/dist/middleware/compression.js +240 -0
- package/dist/middleware/compression.js.map +1 -0
- package/dist/middleware/csrf.d.ts +118 -0
- package/dist/middleware/csrf.d.ts.map +1 -0
- package/dist/middleware/csrf.js +300 -0
- package/dist/middleware/csrf.js.map +1 -0
- package/dist/middleware/index.d.ts +13 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +17 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/wsRateLimiter.d.ts +129 -0
- package/dist/middleware/wsRateLimiter.d.ts.map +1 -0
- package/dist/middleware/wsRateLimiter.js +279 -0
- package/dist/middleware/wsRateLimiter.js.map +1 -0
- package/dist/migrations/run.d.ts +2 -0
- package/dist/migrations/run.d.ts.map +1 -0
- package/dist/migrations/run.js +25 -0
- package/dist/migrations/run.js.map +1 -0
- package/dist/migrations/syncDimensions.d.ts +24 -0
- package/dist/migrations/syncDimensions.d.ts.map +1 -0
- package/dist/migrations/syncDimensions.js +140 -0
- package/dist/migrations/syncDimensions.js.map +1 -0
- package/dist/migrations/teamComms.d.ts +16 -0
- package/dist/migrations/teamComms.d.ts.map +1 -0
- package/dist/migrations/teamComms.js +210 -0
- package/dist/migrations/teamComms.js.map +1 -0
- package/dist/openapi/index.d.ts +10 -0
- package/dist/openapi/index.d.ts.map +1 -0
- package/dist/openapi/index.js +10 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/openapi/spec.d.ts +902 -0
- package/dist/openapi/spec.d.ts.map +1 -0
- package/dist/openapi/spec.js +733 -0
- package/dist/openapi/spec.js.map +1 -0
- package/dist/packages/dependencyHistory.d.ts +113 -0
- package/dist/packages/dependencyHistory.d.ts.map +1 -0
- package/dist/packages/dependencyHistory.js +360 -0
- package/dist/packages/dependencyHistory.js.map +1 -0
- package/dist/packages/index.d.ts +30 -0
- package/dist/packages/index.d.ts.map +1 -0
- package/dist/packages/index.js +65 -0
- package/dist/packages/index.js.map +1 -0
- package/dist/packages/packageTools.d.ts +255 -0
- package/dist/packages/packageTools.d.ts.map +1 -0
- package/dist/packages/packageTools.js +242 -0
- package/dist/packages/packageTools.js.map +1 -0
- package/dist/packages/packageTracker.d.ts +98 -0
- package/dist/packages/packageTracker.d.ts.map +1 -0
- package/dist/packages/packageTracker.js +268 -0
- package/dist/packages/packageTracker.js.map +1 -0
- package/dist/packages/packageWatcher.d.ts +62 -0
- package/dist/packages/packageWatcher.d.ts.map +1 -0
- package/dist/packages/packageWatcher.js +146 -0
- package/dist/packages/packageWatcher.js.map +1 -0
- package/dist/providers/MiniCOTProvider.d.ts +48 -0
- package/dist/providers/MiniCOTProvider.d.ts.map +1 -0
- package/dist/providers/MiniCOTProvider.js +98 -0
- package/dist/providers/MiniCOTProvider.js.map +1 -0
- package/dist/reminders/index.d.ts +5 -0
- package/dist/reminders/index.d.ts.map +1 -0
- package/dist/reminders/index.js +5 -0
- package/dist/reminders/index.js.map +1 -0
- package/dist/reminders/skillReminder.d.ts +131 -0
- package/dist/reminders/skillReminder.d.ts.map +1 -0
- package/dist/reminders/skillReminder.js +386 -0
- package/dist/reminders/skillReminder.js.map +1 -0
- package/dist/search.d.ts +35 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +574 -0
- package/dist/search.js.map +1 -0
- package/dist/security/localhostOnly.d.ts +36 -0
- package/dist/security/localhostOnly.d.ts.map +1 -0
- package/dist/security/localhostOnly.js +101 -0
- package/dist/security/localhostOnly.js.map +1 -0
- package/dist/services/CameraZoomSearch.d.ts +206 -0
- package/dist/services/CameraZoomSearch.d.ts.map +1 -0
- package/dist/services/CameraZoomSearch.js +669 -0
- package/dist/services/CameraZoomSearch.js.map +1 -0
- package/dist/services/DataFlowPipeline.d.ts +111 -0
- package/dist/services/DataFlowPipeline.d.ts.map +1 -0
- package/dist/services/DataFlowPipeline.js +379 -0
- package/dist/services/DataFlowPipeline.js.map +1 -0
- package/dist/services/DimensionAdapter.d.ts +194 -0
- package/dist/services/DimensionAdapter.d.ts.map +1 -0
- package/dist/services/DimensionAdapter.js +566 -0
- package/dist/services/DimensionAdapter.js.map +1 -0
- package/dist/services/DimensionService.d.ts +252 -0
- package/dist/services/DimensionService.d.ts.map +1 -0
- package/dist/services/DimensionService.js +564 -0
- package/dist/services/DimensionService.js.map +1 -0
- package/dist/services/EmbeddingQueue.d.ts +71 -0
- package/dist/services/EmbeddingQueue.d.ts.map +1 -0
- package/dist/services/EmbeddingQueue.js +258 -0
- package/dist/services/EmbeddingQueue.js.map +1 -0
- package/dist/services/MemoryDrilldown.d.ts +226 -0
- package/dist/services/MemoryDrilldown.d.ts.map +1 -0
- package/dist/services/MemoryDrilldown.js +479 -0
- package/dist/services/MemoryDrilldown.js.map +1 -0
- package/dist/services/MiniCOTScorer.d.ts +140 -0
- package/dist/services/MiniCOTScorer.d.ts.map +1 -0
- package/dist/services/MiniCOTScorer.js +292 -0
- package/dist/services/MiniCOTScorer.js.map +1 -0
- package/dist/services/ProjectContext.d.ts +342 -0
- package/dist/services/ProjectContext.d.ts.map +1 -0
- package/dist/services/ProjectContext.js +667 -0
- package/dist/services/ProjectContext.js.map +1 -0
- package/dist/services/ResponseCompactor.d.ts +135 -0
- package/dist/services/ResponseCompactor.d.ts.map +1 -0
- package/dist/services/ResponseCompactor.js +501 -0
- package/dist/services/ResponseCompactor.js.map +1 -0
- package/dist/services/TeamCommsDbService.d.ts +202 -0
- package/dist/services/TeamCommsDbService.d.ts.map +1 -0
- package/dist/services/TeamCommsDbService.js +526 -0
- package/dist/services/TeamCommsDbService.js.map +1 -0
- package/dist/services/UnifiedPasswordService.d.ts +166 -0
- package/dist/services/UnifiedPasswordService.d.ts.map +1 -0
- package/dist/services/UnifiedPasswordService.js +587 -0
- package/dist/services/UnifiedPasswordService.js.map +1 -0
- package/dist/services/adaptiveSearchConfig.d.ts +64 -0
- package/dist/services/adaptiveSearchConfig.d.ts.map +1 -0
- package/dist/services/adaptiveSearchConfig.js +187 -0
- package/dist/services/adaptiveSearchConfig.js.map +1 -0
- package/dist/skills/index.d.ts +8 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +8 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/skillScanner.d.ts +203 -0
- package/dist/skills/skillScanner.d.ts.map +1 -0
- package/dist/skills/skillScanner.js +559 -0
- package/dist/skills/skillScanner.js.map +1 -0
- package/dist/skills/skillsResource.d.ts +69 -0
- package/dist/skills/skillsResource.d.ts.map +1 -0
- package/dist/skills/skillsResource.js +257 -0
- package/dist/skills/skillsResource.js.map +1 -0
- package/dist/startup/index.d.ts +9 -0
- package/dist/startup/index.d.ts.map +1 -0
- package/dist/startup/index.js +12 -0
- package/dist/startup/index.js.map +1 -0
- package/dist/startup/startupIndexing.d.ts +80 -0
- package/dist/startup/startupIndexing.d.ts.map +1 -0
- package/dist/startup/startupIndexing.js +463 -0
- package/dist/startup/startupIndexing.js.map +1 -0
- package/dist/startup/validation.d.ts +89 -0
- package/dist/startup/validation.d.ts.map +1 -0
- package/dist/startup/validation.js +590 -0
- package/dist/startup/validation.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +4 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/overflowManager.d.ts +80 -0
- package/dist/storage/overflowManager.d.ts.map +1 -0
- package/dist/storage/overflowManager.js +317 -0
- package/dist/storage/overflowManager.js.map +1 -0
- package/dist/storage/overflowStorage.d.ts +69 -0
- package/dist/storage/overflowStorage.d.ts.map +1 -0
- package/dist/storage/overflowStorage.js +379 -0
- package/dist/storage/overflowStorage.js.map +1 -0
- package/dist/storage/toonFormat.d.ts +50 -0
- package/dist/storage/toonFormat.d.ts.map +1 -0
- package/dist/storage/toonFormat.js +224 -0
- package/dist/storage/toonFormat.js.map +1 -0
- package/dist/team-members/communication.d.ts +237 -0
- package/dist/team-members/communication.d.ts.map +1 -0
- package/dist/team-members/communication.js +650 -0
- package/dist/team-members/communication.js.map +1 -0
- package/dist/team-members/index.d.ts +14 -0
- package/dist/team-members/index.d.ts.map +1 -0
- package/dist/team-members/index.js +22 -0
- package/dist/team-members/index.js.map +1 -0
- package/dist/team-members/taskOrchestrator.d.ts +224 -0
- package/dist/team-members/taskOrchestrator.d.ts.map +1 -0
- package/dist/team-members/taskOrchestrator.js +574 -0
- package/dist/team-members/taskOrchestrator.js.map +1 -0
- package/dist/team-members/taskTeamMemberLogger.d.ts +157 -0
- package/dist/team-members/taskTeamMemberLogger.d.ts.map +1 -0
- package/dist/team-members/taskTeamMemberLogger.js +478 -0
- package/dist/team-members/taskTeamMemberLogger.js.map +1 -0
- package/dist/team-members/teamCommsService.d.ts +221 -0
- package/dist/team-members/teamCommsService.d.ts.map +1 -0
- package/dist/team-members/teamCommsService.js +628 -0
- package/dist/team-members/teamCommsService.js.map +1 -0
- package/dist/team-members/teamMemberChannels.d.ts +217 -0
- package/dist/team-members/teamMemberChannels.d.ts.map +1 -0
- package/dist/team-members/teamMemberChannels.js +687 -0
- package/dist/team-members/teamMemberChannels.js.map +1 -0
- package/dist/team-members/teamMemberDashboard.d.ts +222 -0
- package/dist/team-members/teamMemberDashboard.d.ts.map +1 -0
- package/dist/team-members/teamMemberDashboard.js +610 -0
- package/dist/team-members/teamMemberDashboard.js.map +1 -0
- package/dist/team-members/teamMemberDeployment.d.ts +60 -0
- package/dist/team-members/teamMemberDeployment.d.ts.map +1 -0
- package/dist/team-members/teamMemberDeployment.js +429 -0
- package/dist/team-members/teamMemberDeployment.js.map +1 -0
- package/dist/team-members/teamMemberDiscovery.d.ts +178 -0
- package/dist/team-members/teamMemberDiscovery.d.ts.map +1 -0
- package/dist/team-members/teamMemberDiscovery.js +446 -0
- package/dist/team-members/teamMemberDiscovery.js.map +1 -0
- package/dist/team-members/teamMemberHistory.d.ts +80 -0
- package/dist/team-members/teamMemberHistory.d.ts.map +1 -0
- package/dist/team-members/teamMemberHistory.js +426 -0
- package/dist/team-members/teamMemberHistory.js.map +1 -0
- package/dist/team-members/teamMemberLimits.d.ts +66 -0
- package/dist/team-members/teamMemberLimits.d.ts.map +1 -0
- package/dist/team-members/teamMemberLimits.js +259 -0
- package/dist/team-members/teamMemberLimits.js.map +1 -0
- package/dist/team-members/teamMemberRegistry.d.ts +199 -0
- package/dist/team-members/teamMemberRegistry.d.ts.map +1 -0
- package/dist/team-members/teamMemberRegistry.js +572 -0
- package/dist/team-members/teamMemberRegistry.js.map +1 -0
- package/dist/team-members/teamMemberTracker.d.ts +148 -0
- package/dist/team-members/teamMemberTracker.d.ts.map +1 -0
- package/dist/team-members/teamMemberTracker.js +828 -0
- package/dist/team-members/teamMemberTracker.js.map +1 -0
- package/dist/team-members/workers/aiWorker.d.ts +53 -0
- package/dist/team-members/workers/aiWorker.d.ts.map +1 -0
- package/dist/team-members/workers/aiWorker.js +322 -0
- package/dist/team-members/workers/aiWorker.js.map +1 -0
- package/dist/team-members/workers/baseWorker.d.ts +101 -0
- package/dist/team-members/workers/baseWorker.d.ts.map +1 -0
- package/dist/team-members/workers/baseWorker.js +179 -0
- package/dist/team-members/workers/baseWorker.js.map +1 -0
- package/dist/team-members/workers/codeReviewWorker.d.ts +3 -0
- package/dist/team-members/workers/codeReviewWorker.d.ts.map +1 -0
- package/dist/team-members/workers/codeReviewWorker.js +144 -0
- package/dist/team-members/workers/codeReviewWorker.js.map +1 -0
- package/dist/team-members/workers/index.d.ts +7 -0
- package/dist/team-members/workers/index.d.ts.map +1 -0
- package/dist/team-members/workers/index.js +7 -0
- package/dist/team-members/workers/index.js.map +1 -0
- package/dist/team-members/workers/repairWorker.d.ts +9 -0
- package/dist/team-members/workers/repairWorker.d.ts.map +1 -0
- package/dist/team-members/workers/repairWorker.js +102 -0
- package/dist/team-members/workers/repairWorker.js.map +1 -0
- package/dist/team-members/workers/sendToTeamMemberB.d.ts +9 -0
- package/dist/team-members/workers/sendToTeamMemberB.d.ts.map +1 -0
- package/dist/team-members/workers/sendToTeamMemberB.js +105 -0
- package/dist/team-members/workers/sendToTeamMemberB.js.map +1 -0
- package/dist/team-members/workers/specmemClient.d.ts +179 -0
- package/dist/team-members/workers/specmemClient.d.ts.map +1 -0
- package/dist/team-members/workers/specmemClient.js +421 -0
- package/dist/team-members/workers/specmemClient.js.map +1 -0
- package/dist/team-members/workers/testCommunication.d.ts +8 -0
- package/dist/team-members/workers/testCommunication.d.ts.map +1 -0
- package/dist/team-members/workers/testCommunication.js +136 -0
- package/dist/team-members/workers/testCommunication.js.map +1 -0
- package/dist/team-members/workers/testCommunicationSuite.d.ts +26 -0
- package/dist/team-members/workers/testCommunicationSuite.d.ts.map +1 -0
- package/dist/team-members/workers/testCommunicationSuite.js +415 -0
- package/dist/team-members/workers/testCommunicationSuite.js.map +1 -0
- package/dist/team-members/workers/testWorker.d.ts +9 -0
- package/dist/team-members/workers/testWorker.d.ts.map +1 -0
- package/dist/team-members/workers/testWorker.js +107 -0
- package/dist/team-members/workers/testWorker.js.map +1 -0
- package/dist/tools/agentDefinitions.d.ts +30 -0
- package/dist/tools/agentDefinitions.d.ts.map +1 -0
- package/dist/tools/agentDefinitions.js +166 -0
- package/dist/tools/agentDefinitions.js.map +1 -0
- package/dist/tools/goofy/checkSyncStatus.d.ts +68 -0
- package/dist/tools/goofy/checkSyncStatus.d.ts.map +1 -0
- package/dist/tools/goofy/checkSyncStatus.js +112 -0
- package/dist/tools/goofy/checkSyncStatus.js.map +1 -0
- package/dist/tools/goofy/codeMemoryLink.d.ts +82 -0
- package/dist/tools/goofy/codeMemoryLink.d.ts.map +1 -0
- package/dist/tools/goofy/codeMemoryLink.js +212 -0
- package/dist/tools/goofy/codeMemoryLink.js.map +1 -0
- package/dist/tools/goofy/compareInstanceMemory.d.ts +97 -0
- package/dist/tools/goofy/compareInstanceMemory.d.ts.map +1 -0
- package/dist/tools/goofy/compareInstanceMemory.js +218 -0
- package/dist/tools/goofy/compareInstanceMemory.js.map +1 -0
- package/dist/tools/goofy/createReasoningChain.d.ts +135 -0
- package/dist/tools/goofy/createReasoningChain.d.ts.map +1 -0
- package/dist/tools/goofy/createReasoningChain.js +257 -0
- package/dist/tools/goofy/createReasoningChain.js.map +1 -0
- package/dist/tools/goofy/deployTeamMember.d.ts +63 -0
- package/dist/tools/goofy/deployTeamMember.d.ts.map +1 -0
- package/dist/tools/goofy/deployTeamMember.js +103 -0
- package/dist/tools/goofy/deployTeamMember.js.map +1 -0
- package/dist/tools/goofy/drillDown.d.ts +143 -0
- package/dist/tools/goofy/drillDown.d.ts.map +1 -0
- package/dist/tools/goofy/drillDown.js +288 -0
- package/dist/tools/goofy/drillDown.js.map +1 -0
- package/dist/tools/goofy/extractClaudeSessions.d.ts +90 -0
- package/dist/tools/goofy/extractClaudeSessions.d.ts.map +1 -0
- package/dist/tools/goofy/extractClaudeSessions.js +277 -0
- package/dist/tools/goofy/extractClaudeSessions.js.map +1 -0
- package/dist/tools/goofy/extractContextRestorations.d.ts +70 -0
- package/dist/tools/goofy/extractContextRestorations.d.ts.map +1 -0
- package/dist/tools/goofy/extractContextRestorations.js +100 -0
- package/dist/tools/goofy/extractContextRestorations.js.map +1 -0
- package/dist/tools/goofy/findCodePointers.d.ts +364 -0
- package/dist/tools/goofy/findCodePointers.d.ts.map +1 -0
- package/dist/tools/goofy/findCodePointers.js +1764 -0
- package/dist/tools/goofy/findCodePointers.js.map +1 -0
- package/dist/tools/goofy/findMemoryGallery.d.ts +40 -0
- package/dist/tools/goofy/findMemoryGallery.d.ts.map +1 -0
- package/dist/tools/goofy/findMemoryGallery.js +66 -0
- package/dist/tools/goofy/findMemoryGallery.js.map +1 -0
- package/dist/tools/goofy/findWhatISaid.d.ts +300 -0
- package/dist/tools/goofy/findWhatISaid.d.ts.map +1 -0
- package/dist/tools/goofy/findWhatISaid.js +2547 -0
- package/dist/tools/goofy/findWhatISaid.js.map +1 -0
- package/dist/tools/goofy/forceResync.d.ts +57 -0
- package/dist/tools/goofy/forceResync.d.ts.map +1 -0
- package/dist/tools/goofy/forceResync.js +100 -0
- package/dist/tools/goofy/forceResync.js.map +1 -0
- package/dist/tools/goofy/getActiveTeamMembers.d.ts +48 -0
- package/dist/tools/goofy/getActiveTeamMembers.d.ts.map +1 -0
- package/dist/tools/goofy/getActiveTeamMembers.js +136 -0
- package/dist/tools/goofy/getActiveTeamMembers.js.map +1 -0
- package/dist/tools/goofy/getMemoryFull.d.ts +34 -0
- package/dist/tools/goofy/getMemoryFull.d.ts.map +1 -0
- package/dist/tools/goofy/getMemoryFull.js +58 -0
- package/dist/tools/goofy/getMemoryFull.js.map +1 -0
- package/dist/tools/goofy/getSessionWatcherStatus.d.ts +43 -0
- package/dist/tools/goofy/getSessionWatcherStatus.d.ts.map +1 -0
- package/dist/tools/goofy/getSessionWatcherStatus.js +92 -0
- package/dist/tools/goofy/getSessionWatcherStatus.js.map +1 -0
- package/dist/tools/goofy/getTeamMemberOutput.d.ts +35 -0
- package/dist/tools/goofy/getTeamMemberOutput.d.ts.map +1 -0
- package/dist/tools/goofy/getTeamMemberOutput.js +62 -0
- package/dist/tools/goofy/getTeamMemberOutput.js.map +1 -0
- package/dist/tools/goofy/getTeamMemberScreen.d.ts +28 -0
- package/dist/tools/goofy/getTeamMemberScreen.d.ts.map +1 -0
- package/dist/tools/goofy/getTeamMemberScreen.js +59 -0
- package/dist/tools/goofy/getTeamMemberScreen.js.map +1 -0
- package/dist/tools/goofy/getTeamMemberStatus.d.ts +33 -0
- package/dist/tools/goofy/getTeamMemberStatus.d.ts.map +1 -0
- package/dist/tools/goofy/getTeamMemberStatus.js +56 -0
- package/dist/tools/goofy/getTeamMemberStatus.js.map +1 -0
- package/dist/tools/goofy/index.d.ts +39 -0
- package/dist/tools/goofy/index.d.ts.map +1 -0
- package/dist/tools/goofy/index.js +51 -0
- package/dist/tools/goofy/index.js.map +1 -0
- package/dist/tools/goofy/interveneTeamMember.d.ts +33 -0
- package/dist/tools/goofy/interveneTeamMember.d.ts.map +1 -0
- package/dist/tools/goofy/interveneTeamMember.js +69 -0
- package/dist/tools/goofy/interveneTeamMember.js.map +1 -0
- package/dist/tools/goofy/killDeployedTeamMember.d.ts +29 -0
- package/dist/tools/goofy/killDeployedTeamMember.d.ts.map +1 -0
- package/dist/tools/goofy/killDeployedTeamMember.js +56 -0
- package/dist/tools/goofy/killDeployedTeamMember.js.map +1 -0
- package/dist/tools/goofy/linkTheVibes.d.ts +125 -0
- package/dist/tools/goofy/linkTheVibes.d.ts.map +1 -0
- package/dist/tools/goofy/linkTheVibes.js +354 -0
- package/dist/tools/goofy/linkTheVibes.js.map +1 -0
- package/dist/tools/goofy/listDeployedTeamMembers.d.ts +26 -0
- package/dist/tools/goofy/listDeployedTeamMembers.d.ts.map +1 -0
- package/dist/tools/goofy/listDeployedTeamMembers.js +52 -0
- package/dist/tools/goofy/listDeployedTeamMembers.js.map +1 -0
- package/dist/tools/goofy/listenForMessages.d.ts +56 -0
- package/dist/tools/goofy/listenForMessages.d.ts.map +1 -0
- package/dist/tools/goofy/listenForMessages.js +122 -0
- package/dist/tools/goofy/listenForMessages.js.map +1 -0
- package/dist/tools/goofy/memoryHealthCheck.d.ts +159 -0
- package/dist/tools/goofy/memoryHealthCheck.d.ts.map +1 -0
- package/dist/tools/goofy/memoryHealthCheck.js +443 -0
- package/dist/tools/goofy/memoryHealthCheck.js.map +1 -0
- package/dist/tools/goofy/rememberThisShit.d.ts +103 -0
- package/dist/tools/goofy/rememberThisShit.d.ts.map +1 -0
- package/dist/tools/goofy/rememberThisShit.js +291 -0
- package/dist/tools/goofy/rememberThisShit.js.map +1 -0
- package/dist/tools/goofy/sayToTeamMember.d.ts +55 -0
- package/dist/tools/goofy/sayToTeamMember.d.ts.map +1 -0
- package/dist/tools/goofy/sayToTeamMember.js +116 -0
- package/dist/tools/goofy/sayToTeamMember.js.map +1 -0
- package/dist/tools/goofy/selfMessage.d.ts +54 -0
- package/dist/tools/goofy/selfMessage.d.ts.map +1 -0
- package/dist/tools/goofy/selfMessage.js +111 -0
- package/dist/tools/goofy/selfMessage.js.map +1 -0
- package/dist/tools/goofy/sendHeartbeat.d.ts +53 -0
- package/dist/tools/goofy/sendHeartbeat.d.ts.map +1 -0
- package/dist/tools/goofy/sendHeartbeat.js +119 -0
- package/dist/tools/goofy/sendHeartbeat.js.map +1 -0
- package/dist/tools/goofy/showMeTheStats.d.ts +216 -0
- package/dist/tools/goofy/showMeTheStats.d.ts.map +1 -0
- package/dist/tools/goofy/showMeTheStats.js +535 -0
- package/dist/tools/goofy/showMeTheStats.js.map +1 -0
- package/dist/tools/goofy/smartRecall.d.ts +136 -0
- package/dist/tools/goofy/smartRecall.d.ts.map +1 -0
- package/dist/tools/goofy/smartRecall.js +286 -0
- package/dist/tools/goofy/smartRecall.js.map +1 -0
- package/dist/tools/goofy/smartSearch.d.ts +64 -0
- package/dist/tools/goofy/smartSearch.d.ts.map +1 -0
- package/dist/tools/goofy/smartSearch.js +89 -0
- package/dist/tools/goofy/smartSearch.js.map +1 -0
- package/dist/tools/goofy/smushMemoriesTogether.d.ts +128 -0
- package/dist/tools/goofy/smushMemoriesTogether.d.ts.map +1 -0
- package/dist/tools/goofy/smushMemoriesTogether.js +536 -0
- package/dist/tools/goofy/smushMemoriesTogether.js.map +1 -0
- package/dist/tools/goofy/spatialSearch.d.ts +198 -0
- package/dist/tools/goofy/spatialSearch.d.ts.map +1 -0
- package/dist/tools/goofy/spatialSearch.js +551 -0
- package/dist/tools/goofy/spatialSearch.js.map +1 -0
- package/dist/tools/goofy/spawnResearchTeamMember.d.ts +104 -0
- package/dist/tools/goofy/spawnResearchTeamMember.d.ts.map +1 -0
- package/dist/tools/goofy/spawnResearchTeamMember.js +290 -0
- package/dist/tools/goofy/spawnResearchTeamMember.js.map +1 -0
- package/dist/tools/goofy/spawnResearchTeamMemberTool.d.ts +121 -0
- package/dist/tools/goofy/spawnResearchTeamMemberTool.d.ts.map +1 -0
- package/dist/tools/goofy/spawnResearchTeamMemberTool.js +215 -0
- package/dist/tools/goofy/spawnResearchTeamMemberTool.js.map +1 -0
- package/dist/tools/goofy/startWatchingTheFiles.d.ts +81 -0
- package/dist/tools/goofy/startWatchingTheFiles.d.ts.map +1 -0
- package/dist/tools/goofy/startWatchingTheFiles.js +161 -0
- package/dist/tools/goofy/startWatchingTheFiles.js.map +1 -0
- package/dist/tools/goofy/stopWatchingTheFiles.d.ts +50 -0
- package/dist/tools/goofy/stopWatchingTheFiles.d.ts.map +1 -0
- package/dist/tools/goofy/stopWatchingTheFiles.js +81 -0
- package/dist/tools/goofy/stopWatchingTheFiles.js.map +1 -0
- package/dist/tools/goofy/whatDidIMean.d.ts +113 -0
- package/dist/tools/goofy/whatDidIMean.d.ts.map +1 -0
- package/dist/tools/goofy/whatDidIMean.js +401 -0
- package/dist/tools/goofy/whatDidIMean.js.map +1 -0
- package/dist/tools/goofy/yeahNahDeleteThat.d.ts +109 -0
- package/dist/tools/goofy/yeahNahDeleteThat.d.ts.map +1 -0
- package/dist/tools/goofy/yeahNahDeleteThat.js +319 -0
- package/dist/tools/goofy/yeahNahDeleteThat.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/teamMemberDeployer.d.ts +117 -0
- package/dist/tools/teamMemberDeployer.d.ts.map +1 -0
- package/dist/tools/teamMemberDeployer.js +613 -0
- package/dist/tools/teamMemberDeployer.js.map +1 -0
- package/dist/trace/index.d.ts +14 -0
- package/dist/trace/index.d.ts.map +1 -0
- package/dist/trace/index.js +16 -0
- package/dist/trace/index.js.map +1 -0
- package/dist/trace/tools/analyzeImpact.d.ts +90 -0
- package/dist/trace/tools/analyzeImpact.d.ts.map +1 -0
- package/dist/trace/tools/analyzeImpact.js +240 -0
- package/dist/trace/tools/analyzeImpact.js.map +1 -0
- package/dist/trace/tools/exploreDependencies.d.ts +81 -0
- package/dist/trace/tools/exploreDependencies.d.ts.map +1 -0
- package/dist/trace/tools/exploreDependencies.js +161 -0
- package/dist/trace/tools/exploreDependencies.js.map +1 -0
- package/dist/trace/tools/findSimilarBugs.d.ts +112 -0
- package/dist/trace/tools/findSimilarBugs.d.ts.map +1 -0
- package/dist/trace/tools/findSimilarBugs.js +216 -0
- package/dist/trace/tools/findSimilarBugs.js.map +1 -0
- package/dist/trace/tools/index.d.ts +22 -0
- package/dist/trace/tools/index.d.ts.map +1 -0
- package/dist/trace/tools/index.js +39 -0
- package/dist/trace/tools/index.js.map +1 -0
- package/dist/trace/tools/smartExplore.d.ts +126 -0
- package/dist/trace/tools/smartExplore.d.ts.map +1 -0
- package/dist/trace/tools/smartExplore.js +303 -0
- package/dist/trace/tools/smartExplore.js.map +1 -0
- package/dist/trace/tools/traceError.d.ts +101 -0
- package/dist/trace/tools/traceError.d.ts.map +1 -0
- package/dist/trace/tools/traceError.js +175 -0
- package/dist/trace/tools/traceError.js.map +1 -0
- package/dist/trace/traceExploreSystem.d.ts +271 -0
- package/dist/trace/traceExploreSystem.d.ts.map +1 -0
- package/dist/trace/traceExploreSystem.js +789 -0
- package/dist/trace/traceExploreSystem.js.map +1 -0
- package/dist/types/index.d.ts +421 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +118 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/circuitBreaker.d.ts +195 -0
- package/dist/utils/circuitBreaker.d.ts.map +1 -0
- package/dist/utils/circuitBreaker.js +374 -0
- package/dist/utils/circuitBreaker.js.map +1 -0
- package/dist/utils/cleanupHandler.d.ts +108 -0
- package/dist/utils/cleanupHandler.d.ts.map +1 -0
- package/dist/utils/cleanupHandler.js +203 -0
- package/dist/utils/cleanupHandler.js.map +1 -0
- package/dist/utils/compactXmlResponse.d.ts +60 -0
- package/dist/utils/compactXmlResponse.d.ts.map +1 -0
- package/dist/utils/compactXmlResponse.js +209 -0
- package/dist/utils/compactXmlResponse.js.map +1 -0
- package/dist/utils/cotBroadcast.d.ts +56 -0
- package/dist/utils/cotBroadcast.d.ts.map +1 -0
- package/dist/utils/cotBroadcast.js +157 -0
- package/dist/utils/cotBroadcast.js.map +1 -0
- package/dist/utils/debugLogger.d.ts +95 -0
- package/dist/utils/debugLogger.d.ts.map +1 -0
- package/dist/utils/debugLogger.js +610 -0
- package/dist/utils/debugLogger.js.map +1 -0
- package/dist/utils/fileProcessingQueue.d.ts +259 -0
- package/dist/utils/fileProcessingQueue.d.ts.map +1 -0
- package/dist/utils/fileProcessingQueue.js +714 -0
- package/dist/utils/fileProcessingQueue.js.map +1 -0
- package/dist/utils/humanReadableOutput.d.ts +124 -0
- package/dist/utils/humanReadableOutput.d.ts.map +1 -0
- package/dist/utils/humanReadableOutput.js +340 -0
- package/dist/utils/humanReadableOutput.js.map +1 -0
- package/dist/utils/index.d.ts +32 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +71 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/instanceManager.d.ts +530 -0
- package/dist/utils/instanceManager.d.ts.map +1 -0
- package/dist/utils/instanceManager.js +1784 -0
- package/dist/utils/instanceManager.js.map +1 -0
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +49 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/mapCleanup.d.ts +58 -0
- package/dist/utils/mapCleanup.d.ts.map +1 -0
- package/dist/utils/mapCleanup.js +150 -0
- package/dist/utils/mapCleanup.js.map +1 -0
- package/dist/utils/memoryManager.d.ts +349 -0
- package/dist/utils/memoryManager.d.ts.map +1 -0
- package/dist/utils/memoryManager.js +799 -0
- package/dist/utils/memoryManager.js.map +1 -0
- package/dist/utils/metrics.d.ts +160 -0
- package/dist/utils/metrics.d.ts.map +1 -0
- package/dist/utils/metrics.js +558 -0
- package/dist/utils/metrics.js.map +1 -0
- package/dist/utils/pathValidator.d.ts +96 -0
- package/dist/utils/pathValidator.d.ts.map +1 -0
- package/dist/utils/pathValidator.js +320 -0
- package/dist/utils/pathValidator.js.map +1 -0
- package/dist/utils/portAllocator.d.ts +296 -0
- package/dist/utils/portAllocator.d.ts.map +1 -0
- package/dist/utils/portAllocator.js +768 -0
- package/dist/utils/portAllocator.js.map +1 -0
- package/dist/utils/portUtils.d.ts +97 -0
- package/dist/utils/portUtils.d.ts.map +1 -0
- package/dist/utils/portUtils.js +285 -0
- package/dist/utils/portUtils.js.map +1 -0
- package/dist/utils/postgresAutoSetup.d.ts +55 -0
- package/dist/utils/postgresAutoSetup.d.ts.map +1 -0
- package/dist/utils/postgresAutoSetup.js +406 -0
- package/dist/utils/postgresAutoSetup.js.map +1 -0
- package/dist/utils/processHealthCheck.d.ts +61 -0
- package/dist/utils/processHealthCheck.d.ts.map +1 -0
- package/dist/utils/processHealthCheck.js +313 -0
- package/dist/utils/processHealthCheck.js.map +1 -0
- package/dist/utils/progressReporter.d.ts +151 -0
- package/dist/utils/progressReporter.d.ts.map +1 -0
- package/dist/utils/progressReporter.js +345 -0
- package/dist/utils/progressReporter.js.map +1 -0
- package/dist/utils/projectEnv.d.ts +73 -0
- package/dist/utils/projectEnv.d.ts.map +1 -0
- package/dist/utils/projectEnv.js +137 -0
- package/dist/utils/projectEnv.js.map +1 -0
- package/dist/utils/qoms.d.ts +122 -0
- package/dist/utils/qoms.d.ts.map +1 -0
- package/dist/utils/qoms.js +650 -0
- package/dist/utils/qoms.js.map +1 -0
- package/dist/utils/retryHelper.d.ts +122 -0
- package/dist/utils/retryHelper.d.ts.map +1 -0
- package/dist/utils/retryHelper.js +272 -0
- package/dist/utils/retryHelper.js.map +1 -0
- package/dist/utils/safeProcessTermination.d.ts +206 -0
- package/dist/utils/safeProcessTermination.d.ts.map +1 -0
- package/dist/utils/safeProcessTermination.js +552 -0
- package/dist/utils/safeProcessTermination.js.map +1 -0
- package/dist/utils/sessionInjector.d.ts +68 -0
- package/dist/utils/sessionInjector.d.ts.map +1 -0
- package/dist/utils/sessionInjector.js +189 -0
- package/dist/utils/sessionInjector.js.map +1 -0
- package/dist/utils/statsCache.d.ts +134 -0
- package/dist/utils/statsCache.d.ts.map +1 -0
- package/dist/utils/statsCache.js +285 -0
- package/dist/utils/statsCache.js.map +1 -0
- package/dist/utils/timeoutMiddleware.d.ts +81 -0
- package/dist/utils/timeoutMiddleware.d.ts.map +1 -0
- package/dist/utils/timeoutMiddleware.js +155 -0
- package/dist/utils/timeoutMiddleware.js.map +1 -0
- package/dist/utils/timerRegistry.d.ts +91 -0
- package/dist/utils/timerRegistry.d.ts.map +1 -0
- package/dist/utils/timerRegistry.js +187 -0
- package/dist/utils/timerRegistry.js.map +1 -0
- package/dist/utils/tokenCompressor.d.ts +332 -0
- package/dist/utils/tokenCompressor.d.ts.map +1 -0
- package/dist/utils/tokenCompressor.js +1306 -0
- package/dist/utils/tokenCompressor.js.map +1 -0
- package/dist/utils/tracing.d.ts +236 -0
- package/dist/utils/tracing.d.ts.map +1 -0
- package/dist/utils/tracing.js +378 -0
- package/dist/utils/tracing.js.map +1 -0
- package/dist/watcher/changeHandler.d.ts +123 -0
- package/dist/watcher/changeHandler.d.ts.map +1 -0
- package/dist/watcher/changeHandler.js +623 -0
- package/dist/watcher/changeHandler.js.map +1 -0
- package/dist/watcher/changeQueue.d.ts +133 -0
- package/dist/watcher/changeQueue.d.ts.map +1 -0
- package/dist/watcher/changeQueue.js +355 -0
- package/dist/watcher/changeQueue.js.map +1 -0
- package/dist/watcher/fileWatcher.d.ts +121 -0
- package/dist/watcher/fileWatcher.d.ts.map +1 -0
- package/dist/watcher/fileWatcher.js +531 -0
- package/dist/watcher/fileWatcher.js.map +1 -0
- package/dist/watcher/index.d.ts +94 -0
- package/dist/watcher/index.d.ts.map +1 -0
- package/dist/watcher/index.js +235 -0
- package/dist/watcher/index.js.map +1 -0
- package/dist/watcher/syncChecker.d.ts +93 -0
- package/dist/watcher/syncChecker.d.ts.map +1 -0
- package/dist/watcher/syncChecker.js +401 -0
- package/dist/watcher/syncChecker.js.map +1 -0
- package/dist/watcher/tsCompiler.d.ts +88 -0
- package/dist/watcher/tsCompiler.d.ts.map +1 -0
- package/dist/watcher/tsCompiler.js +212 -0
- package/dist/watcher/tsCompiler.js.map +1 -0
- package/embedding-sandbox/Dockerfile +77 -0
- package/embedding-sandbox/Dockerfile.frankenstein +91 -0
- package/embedding-sandbox/README.md +193 -0
- package/embedding-sandbox/__pycache__/frankenstein-embeddings.cpython-312.pyc +0 -0
- package/embedding-sandbox/__pycache__/frankenstein-embeddings.cpython-313.pyc +0 -0
- package/embedding-sandbox/__pycache__/qqms_v2.cpython-312.pyc +0 -0
- package/embedding-sandbox/__pycache__/qqms_v2.cpython-313.pyc +0 -0
- package/embedding-sandbox/add_js_docs.py +684 -0
- package/embedding-sandbox/build_docs_db.py +239 -0
- package/embedding-sandbox/client.cjs +376 -0
- package/embedding-sandbox/client.ts +913 -0
- package/embedding-sandbox/deploy-frankenstein.sh +240 -0
- package/embedding-sandbox/docker-compose.yml +60 -0
- package/embedding-sandbox/docker-manager.py +325 -0
- package/embedding-sandbox/docs/python_docs.db +0 -0
- package/embedding-sandbox/download-model.mjs +79 -0
- package/embedding-sandbox/download-model.py +28 -0
- package/embedding-sandbox/embedding-supervisor.sh +164 -0
- package/embedding-sandbox/frankenstein-embeddings.py +3940 -0
- package/embedding-sandbox/manage-services.sh +354 -0
- package/embedding-sandbox/overflow_queue.py +345 -0
- package/embedding-sandbox/package.json +17 -0
- package/embedding-sandbox/project_isolation.py +292 -0
- package/embedding-sandbox/qqms_v2.py +967 -0
- package/embedding-sandbox/ram-manager.sh +311 -0
- package/embedding-sandbox/requirements-frankenstein.txt +7 -0
- package/embedding-sandbox/run_js_docs.py +59 -0
- package/embedding-sandbox/seed_docs.py +885 -0
- package/embedding-sandbox/server-batch.mjs +228 -0
- package/embedding-sandbox/server.mjs +389 -0
- package/embedding-sandbox/specmem/sockets/claude-input-state.json +1 -0
- package/embedding-sandbox/specmem/sockets/embedding-death-reason.txt +3 -0
- package/embedding-sandbox/specmem/sockets/seen-sessions.json +1 -0
- package/embedding-sandbox/specmem/sockets/session-start.lock +1 -0
- package/embedding-sandbox/specmem/sockets/session-stops.log +7 -0
- package/embedding-sandbox/start-frankenstein-throttled.sh +98 -0
- package/embedding-sandbox/start-on-demand.sh +116 -0
- package/embedding-sandbox/start-sandbox.sh +237 -0
- package/embedding-sandbox/start-supervised.sh +11 -0
- package/embedding-sandbox/stop-sandbox.sh +51 -0
- package/embedding-sandbox/test-socket.mjs +61 -0
- package/embedding-sandbox/warm-start.sh +353 -0
- package/embedding-sandbox/warm_start_feeder.py +660 -0
- package/legal/README.md +31 -0
- package/legal/anthropic-privacy-center-screenshot-2026-01-30.png +0 -0
- package/legal/anthropic-tos-screenshot-2026-01-30.png +0 -0
- package/lib/codebase-bridge.cjs +308 -0
- package/package.json +136 -0
- package/plugins/specmem-agents/agents/bug-hunter.md +79 -0
- package/plugins/specmem-agents/agents/memory-explorer.md +57 -0
- package/plugins/specmem-agents/agents/team-coordinator.md +82 -0
- package/scripts/auto-updater.cjs +399 -0
- package/scripts/backfill-code-definition-embeddings.ts +440 -0
- package/scripts/backfill-code-embeddings.ts +206 -0
- package/scripts/capture-tos-screenshots.cjs +94 -0
- package/scripts/check-global-install.cjs +67 -0
- package/scripts/cleanup-embedding-servers.sh +25 -0
- package/scripts/dashboard-standalone.sh +369 -0
- package/scripts/deploy-hooks.cjs +1451 -0
- package/scripts/deploy.sh +106 -0
- package/scripts/docker-project-down.sh +83 -0
- package/scripts/docker-project-list.sh +40 -0
- package/scripts/docker-project-up.sh +79 -0
- package/scripts/fast-backfill-embeddings.ts +173 -0
- package/scripts/fast-batch-embedder.cjs +334 -0
- package/scripts/first-run-model-setup.cjs +849 -0
- package/scripts/global-postinstall.cjs +1957 -0
- package/scripts/index-codebase.js +72 -0
- package/scripts/migrate-fix-embeddings.py +110 -0
- package/scripts/migrate-to-project-schemas.ts +525 -0
- package/scripts/optimize-embedding-model.py +324 -0
- package/scripts/optimize-instructions.cjs +530 -0
- package/scripts/pack-docker-images.sh +68 -0
- package/scripts/pack-for-testing.sh +130 -0
- package/scripts/postinstall.cjs +54 -0
- package/scripts/project-env.sh +51 -0
- package/scripts/reset-db.sh +30 -0
- package/scripts/run-indexer.ts +69 -0
- package/scripts/run-migrations.js +47 -0
- package/scripts/setup-db.sh +34 -0
- package/scripts/setup-minimal-schema.sql +143 -0
- package/scripts/skills/code-review.md +44 -0
- package/scripts/skills/debugging.md +56 -0
- package/scripts/skills/specmem-deployteam.md +239 -0
- package/scripts/skills/teammemberskills/EFFICIENT_GREP.md +171 -0
- package/scripts/skills/teammemberskills/task-planning.md +67 -0
- package/scripts/specmem/sockets/session-start.lock +1 -0
- package/scripts/specmem/sockets/session-stops.log +1 -0
- package/scripts/specmem-health.sh +382 -0
- package/scripts/specmem-init.cjs +6935 -0
- package/scripts/strip-debug-logs.cjs +43 -0
- package/scripts/test-mcp-standalone.sh +365 -0
- package/scripts/test-optimized-models.py +166 -0
- package/scripts/verify-embedding-fix.sh +148 -0
- package/skills/code-review.md +44 -0
- package/skills/debugging.md +56 -0
- package/skills/specmem-deployteam.md +239 -0
- package/skills/teammemberskills/EFFICIENT_GREP.md +171 -0
- package/skills/teammemberskills/task-planning.md +67 -0
- package/specmem-health.cjs +522 -0
- package/specmem.env +216 -0
|
@@ -0,0 +1,2048 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* SpecMem - Speculative Memory MCP Server
|
|
4
|
+
*
|
|
5
|
+
* yo shoutout to doobidoo/mcp-memory-service for the inspo
|
|
6
|
+
* we took their SQLite version and made it POSTGRESQL BEAST MODE
|
|
7
|
+
* - hardwicksoftwareservices
|
|
8
|
+
*
|
|
9
|
+
* this thing hits different fr fr - semantic search, dream-inspired
|
|
10
|
+
* consolidation, and postgresql go crazy together no cap
|
|
11
|
+
*/
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// STARTUP LOGGING - Debug MCP connection issues
|
|
14
|
+
// Uses project-isolated path: /tmp/specmem-${PROJECT_HASH}/mcp-startup.log
|
|
15
|
+
// ============================================================================
|
|
16
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
17
|
+
import { appendFile, writeFile } from 'fs/promises';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
// DEBUG LOGGING - only enabled when SPECMEM_DEBUG=1
|
|
20
|
+
const __debugLog = process.env['SPECMEM_DEBUG'] === '1'
|
|
21
|
+
? (...args) => console.error('[DEBUG]', ...args) // stderr, not stdout!
|
|
22
|
+
: () => { };
|
|
23
|
+
// Compute project directory name early for log isolation (READABLE!)
|
|
24
|
+
const __projectPath = process.env['SPECMEM_PROJECT_PATH'] || process.cwd();
|
|
25
|
+
const __projectDirName = process.env['SPECMEM_PROJECT_DIR_NAME'] ||
|
|
26
|
+
path.basename(__projectPath)
|
|
27
|
+
.toLowerCase()
|
|
28
|
+
.replace(/[^a-z0-9_.-]/g, '-')
|
|
29
|
+
.replace(/-+/g, '-')
|
|
30
|
+
.replace(/^-|-$/g, '') || 'default';
|
|
31
|
+
const __projectTmpDir = `/tmp/specmem-${__projectDirName}`;
|
|
32
|
+
// Ensure project tmp directory exists
|
|
33
|
+
try {
|
|
34
|
+
if (!existsSync(__projectTmpDir)) {
|
|
35
|
+
mkdirSync(__projectTmpDir, { recursive: true, mode: 0o755 });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (mkdirErr) {
|
|
39
|
+
if (mkdirErr.code === 'EACCES' || mkdirErr.code === 'EPERM') {
|
|
40
|
+
console.error('\x1b[31m\x1b[1m Hey, I need sudo! SpecMem can\'t create directories without proper permissions.\x1b[0m');
|
|
41
|
+
console.error(`\x1b[31m Failed path: ${__projectTmpDir}\x1b[0m`);
|
|
42
|
+
console.error('\x1b[31m Run with: sudo npx specmem-hardwicksoftware\x1b[0m');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
// Log at debug level - directory creation can fail if race condition
|
|
46
|
+
if (process.env.SPECMEM_DEBUG === 'true') {
|
|
47
|
+
console.error(`[DEBUG] Failed to create tmp dir: ${mkdirErr}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const STARTUP_LOG_PATH = `${__projectTmpDir}/mcp-startup.log`;
|
|
51
|
+
function startupLog(msg, error) {
|
|
52
|
+
const timestamp = new Date().toISOString();
|
|
53
|
+
const pid = process.pid;
|
|
54
|
+
let logLine = `${timestamp} [PID:${pid}] [specMemServer.ts] ${msg}\n`;
|
|
55
|
+
if (error) {
|
|
56
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
57
|
+
const errStack = error instanceof Error ? error.stack : undefined;
|
|
58
|
+
logLine += `${timestamp} [PID:${pid}] [specMemServer.ts] ERROR: ${errMsg}\n`;
|
|
59
|
+
if (errStack) {
|
|
60
|
+
logLine += `${timestamp} [PID:${pid}] [specMemServer.ts] STACK: ${errStack}\n`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
appendFile(STARTUP_LOG_PATH, logLine).catch(() => {
|
|
64
|
+
// fire and forget - startup logging shouldnt block the event loop
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
68
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
69
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
70
|
+
import { createToolRegistry } from './toolRegistry.js';
|
|
71
|
+
import { MCPProtocolHandler } from './mcpProtocolHandler.js';
|
|
72
|
+
import { getDatabase } from '../database.js';
|
|
73
|
+
import { initTeamCommsDB } from './tools/teamComms.js';
|
|
74
|
+
import { config, getEmbeddingSocketPath } from '../config.js';
|
|
75
|
+
import { logger } from '../utils/logger.js';
|
|
76
|
+
import { reportProgress, reportComplete, reportError, setMcpServer as setProgressMcpServer } from '../utils/progressReporter.js';
|
|
77
|
+
import { createCommandHandler, getCommandsResource, getCommandHelpResource, getCommandExecutorToolDefinition } from '../commands/index.js';
|
|
78
|
+
// Skills system imports
|
|
79
|
+
import { getSkillScanner } from '../skills/skillScanner.js';
|
|
80
|
+
import { getSkillResourceProvider } from '../skills/skillsResource.js';
|
|
81
|
+
import { getSkillReminder } from '../reminders/skillReminder.js';
|
|
82
|
+
// Command loader - load command .md files as MCP prompts
|
|
83
|
+
import { getCommandLoader } from '../commands/commandLoader.js';
|
|
84
|
+
// CLI Notifications - centralized notification system
|
|
85
|
+
import { getDashboardUrl } from './cliNotifications.js';
|
|
86
|
+
// Resilient transport for connection health monitoring and graceful shutdown
|
|
87
|
+
import { getResilientTransport, resetResilientTransport, ConnectionState } from './resilientTransport.js';
|
|
88
|
+
// HR-6: Hot Reload Manager for tracking active tool calls during reload
|
|
89
|
+
// This enables safe hot reload by ensuring no tool calls are in flight
|
|
90
|
+
import { getHotReloadManager } from './hotReloadManager.js';
|
|
91
|
+
import { wrapToolResponse, compressHumanReadableFormat } from '../services/ResponseCompactor.js';
|
|
92
|
+
// Health Monitor - centralized health monitoring for all MCP components
|
|
93
|
+
import { getHealthMonitor, resetHealthMonitor, ComponentHealth } from './healthMonitor.js';
|
|
94
|
+
// Embedding Server Lifecycle Manager - manages embedding server process
|
|
95
|
+
import { getEmbeddingServerManager, resetEmbeddingServerManager } from './embeddingServerManager.js';
|
|
96
|
+
// Mini COT Server Lifecycle Manager - manages Mini COT model service
|
|
97
|
+
import { getMiniCOTServerManager, resetMiniCOTServerManager } from './miniCOTServerManager.js';
|
|
98
|
+
// Map cleanup utility for stale entry prevention
|
|
99
|
+
import { setupMapCleanupWithEmbeddedTime } from '../utils/mapCleanup.js';
|
|
100
|
+
const _SERVER_CACHE_BY_PROJECT = new Map();
|
|
101
|
+
// Cleanup stale server cache entries after 30 min inactivity
|
|
102
|
+
setupMapCleanupWithEmbeddedTime(_SERVER_CACHE_BY_PROJECT, {
|
|
103
|
+
staleThresholdMs: 30 * 60 * 1000,
|
|
104
|
+
checkIntervalMs: 5 * 60 * 1000,
|
|
105
|
+
logPrefix: '[ServerCache]'
|
|
106
|
+
});
|
|
107
|
+
/**
|
|
108
|
+
* Get project-scoped server cache stats
|
|
109
|
+
*/
|
|
110
|
+
function getServerCache() {
|
|
111
|
+
const projectPath = __projectPath;
|
|
112
|
+
if (!_SERVER_CACHE_BY_PROJECT.has(projectPath)) {
|
|
113
|
+
_SERVER_CACHE_BY_PROJECT.set(projectPath, {
|
|
114
|
+
hitCount: 0,
|
|
115
|
+
missCount: 0,
|
|
116
|
+
lastAccessTime: Date.now()
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const cache = _SERVER_CACHE_BY_PROJECT.get(projectPath);
|
|
120
|
+
cache.lastAccessTime = Date.now();
|
|
121
|
+
return cache;
|
|
122
|
+
}
|
|
123
|
+
// Legacy export for backwards compatibility - proxies to project-scoped cache
|
|
124
|
+
const _SERVER_CACHE = {
|
|
125
|
+
get hitCount() { return getServerCache().hitCount; },
|
|
126
|
+
set hitCount(v) { getServerCache().hitCount = v; },
|
|
127
|
+
get missCount() { return getServerCache().missCount; },
|
|
128
|
+
set missCount(v) { getServerCache().missCount = v; },
|
|
129
|
+
get lastAccessTime() { return getServerCache().lastAccessTime; },
|
|
130
|
+
set lastAccessTime(v) { getServerCache().lastAccessTime = v; }
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* SpecMem MCP Server - the main event fr fr
|
|
134
|
+
*
|
|
135
|
+
* handles all the claude code integration like a champ
|
|
136
|
+
* stdio transport go brrrr for that sweet sweet IPC
|
|
137
|
+
*/
|
|
138
|
+
export class SpecMemServer {
|
|
139
|
+
server;
|
|
140
|
+
db;
|
|
141
|
+
toolRegistry;
|
|
142
|
+
protocolHandler;
|
|
143
|
+
commandHandler;
|
|
144
|
+
startTime;
|
|
145
|
+
toolCallCount = 0;
|
|
146
|
+
lastError = null;
|
|
147
|
+
embeddingProvider;
|
|
148
|
+
resilientTransport = null;
|
|
149
|
+
isShuttingDown = false;
|
|
150
|
+
// HR-6: Hot reload manager for tracking active tool calls
|
|
151
|
+
hotReloadManager = null;
|
|
152
|
+
// Centralized health monitor for all MCP components
|
|
153
|
+
healthMonitor = null;
|
|
154
|
+
// Embedding server lifecycle manager - ensures embedding is ALWAYS available
|
|
155
|
+
embeddingServerManager = null;
|
|
156
|
+
// Mini COT server lifecycle manager - optional semantic analysis service
|
|
157
|
+
miniCOTServerManager = null;
|
|
158
|
+
constructor(embeddingProvider) {
|
|
159
|
+
this.embeddingProvider = embeddingProvider;
|
|
160
|
+
this.startTime = new Date();
|
|
161
|
+
// server setup go crazy
|
|
162
|
+
this.server = new Server({
|
|
163
|
+
name: 'specmem',
|
|
164
|
+
version: '1.0.0'
|
|
165
|
+
}, {
|
|
166
|
+
capabilities: {
|
|
167
|
+
// CRITICAL FIX: Explicitly declare tool capabilities with listChanged
|
|
168
|
+
// This tells that our tool list can change dynamically and
|
|
169
|
+
// it should respect sendToolListChanged() notifications
|
|
170
|
+
tools: {
|
|
171
|
+
listChanged: true // Signal we support dynamic tool list updates
|
|
172
|
+
},
|
|
173
|
+
// we ready for resources and prompts too when claude needs em
|
|
174
|
+
resources: {
|
|
175
|
+
listChanged: true // Signal we support dynamic resource list updates
|
|
176
|
+
},
|
|
177
|
+
prompts: {
|
|
178
|
+
listChanged: true // Signal we support dynamic prompt list updates
|
|
179
|
+
},
|
|
180
|
+
// logging enabled so we can announce ourselves to fr fr
|
|
181
|
+
logging: {}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
// setup the oninitialized callback to announce ourselves and signal readiness
|
|
185
|
+
// This is called when the MCP protocol handshake completes (initialize/initialized)
|
|
186
|
+
// NOTE: The MCP SDK supports async oninitialized callbacks, so we use async/await
|
|
187
|
+
this.server.oninitialized = async () => {
|
|
188
|
+
const timestamp = new Date().toISOString();
|
|
189
|
+
// Enable progress reporter to use MCP sendLoggingMessage (visible in Code!)
|
|
190
|
+
setProgressMcpServer(this.server);
|
|
191
|
+
// DEBUG: Log to startup file for reliable debugging
|
|
192
|
+
startupLog('oninitialized callback fired - MCP handshake complete');
|
|
193
|
+
// DEBUG: Log with high visibility that the initialized notification was received
|
|
194
|
+
logger.info({ timestamp, event: 'HANDSHAKE_INITIALIZED' }, '[MCP DEBUG] Received initialized notification from - handshake complete');
|
|
195
|
+
// Write readiness signal to stderr for any process monitors
|
|
196
|
+
// This is critical for debugging - it shows up in Code's stderr logs
|
|
197
|
+
process.stderr.write(`[SPECMEM DEBUG ${timestamp}] oninitialized callback fired - MCP handshake complete\n`);
|
|
198
|
+
// Record activity on the resilient transport (if initialized)
|
|
199
|
+
if (this.resilientTransport) {
|
|
200
|
+
this.resilientTransport.recordActivity();
|
|
201
|
+
}
|
|
202
|
+
// CRITICAL FIX: Notify that tools list is ready
|
|
203
|
+
// This triggers to re-fetch the tools list via ListToolsRequest
|
|
204
|
+
// Without this, may cache an empty tool list from early handshake
|
|
205
|
+
startupLog('About to call notifyToolListReady() to trigger tools/list refresh');
|
|
206
|
+
logger.info({ timestamp, event: 'HANDSHAKE_NOTIFY_TOOLS' }, '[MCP DEBUG] About to call notifyToolListReady() to trigger tools/list refresh');
|
|
207
|
+
// IMPORTANT: Await the notification to ensure it's sent before continuing
|
|
208
|
+
// This ensures proper sequencing of the handshake
|
|
209
|
+
try {
|
|
210
|
+
await this.notifyToolListReady();
|
|
211
|
+
startupLog('Tool list notification sent successfully');
|
|
212
|
+
logger.info({ timestamp, event: 'HANDSHAKE_NOTIFY_COMPLETE' }, '[MCP DEBUG] Tool list notification complete');
|
|
213
|
+
}
|
|
214
|
+
catch (notifyErr) {
|
|
215
|
+
const error = notifyErr instanceof Error ? notifyErr : new Error(String(notifyErr));
|
|
216
|
+
startupLog('FAILED to send tool list notification', notifyErr);
|
|
217
|
+
logger.error({ timestamp, event: 'HANDSHAKE_NOTIFY_ERROR', error: error.message }, '[MCP DEBUG] Failed to notify tool list - tools may not be available');
|
|
218
|
+
process.stderr.write(`[SPECMEM ERROR ${timestamp}] Tool notification failed: ${error.message}\n`);
|
|
219
|
+
}
|
|
220
|
+
// Send the startup announcement to
|
|
221
|
+
startupLog('Calling announceToOnStartup()');
|
|
222
|
+
this.announceToOnStartup();
|
|
223
|
+
};
|
|
224
|
+
// get that db connection no cap
|
|
225
|
+
this.db = getDatabase(config.database);
|
|
226
|
+
// registry got all our goofy tools registered
|
|
227
|
+
this.toolRegistry = createToolRegistry(this.db, embeddingProvider);
|
|
228
|
+
// protocol handler do be handling protocols tho
|
|
229
|
+
this.protocolHandler = new MCPProtocolHandler(this.toolRegistry);
|
|
230
|
+
// command handler for slash commands - doobidoo style
|
|
231
|
+
this.commandHandler = createCommandHandler(this.db, embeddingProvider);
|
|
232
|
+
this.setupHandlers();
|
|
233
|
+
this.setupResourceHandlers();
|
|
234
|
+
this.setupErrorHandling();
|
|
235
|
+
logger.info('SpecMem MCP Server initialized - ready to remember some stuff fr fr');
|
|
236
|
+
}
|
|
237
|
+
setupHandlers() {
|
|
238
|
+
// list tools - show claude what we got plus the command executor
|
|
239
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
240
|
+
const timestamp = new Date().toISOString();
|
|
241
|
+
const requestId = `tools_list_${Date.now()}`;
|
|
242
|
+
// DEBUG: Log to startup file - this is the CRITICAL request makes to get tools
|
|
243
|
+
startupLog(`tools/list request received from (id: ${requestId})`);
|
|
244
|
+
// DEBUG: Log that we received a tools/list request
|
|
245
|
+
logger.info({ timestamp, requestId, event: 'TOOLS_LIST_REQUEST' }, '[MCP DEBUG] Received tools/list request from ');
|
|
246
|
+
process.stderr.write(`[SPECMEM DEBUG ${timestamp}] tools/list request received (id: ${requestId})\n`);
|
|
247
|
+
_SERVER_CACHE.hitCount++;
|
|
248
|
+
_SERVER_CACHE.lastAccessTime = Date.now();
|
|
249
|
+
// Record activity - tool list request means connection is active
|
|
250
|
+
if (this.resilientTransport) {
|
|
251
|
+
this.resilientTransport.recordActivity();
|
|
252
|
+
}
|
|
253
|
+
// add execute_command tool for slash commands
|
|
254
|
+
const commandTool = getCommandExecutorToolDefinition();
|
|
255
|
+
const regularTools = this.toolRegistry.getToolDefinitions();
|
|
256
|
+
const allTools = [
|
|
257
|
+
...regularTools,
|
|
258
|
+
{
|
|
259
|
+
name: commandTool.name,
|
|
260
|
+
description: commandTool.description,
|
|
261
|
+
inputSchema: commandTool.inputSchema
|
|
262
|
+
}
|
|
263
|
+
];
|
|
264
|
+
// DEBUG: Log the response we're about to send
|
|
265
|
+
const toolNames = allTools.map(t => t.name);
|
|
266
|
+
startupLog(`tools/list response: ${allTools.length} tools being returned to `);
|
|
267
|
+
logger.info({
|
|
268
|
+
timestamp,
|
|
269
|
+
requestId,
|
|
270
|
+
event: 'TOOLS_LIST_RESPONSE',
|
|
271
|
+
toolCount: allTools.length,
|
|
272
|
+
regularToolCount: regularTools.length,
|
|
273
|
+
cacheHitCount: _SERVER_CACHE.hitCount,
|
|
274
|
+
toolNames: toolNames.slice(0, 10), // First 10 tool names for debugging
|
|
275
|
+
totalTools: toolNames.length
|
|
276
|
+
}, `[MCP DEBUG] Returning ${allTools.length} tools to `);
|
|
277
|
+
process.stderr.write(`[SPECMEM DEBUG ${timestamp}] tools/list response: ${allTools.length} tools (first 5: ${toolNames.slice(0, 5).join(', ')})\n`);
|
|
278
|
+
return { tools: allTools };
|
|
279
|
+
});
|
|
280
|
+
// call tool - where the magic happens
|
|
281
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
282
|
+
const callToolStartTime = Date.now();
|
|
283
|
+
const { name, arguments: args } = request.params;
|
|
284
|
+
this.toolCallCount++;
|
|
285
|
+
// HIGH-20: Wait for server to be fully ready before executing tools
|
|
286
|
+
// This prevents race conditions where tools execute before DB is initialized
|
|
287
|
+
if (!this.isFullyReady) {
|
|
288
|
+
__debugLog('[MCP DEBUG]', callToolStartTime, 'WAITING_FOR_READY', { toolName: name });
|
|
289
|
+
try {
|
|
290
|
+
await this.waitForReady();
|
|
291
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'READY_COMPLETE', { toolName: name, waitMs: Date.now() - callToolStartTime });
|
|
292
|
+
}
|
|
293
|
+
catch (readyError) {
|
|
294
|
+
const errorMsg = readyError instanceof Error ? readyError.message : String(readyError);
|
|
295
|
+
logger.error({ error: readyError, tool: name }, 'Server not ready for tool execution');
|
|
296
|
+
return {
|
|
297
|
+
content: [{
|
|
298
|
+
type: 'text',
|
|
299
|
+
text: JSON.stringify({
|
|
300
|
+
error: true,
|
|
301
|
+
message: `Server not fully initialized: ${errorMsg}`,
|
|
302
|
+
tool: name,
|
|
303
|
+
suggestion: 'Wait a moment and try again - server is still starting up'
|
|
304
|
+
}, null, 2)
|
|
305
|
+
}],
|
|
306
|
+
isError: true
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// ==========================================================================
|
|
311
|
+
// MULTI-PROJECT ISOLATION FIX: SPECMEM_PROJECT_PATH is IMMUTABLE
|
|
312
|
+
// ==========================================================================
|
|
313
|
+
// REMOVED: Marker file reading - caused race condition with simultaneous projects!
|
|
314
|
+
//
|
|
315
|
+
// Each MCP server instance has SPECMEM_PROJECT_PATH set at startup by bootstrap.cjs.
|
|
316
|
+
// This env var NEVER changes during the server's lifetime.
|
|
317
|
+
// Tools can pass explicit projectPath/project_path args for cross-project queries.
|
|
318
|
+
// ==========================================================================
|
|
319
|
+
const requestMeta = request._meta;
|
|
320
|
+
const argsObj = args;
|
|
321
|
+
// STEP 2: Determine project path with correct priority
|
|
322
|
+
// MULTI-PROJECT ISOLATION: Server's SPECMEM_PROJECT_PATH is IMMUTABLE
|
|
323
|
+
// Tools can use explicit projectPath/project_path args for cross-project queries
|
|
324
|
+
// but we NEVER change the server's env var dynamically
|
|
325
|
+
const serverProjectPath = process.env['SPECMEM_PROJECT_PATH'];
|
|
326
|
+
const explicitProjectPath = argsObj?.projectPath || argsObj?.project_path ||
|
|
327
|
+
requestMeta?.cwd || requestMeta?.workingDirectory;
|
|
328
|
+
// Log if tool is explicitly querying a different project
|
|
329
|
+
if (explicitProjectPath && explicitProjectPath !== serverProjectPath) {
|
|
330
|
+
startupLog(`[CROSS-PROJECT QUERY] Tool ${name} targeting: ${explicitProjectPath} (server: ${serverProjectPath})`);
|
|
331
|
+
}
|
|
332
|
+
if (!serverProjectPath) {
|
|
333
|
+
startupLog(`[PROJECT PATH] WARNING: No SPECMEM_PROJECT_PATH set for tool ${name}`);
|
|
334
|
+
}
|
|
335
|
+
// HR-6: Generate unique call ID and track tool call start for hot reload safety
|
|
336
|
+
// This ensures we don't reload while tool calls are in flight
|
|
337
|
+
const callId = `${name}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
338
|
+
// DEBUG: Log call tool request received
|
|
339
|
+
__debugLog('[MCP DEBUG]', callToolStartTime, 'CALL_TOOL_REQUEST_RECEIVED', {
|
|
340
|
+
callId,
|
|
341
|
+
toolName: name,
|
|
342
|
+
hasArgs: !!args,
|
|
343
|
+
argsType: typeof args,
|
|
344
|
+
argsKeys: args && typeof args === 'object' ? Object.keys(args) : [],
|
|
345
|
+
totalToolCalls: this.toolCallCount
|
|
346
|
+
});
|
|
347
|
+
// Record activity with resilient transport for connection health tracking
|
|
348
|
+
if (this.resilientTransport) {
|
|
349
|
+
this.resilientTransport.recordActivity();
|
|
350
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'RESILIENT_TRANSPORT_ACTIVITY_RECORDED', { callId });
|
|
351
|
+
}
|
|
352
|
+
// Get hot reload manager (lazy init on first tool call)
|
|
353
|
+
if (!this.hotReloadManager) {
|
|
354
|
+
try {
|
|
355
|
+
this.hotReloadManager = getHotReloadManager();
|
|
356
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'HOT_RELOAD_MANAGER_INIT', { callId, success: true });
|
|
357
|
+
}
|
|
358
|
+
catch (err) {
|
|
359
|
+
// Hot reload manager not available yet - that's fine, continue without tracking
|
|
360
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'HOT_RELOAD_MANAGER_INIT', { callId, success: false, error: err instanceof Error ? err.message : String(err) });
|
|
361
|
+
logger.debug({ error: err }, '[HR-6] Hot reload manager not available yet');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
// Start tracking this tool call
|
|
365
|
+
if (this.hotReloadManager) {
|
|
366
|
+
this.hotReloadManager.startToolCall(callId, name);
|
|
367
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'HOT_RELOAD_TRACKING_START', { callId, toolName: name });
|
|
368
|
+
}
|
|
369
|
+
try {
|
|
370
|
+
const startTime = Date.now();
|
|
371
|
+
let result;
|
|
372
|
+
__debugLog('[MCP DEBUG]', startTime, 'TOOL_EXECUTION_START', {
|
|
373
|
+
callId,
|
|
374
|
+
toolName: name,
|
|
375
|
+
isExecuteCommand: name === 'execute_command'
|
|
376
|
+
});
|
|
377
|
+
// Report tool start for progress tracking (only shown for slow tools)
|
|
378
|
+
reportProgress({
|
|
379
|
+
operation: 'tool',
|
|
380
|
+
phase: 'start',
|
|
381
|
+
message: `Running ${name}...`,
|
|
382
|
+
});
|
|
383
|
+
// handle execute_command specially - route to command handler
|
|
384
|
+
if (name === 'execute_command') {
|
|
385
|
+
const commandArgs = args;
|
|
386
|
+
const command = commandArgs?.command ?? '';
|
|
387
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'EXECUTE_COMMAND_ROUTING', { callId, command: command.substring(0, 100) });
|
|
388
|
+
result = await this.commandHandler.handleCommand(command);
|
|
389
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'EXECUTE_COMMAND_COMPLETE', { callId, hasResult: !!result });
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'PROTOCOL_HANDLER_ROUTING', { callId, toolName: name });
|
|
393
|
+
result = await this.protocolHandler.handleToolCall(name, args ?? {});
|
|
394
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'PROTOCOL_HANDLER_COMPLETE', { callId, hasResult: !!result, resultType: typeof result });
|
|
395
|
+
}
|
|
396
|
+
const duration = Date.now() - startTime;
|
|
397
|
+
const totalDuration = Date.now() - callToolStartTime;
|
|
398
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'TOOL_EXECUTION_SUCCESS', {
|
|
399
|
+
callId,
|
|
400
|
+
toolName: name,
|
|
401
|
+
executionDurationMs: duration,
|
|
402
|
+
totalDurationMs: totalDuration,
|
|
403
|
+
resultIsArray: Array.isArray(result),
|
|
404
|
+
resultLength: Array.isArray(result) ? result.length : (typeof result === 'object' && result !== null ? Object.keys(result).length : undefined)
|
|
405
|
+
});
|
|
406
|
+
// Report completion with duration
|
|
407
|
+
reportComplete('tool', duration, `${name} complete`);
|
|
408
|
+
// Log tool call to dashboard log for real-time display (async - fire and forget)
|
|
409
|
+
const toolLogPath = path.join(serverProjectPath || process.cwd(), 'specmem', 'sockets', 'mcp-tool-calls.log');
|
|
410
|
+
// Enhanced debug logging - include args preview and result summary
|
|
411
|
+
const argsPreview = args ? JSON.stringify(args).slice(0, 200) : '{}';
|
|
412
|
+
const resultPreview = (() => {
|
|
413
|
+
try {
|
|
414
|
+
if (result === null || result === undefined)
|
|
415
|
+
return 'null';
|
|
416
|
+
if (typeof result === 'string')
|
|
417
|
+
return result.slice(0, 100);
|
|
418
|
+
if (Array.isArray(result))
|
|
419
|
+
return `[${result.length} items]`;
|
|
420
|
+
if (typeof result === 'object') {
|
|
421
|
+
const keys = Object.keys(result);
|
|
422
|
+
return `{${keys.slice(0, 3).join(', ')}${keys.length > 3 ? '...' : ''}}`;
|
|
423
|
+
}
|
|
424
|
+
return String(result).slice(0, 50);
|
|
425
|
+
}
|
|
426
|
+
catch {
|
|
427
|
+
return '?';
|
|
428
|
+
}
|
|
429
|
+
})();
|
|
430
|
+
const toolLogEntry = JSON.stringify({
|
|
431
|
+
timestamp: new Date().toISOString(),
|
|
432
|
+
callId,
|
|
433
|
+
name,
|
|
434
|
+
args: argsPreview,
|
|
435
|
+
duration,
|
|
436
|
+
result: resultPreview,
|
|
437
|
+
status: 'success'
|
|
438
|
+
}) + '\n';
|
|
439
|
+
appendFile(toolLogPath, toolLogEntry).catch(() => {
|
|
440
|
+
// fire and forget - dashboard logging shouldnt block tool execution
|
|
441
|
+
});
|
|
442
|
+
// Also write human-readable line for easier debugging
|
|
443
|
+
const hrLogPath = path.join(serverProjectPath || process.cwd(), 'specmem', 'sockets', 'mcp-debug.log');
|
|
444
|
+
const hrTime = new Date().toISOString().split('T')[1]?.slice(0, 8) || '??:??:??';
|
|
445
|
+
const hrLine = `[${hrTime}] ${name} (${duration}ms) args=${argsPreview.slice(0, 80)} result=${resultPreview}\n`;
|
|
446
|
+
appendFile(hrLogPath, hrLine).catch(() => { });
|
|
447
|
+
// Update statusbar state for claudefix integration
|
|
448
|
+
const statusbarPath = path.join(serverProjectPath || process.cwd(), 'specmem', 'sockets', 'statusbar-state.json');
|
|
449
|
+
const statusState = {
|
|
450
|
+
lastToolCall: { tool: name, duration, time: hrTime },
|
|
451
|
+
mcpConnected: true,
|
|
452
|
+
lastUpdate: Date.now()
|
|
453
|
+
};
|
|
454
|
+
writeFile(statusbarPath, JSON.stringify(statusState)).catch(() => { });
|
|
455
|
+
// log slow operations so we know whats up
|
|
456
|
+
if (duration > 100) {
|
|
457
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'TOOL_SLOW_WARNING', { callId, toolName: name, durationMs: duration, threshold: 100 });
|
|
458
|
+
logger.warn({ duration, tool: name }, 'tool execution kinda slow ngl');
|
|
459
|
+
}
|
|
460
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'FORMATTING_RESPONSE', { callId, toolName: name });
|
|
461
|
+
const formattedResponse = this.formatResponse(result);
|
|
462
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'RESPONSE_FORMATTED', {
|
|
463
|
+
callId,
|
|
464
|
+
toolName: name,
|
|
465
|
+
contentCount: formattedResponse.content.length,
|
|
466
|
+
firstContentType: formattedResponse.content[0]?.type
|
|
467
|
+
});
|
|
468
|
+
return formattedResponse;
|
|
469
|
+
}
|
|
470
|
+
catch (error) {
|
|
471
|
+
const errorTime = Date.now();
|
|
472
|
+
const totalDuration = errorTime - callToolStartTime;
|
|
473
|
+
const errorMessage = error instanceof Error ? error.message : 'unknown error fr';
|
|
474
|
+
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
475
|
+
__debugLog('[MCP DEBUG]', errorTime, 'TOOL_EXECUTION_ERROR', {
|
|
476
|
+
callId,
|
|
477
|
+
toolName: name,
|
|
478
|
+
totalDurationMs: totalDuration,
|
|
479
|
+
errorMessage,
|
|
480
|
+
errorType: error instanceof Error ? error.constructor.name : typeof error,
|
|
481
|
+
errorStack: errorStack?.split('\n').slice(0, 5).join('\n')
|
|
482
|
+
});
|
|
483
|
+
this.lastError = errorMessage;
|
|
484
|
+
logger.error({ error, tool: name }, 'tool execution said nah');
|
|
485
|
+
// Report error
|
|
486
|
+
reportError('tool', `${name} failed: ${this.lastError}`);
|
|
487
|
+
// Log error to human-readable debug log
|
|
488
|
+
const hrLogPath = path.join(serverProjectPath || process.cwd(), 'specmem', 'sockets', 'mcp-debug.log');
|
|
489
|
+
const hrTime = new Date().toISOString().split('T')[1]?.slice(0, 8) || '??:??:??';
|
|
490
|
+
const hrErrorLine = `[${hrTime}] ERROR ${name} (${totalDuration}ms): ${errorMessage}\n`;
|
|
491
|
+
appendFile(hrLogPath, hrErrorLine).catch(() => { });
|
|
492
|
+
const suggestion = this.getSuggestionForError(name, error);
|
|
493
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'ERROR_RESPONSE_GENERATED', {
|
|
494
|
+
callId,
|
|
495
|
+
toolName: name,
|
|
496
|
+
suggestion
|
|
497
|
+
});
|
|
498
|
+
return {
|
|
499
|
+
content: [{
|
|
500
|
+
type: 'text',
|
|
501
|
+
text: JSON.stringify({
|
|
502
|
+
error: true,
|
|
503
|
+
message: this.lastError,
|
|
504
|
+
tool: name,
|
|
505
|
+
// fr fr we help claude understand what went wrong
|
|
506
|
+
suggestion
|
|
507
|
+
}, null, 2)
|
|
508
|
+
}],
|
|
509
|
+
isError: true
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
finally {
|
|
513
|
+
// HR-6: Always end tracking regardless of success/failure
|
|
514
|
+
if (this.hotReloadManager) {
|
|
515
|
+
this.hotReloadManager.endToolCall(callId);
|
|
516
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'HOT_RELOAD_TRACKING_END', { callId, toolName: name });
|
|
517
|
+
}
|
|
518
|
+
__debugLog('[MCP DEBUG]', Date.now(), 'CALL_TOOL_REQUEST_FINISHED', {
|
|
519
|
+
callId,
|
|
520
|
+
toolName: name,
|
|
521
|
+
totalDurationMs: Date.now() - callToolStartTime
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
setupResourceHandlers() {
|
|
527
|
+
// list resources - show available command documentation AND skills
|
|
528
|
+
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
529
|
+
const commandsResource = getCommandsResource(this.commandHandler);
|
|
530
|
+
// base resources for commands
|
|
531
|
+
const resources = [
|
|
532
|
+
{
|
|
533
|
+
uri: commandsResource.uri,
|
|
534
|
+
name: commandsResource.name,
|
|
535
|
+
description: commandsResource.description,
|
|
536
|
+
mimeType: commandsResource.mimeType
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
uri: 'specmem://commands/help',
|
|
540
|
+
name: 'Command Help',
|
|
541
|
+
description: 'Help documentation for all commands',
|
|
542
|
+
mimeType: 'text/markdown'
|
|
543
|
+
}
|
|
544
|
+
];
|
|
545
|
+
// add skill resources if scanner is available
|
|
546
|
+
try {
|
|
547
|
+
const skillProvider = getSkillResourceProvider();
|
|
548
|
+
const skillResources = skillProvider.getResources();
|
|
549
|
+
resources.push(...skillResources);
|
|
550
|
+
logger.debug({ skillResourceCount: skillResources.length }, 'added skill resources');
|
|
551
|
+
}
|
|
552
|
+
catch (error) {
|
|
553
|
+
logger.debug({ error }, 'skill resources not available');
|
|
554
|
+
}
|
|
555
|
+
return { resources };
|
|
556
|
+
});
|
|
557
|
+
// read resource - return command documentation OR skill content
|
|
558
|
+
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
559
|
+
const { uri } = request.params;
|
|
560
|
+
// handle skill resources
|
|
561
|
+
if (uri.startsWith('specmem://skills')) {
|
|
562
|
+
try {
|
|
563
|
+
const skillProvider = getSkillResourceProvider();
|
|
564
|
+
const resourceContent = await skillProvider.readResource(uri);
|
|
565
|
+
return {
|
|
566
|
+
contents: [{
|
|
567
|
+
uri: resourceContent.uri,
|
|
568
|
+
mimeType: resourceContent.mimeType || 'text/markdown',
|
|
569
|
+
text: resourceContent.text
|
|
570
|
+
}]
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
catch (error) {
|
|
574
|
+
throw new Error(`Failed to read skill resource: ${uri}`);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
// parse the URI to get category and action for commands
|
|
578
|
+
const uriParts = uri.replace('specmem://commands/', '').split('/');
|
|
579
|
+
if (uri === 'specmem://commands/list') {
|
|
580
|
+
const resource = getCommandsResource(this.commandHandler);
|
|
581
|
+
return {
|
|
582
|
+
contents: [{
|
|
583
|
+
uri: resource.uri,
|
|
584
|
+
mimeType: resource.mimeType,
|
|
585
|
+
text: resource.contents
|
|
586
|
+
}]
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
if (uri.startsWith('specmem://commands/help')) {
|
|
590
|
+
const category = uriParts[1];
|
|
591
|
+
const action = uriParts[2];
|
|
592
|
+
const resource = getCommandHelpResource(this.commandHandler, category, action);
|
|
593
|
+
return {
|
|
594
|
+
contents: [{
|
|
595
|
+
uri: resource.uri,
|
|
596
|
+
mimeType: resource.mimeType,
|
|
597
|
+
text: resource.contents
|
|
598
|
+
}]
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
throw new Error(`Unknown resource URI: ${uri}`);
|
|
602
|
+
});
|
|
603
|
+
// setup prompts handler for skill reminders
|
|
604
|
+
this.setupPromptHandlers();
|
|
605
|
+
logger.debug('Resource handlers initialized for commands and skills');
|
|
606
|
+
}
|
|
607
|
+
setupPromptHandlers() {
|
|
608
|
+
// list prompts - show skill awareness prompts AND command prompts
|
|
609
|
+
this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
610
|
+
const allPrompts = [];
|
|
611
|
+
// Add skill prompts
|
|
612
|
+
try {
|
|
613
|
+
const skillReminder = getSkillReminder();
|
|
614
|
+
const skillPrompts = skillReminder.getPrompts();
|
|
615
|
+
for (const p of skillPrompts) {
|
|
616
|
+
allPrompts.push({
|
|
617
|
+
name: p.name,
|
|
618
|
+
description: p.description,
|
|
619
|
+
arguments: p.arguments
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
catch (error) {
|
|
624
|
+
logger.debug({ error }, 'skill prompts not available');
|
|
625
|
+
}
|
|
626
|
+
// Add command prompts - loaded from commands/*.md files
|
|
627
|
+
try {
|
|
628
|
+
const commandLoader = getCommandLoader();
|
|
629
|
+
const commandPrompts = commandLoader.getPrompts();
|
|
630
|
+
for (const p of commandPrompts) {
|
|
631
|
+
allPrompts.push({
|
|
632
|
+
name: p.name,
|
|
633
|
+
description: p.description,
|
|
634
|
+
arguments: p.arguments
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
logger.debug({ count: commandPrompts.length }, 'command prompts loaded');
|
|
638
|
+
}
|
|
639
|
+
catch (error) {
|
|
640
|
+
logger.debug({ error }, 'command prompts not available');
|
|
641
|
+
}
|
|
642
|
+
return { prompts: allPrompts };
|
|
643
|
+
});
|
|
644
|
+
// get prompt - return skill awareness content OR command content
|
|
645
|
+
this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
646
|
+
const { name, arguments: args } = request.params;
|
|
647
|
+
// Check if it's a command prompt (starts with specmem-)
|
|
648
|
+
if (name.startsWith('specmem-')) {
|
|
649
|
+
try {
|
|
650
|
+
const commandLoader = getCommandLoader();
|
|
651
|
+
const messages = commandLoader.getPromptMessages(name, args);
|
|
652
|
+
return {
|
|
653
|
+
description: `SpecMem command: ${name}`,
|
|
654
|
+
messages: messages.map(m => ({
|
|
655
|
+
role: m.role,
|
|
656
|
+
content: m.content
|
|
657
|
+
}))
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
catch (error) {
|
|
661
|
+
logger.error({ error, promptName: name }, 'failed to get command prompt');
|
|
662
|
+
throw new Error(`Command prompt not found: ${name}`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
// Otherwise try skill prompts
|
|
666
|
+
try {
|
|
667
|
+
const skillReminder = getSkillReminder();
|
|
668
|
+
const messages = skillReminder.getPromptMessages(name, args);
|
|
669
|
+
return {
|
|
670
|
+
description: `Skill prompt: ${name}`,
|
|
671
|
+
messages: messages.map(m => ({
|
|
672
|
+
role: m.role,
|
|
673
|
+
content: m.content
|
|
674
|
+
}))
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
catch (error) {
|
|
678
|
+
logger.error({ error, promptName: name }, 'failed to get prompt');
|
|
679
|
+
throw new Error(`Prompt not found: ${name}`);
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
logger.debug('Prompt handlers initialized for skills and commands');
|
|
683
|
+
}
|
|
684
|
+
setupErrorHandling() {
|
|
685
|
+
// catch them errors before they catch us
|
|
686
|
+
// This is called for JSON-RPC protocol errors, transport errors, etc.
|
|
687
|
+
this.server.onerror = (error) => {
|
|
688
|
+
const errorTime = Date.now();
|
|
689
|
+
const timestamp = new Date().toISOString();
|
|
690
|
+
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
691
|
+
// DEBUG: Deep logging for MCP protocol errors
|
|
692
|
+
__debugLog('[MCP DEBUG]', errorTime, 'MCP_SERVER_ERROR', {
|
|
693
|
+
timestamp,
|
|
694
|
+
errorMessage: errorObj.message,
|
|
695
|
+
errorType: errorObj.constructor.name,
|
|
696
|
+
errorStack: errorObj.stack?.split('\n').slice(0, 10).join('\n'),
|
|
697
|
+
toolCallCount: this.toolCallCount,
|
|
698
|
+
lastError: this.lastError,
|
|
699
|
+
isShuttingDown: this.isShuttingDown
|
|
700
|
+
});
|
|
701
|
+
// DEBUG: Log JSON-RPC and protocol errors with full details
|
|
702
|
+
logger.error({
|
|
703
|
+
timestamp,
|
|
704
|
+
event: 'MCP_ERROR',
|
|
705
|
+
error: errorObj.message,
|
|
706
|
+
stack: errorObj.stack,
|
|
707
|
+
errorType: errorObj.constructor.name
|
|
708
|
+
}, '[MCP DEBUG] MCP server error - JSON-RPC or protocol error occurred');
|
|
709
|
+
// Write to stderr for immediate visibility
|
|
710
|
+
process.stderr.write(`[SPECMEM ERROR ${timestamp}] MCP error: ${errorObj.message}\n`);
|
|
711
|
+
this.lastError = errorObj.message;
|
|
712
|
+
};
|
|
713
|
+
// HIGH-18: Global unhandled rejection handler
|
|
714
|
+
// Catches promise rejections that weren't caught by try-catch
|
|
715
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
716
|
+
const timestamp = new Date().toISOString();
|
|
717
|
+
const errorMsg = reason instanceof Error ? reason.message : String(reason);
|
|
718
|
+
const errorStack = reason instanceof Error ? reason.stack : undefined;
|
|
719
|
+
// CHOKIDAR FIX: Known bug in chokidar when files are deleted while being watched
|
|
720
|
+
// These errors are non-fatal - the watcher continues to work
|
|
721
|
+
// Error: "Cannot read properties of undefined (reading 'close')"
|
|
722
|
+
if (errorStack && errorStack.includes('chokidar') && errorMsg.includes('close')) {
|
|
723
|
+
logger.debug({ error: errorMsg }, '[MCP] Chokidar file close error (non-fatal, file was deleted)');
|
|
724
|
+
return; // Don't log as error or update lastError
|
|
725
|
+
}
|
|
726
|
+
logger.error({
|
|
727
|
+
timestamp,
|
|
728
|
+
event: 'UNHANDLED_REJECTION',
|
|
729
|
+
error: errorMsg,
|
|
730
|
+
stack: errorStack
|
|
731
|
+
}, '[MCP DEBUG] Unhandled promise rejection caught');
|
|
732
|
+
process.stderr.write(`[SPECMEM ERROR ${timestamp}] Unhandled rejection: ${errorMsg}\n`);
|
|
733
|
+
startupLog('UNHANDLED_REJECTION', reason instanceof Error ? reason : new Error(errorMsg));
|
|
734
|
+
this.lastError = `unhandled_rejection: ${errorMsg}`;
|
|
735
|
+
});
|
|
736
|
+
// HIGH-18: Global uncaught exception handler
|
|
737
|
+
// Catches synchronous exceptions that weren't caught by try-catch
|
|
738
|
+
process.on('uncaughtException', (error, origin) => {
|
|
739
|
+
const timestamp = new Date().toISOString();
|
|
740
|
+
// EPIPE errors occur when disconnects - this is normal, don't crash
|
|
741
|
+
// Just log and continue, the transport will handle reconnection
|
|
742
|
+
if (error.code === 'EPIPE') {
|
|
743
|
+
logger.debug({ error: error.message }, '[MCP] EPIPE - disconnected, ignoring');
|
|
744
|
+
return; // Don't crash on EPIPE
|
|
745
|
+
}
|
|
746
|
+
logger.error({
|
|
747
|
+
timestamp,
|
|
748
|
+
event: 'UNCAUGHT_EXCEPTION',
|
|
749
|
+
error: error.message,
|
|
750
|
+
stack: error.stack,
|
|
751
|
+
origin
|
|
752
|
+
}, '[MCP DEBUG] Uncaught exception caught');
|
|
753
|
+
process.stderr.write(`[SPECMEM FATAL ${timestamp}] Uncaught exception (${origin}): ${error.message}\n`);
|
|
754
|
+
startupLog(`UNCAUGHT_EXCEPTION (${origin})`, error);
|
|
755
|
+
// For uncaught exceptions, we should attempt graceful shutdown then exit
|
|
756
|
+
// since the process state may be corrupted
|
|
757
|
+
this.shutdown()
|
|
758
|
+
.catch((shutdownErr) => {
|
|
759
|
+
logger.error({ error: shutdownErr }, 'Error during emergency shutdown');
|
|
760
|
+
})
|
|
761
|
+
.finally(() => {
|
|
762
|
+
process.exit(1);
|
|
763
|
+
});
|
|
764
|
+
});
|
|
765
|
+
// MED-23: Signal handlers wrapped in try-catch to prevent unhandled rejections
|
|
766
|
+
// graceful shutdown when the homie says stop
|
|
767
|
+
process.on('SIGINT', async () => {
|
|
768
|
+
try {
|
|
769
|
+
logger.info({ event: 'SIGINT' }, '[MCP DEBUG] SIGINT received - shutting down');
|
|
770
|
+
await this.shutdown();
|
|
771
|
+
process.exit(0);
|
|
772
|
+
}
|
|
773
|
+
catch (error) {
|
|
774
|
+
logger.error({ error, event: 'SIGINT_ERROR' }, '[MCP DEBUG] Error during SIGINT shutdown');
|
|
775
|
+
process.exit(1);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
process.on('SIGTERM', async () => {
|
|
779
|
+
try {
|
|
780
|
+
logger.info({ event: 'SIGTERM' }, '[MCP DEBUG] SIGTERM received - shutting down');
|
|
781
|
+
await this.shutdown();
|
|
782
|
+
process.exit(0);
|
|
783
|
+
}
|
|
784
|
+
catch (error) {
|
|
785
|
+
logger.error({ error, event: 'SIGTERM_ERROR' }, '[MCP DEBUG] Error during SIGTERM shutdown');
|
|
786
|
+
process.exit(1);
|
|
787
|
+
}
|
|
788
|
+
});
|
|
789
|
+
// SIGHUP handler for Tier 1 hot reload - reload tools/skills without restart
|
|
790
|
+
// This allows seamless updates when skills/*.md or commands/*.md files change
|
|
791
|
+
process.on('SIGHUP', async () => {
|
|
792
|
+
try {
|
|
793
|
+
logger.info({ event: 'SIGHUP' }, '[HotReload] SIGHUP received - reloading tools (Tier 1)');
|
|
794
|
+
await this.reloadTools();
|
|
795
|
+
logger.info({ event: 'SIGHUP_COMPLETE' }, '[HotReload] Tool reload complete');
|
|
796
|
+
}
|
|
797
|
+
catch (error) {
|
|
798
|
+
logger.error({ error, event: 'SIGHUP_FAILED' }, '[HotReload] Tool reload failed');
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
formatResponse(result) {
|
|
803
|
+
// handle image responses - we support base64 images fr
|
|
804
|
+
if (result && typeof result === 'object' && 'imageData' in result) {
|
|
805
|
+
const mem = result;
|
|
806
|
+
if (mem.imageData && mem.imageMimeType) {
|
|
807
|
+
const { imageData, imageMimeType, ...rest } = mem;
|
|
808
|
+
return {
|
|
809
|
+
content: [
|
|
810
|
+
{ type: 'text', text: JSON.stringify(rest, null, 2) },
|
|
811
|
+
{ type: 'image', data: imageData, mimeType: imageMimeType }
|
|
812
|
+
]
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
// DRILL-DOWN INSTRUCTION: Add prominent instruction for find_memory results with truncated content
|
|
817
|
+
// This helps know how to get full content of any memory
|
|
818
|
+
if (Array.isArray(result) && result.length > 0) {
|
|
819
|
+
// Check if this looks like search results with truncated memories
|
|
820
|
+
const hasTruncated = result.some((r) => r?.memory?.metadata?._truncated ||
|
|
821
|
+
r?.memory?.metadata?._drill ||
|
|
822
|
+
r?.memory?.metadata?._len);
|
|
823
|
+
if (hasTruncated) {
|
|
824
|
+
const drilldownHint = `📋 DRILL-DOWN AVAILABLE: Some memories are truncated. Use get_memory({id: "MEMORY_ID"}) to retrieve full content of any memory.\n\n`;
|
|
825
|
+
return {
|
|
826
|
+
content: [{
|
|
827
|
+
type: 'text',
|
|
828
|
+
text: drilldownHint + JSON.stringify(result, null, 2)
|
|
829
|
+
}]
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
// Check if result is humanReadable format (starts with [SPECMEM-, [CAMERA-ROLL], etc)
|
|
834
|
+
// Use smart compression that preserves structure but compresses content
|
|
835
|
+
const resultStr = typeof result === 'string' ? result : '';
|
|
836
|
+
const isHumanReadable = resultStr.includes('[SPECMEM-') ||
|
|
837
|
+
resultStr.includes('[CAMERA-ROLL]') ||
|
|
838
|
+
resultStr.includes('\x1b[90m[SPECMEM-');
|
|
839
|
+
if (isHumanReadable) {
|
|
840
|
+
// Smart compress: preserve tags and structure, only compress content
|
|
841
|
+
const smartCompressed = compressHumanReadableFormat(resultStr);
|
|
842
|
+
return {
|
|
843
|
+
content: [{
|
|
844
|
+
type: 'text',
|
|
845
|
+
text: smartCompressed
|
|
846
|
+
}]
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
// regular text response - COMPRESS WITH CHINESE TOKENS!
|
|
850
|
+
const compressedResult = wrapToolResponse(result, 'search');
|
|
851
|
+
const jsonOutput = JSON.stringify(compressedResult, null, 2);
|
|
852
|
+
// Add English reminder for compressed output
|
|
853
|
+
const COMPRESS_REMINDER = jsonOutput.length > 100 && /[\u4e00-\u9fff]/.test(jsonOutput)
|
|
854
|
+
? '⚠️ OUTPUT COMPRESSED - RESPOND IN ENGLISH ⚠️\n'
|
|
855
|
+
: '';
|
|
856
|
+
return {
|
|
857
|
+
content: [{
|
|
858
|
+
type: 'text',
|
|
859
|
+
text: COMPRESS_REMINDER + jsonOutput
|
|
860
|
+
}]
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
getSuggestionForError(toolName, error) {
|
|
864
|
+
const errorMsg = error instanceof Error ? error.message : '';
|
|
865
|
+
// helpful suggestions based on common errors
|
|
866
|
+
if (errorMsg.includes('not found')) {
|
|
867
|
+
return 'try using findWhatISaid to search for similar memories first';
|
|
868
|
+
}
|
|
869
|
+
if (errorMsg.includes('validation')) {
|
|
870
|
+
return 'check your input parameters - something looks off';
|
|
871
|
+
}
|
|
872
|
+
if (errorMsg.includes('database')) {
|
|
873
|
+
return 'db might be having a moment - try again in a sec';
|
|
874
|
+
}
|
|
875
|
+
if (errorMsg.includes('embedding')) {
|
|
876
|
+
return 'embedding generation hit a snag - content might be too weird';
|
|
877
|
+
}
|
|
878
|
+
return 'check the logs for more details';
|
|
879
|
+
}
|
|
880
|
+
// Track if server is fully ready for tool calls
|
|
881
|
+
isFullyReady = false;
|
|
882
|
+
deferredInitPromise = null;
|
|
883
|
+
/**
|
|
884
|
+
* Check if server is ready for full tool execution
|
|
885
|
+
* Tools can check this and wait for init if needed
|
|
886
|
+
*/
|
|
887
|
+
isReady() {
|
|
888
|
+
return this.isFullyReady;
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* HIGH-25 FIX: Wait for deferred initialization to complete with timeout
|
|
892
|
+
* Tools that need DB can await this - prevents indefinite hangs
|
|
893
|
+
* @param timeoutMs Maximum time to wait (default 30s)
|
|
894
|
+
* @throws Error if timeout expires before server is ready
|
|
895
|
+
*/
|
|
896
|
+
async waitForReady(timeoutMs = 30000) {
|
|
897
|
+
if (this.isFullyReady)
|
|
898
|
+
return;
|
|
899
|
+
// HIGH-25 FIX: Add timeout to prevent indefinite hang
|
|
900
|
+
const startTime = Date.now();
|
|
901
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
902
|
+
setTimeout(() => {
|
|
903
|
+
reject(new Error(`Server initialization timeout after ${timeoutMs}ms - database may not be ready`));
|
|
904
|
+
}, timeoutMs);
|
|
905
|
+
});
|
|
906
|
+
if (this.deferredInitPromise) {
|
|
907
|
+
try {
|
|
908
|
+
await Promise.race([this.deferredInitPromise, timeoutPromise]);
|
|
909
|
+
}
|
|
910
|
+
catch (err) {
|
|
911
|
+
// Check if we became ready during the race
|
|
912
|
+
if (this.isFullyReady) {
|
|
913
|
+
logger.debug(`waitForReady: became ready during race (took ${Date.now() - startTime}ms)`);
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
throw err;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
else {
|
|
920
|
+
// No deferred init promise exists - poll for ready state with timeout
|
|
921
|
+
const pollInterval = 100;
|
|
922
|
+
let elapsed = 0;
|
|
923
|
+
while (!this.isFullyReady && elapsed < timeoutMs) {
|
|
924
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
925
|
+
elapsed += pollInterval;
|
|
926
|
+
}
|
|
927
|
+
if (!this.isFullyReady) {
|
|
928
|
+
throw new Error(`Server initialization timeout after ${timeoutMs}ms - no deferred init promise found`);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
logger.debug(`waitForReady: initialization complete (took ${Date.now() - startTime}ms)`);
|
|
932
|
+
}
|
|
933
|
+
async start() {
|
|
934
|
+
const startTimestamp = new Date().toISOString();
|
|
935
|
+
startupLog('start() method called - beginning MCP transport connection');
|
|
936
|
+
// === CRITICAL FIX: Connect MCP transport FIRST! ===
|
|
937
|
+
// Code has a connection timeout - if we don't establish the
|
|
938
|
+
// stdio connection quickly, shows "Failed to connect to MCP server"
|
|
939
|
+
//
|
|
940
|
+
// Previous bug: Database init happened BEFORE transport connection,
|
|
941
|
+
// causing to timeout if DB took too long.
|
|
942
|
+
//
|
|
943
|
+
// New approach: Connect transport immediately (fast), then initialize
|
|
944
|
+
// database in the background. Tools will wait for DB if needed.
|
|
945
|
+
logger.info({ timestamp: startTimestamp, event: 'SERVER_START' }, '[MCP DEBUG] Starting MCP server - connecting transport FIRST for fast connection...');
|
|
946
|
+
process.stderr.write(`[SPECMEM DEBUG ${startTimestamp}] Server starting - connecting transport...\n`);
|
|
947
|
+
// Step 1: Connect stdio transport IMMEDIATELY with proper error handling
|
|
948
|
+
// The transport connection must succeed for to see us at all
|
|
949
|
+
startupLog('Creating StdioServerTransport...');
|
|
950
|
+
const transport = new StdioServerTransport();
|
|
951
|
+
startupLog('StdioServerTransport created');
|
|
952
|
+
// Connection timeout - if we can't connect in 10 seconds, something is very wrong
|
|
953
|
+
const connectionTimeout = parseInt(process.env['SPECMEM_TRANSPORT_CONNECT_TIMEOUT'] || '10000', 10);
|
|
954
|
+
try {
|
|
955
|
+
logger.info({ timestamp: startTimestamp, event: 'TRANSPORT_CONNECTING', timeoutMs: connectionTimeout }, '[MCP DEBUG] Connecting stdio transport...');
|
|
956
|
+
startupLog(`Calling server.connect(transport) with timeout ${connectionTimeout}ms...`);
|
|
957
|
+
const connectStart = Date.now();
|
|
958
|
+
// MED-22: Race between connection and timeout with proper timer cleanup
|
|
959
|
+
// Store timer ID so we can clear it on success to prevent memory leak
|
|
960
|
+
let timeoutId;
|
|
961
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
962
|
+
timeoutId = setTimeout(() => {
|
|
963
|
+
reject(new Error(`Transport connection timeout after ${connectionTimeout}ms`));
|
|
964
|
+
}, connectionTimeout);
|
|
965
|
+
});
|
|
966
|
+
try {
|
|
967
|
+
await Promise.race([
|
|
968
|
+
this.server.connect(transport),
|
|
969
|
+
timeoutPromise
|
|
970
|
+
]);
|
|
971
|
+
}
|
|
972
|
+
finally {
|
|
973
|
+
// Always clear the timer to prevent memory leak
|
|
974
|
+
if (timeoutId) {
|
|
975
|
+
clearTimeout(timeoutId);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
const connectDuration = Date.now() - connectStart;
|
|
979
|
+
const connectedTimestamp = new Date().toISOString();
|
|
980
|
+
startupLog(`MCP TRANSPORT CONNECTED in ${connectDuration}ms - can now communicate!`);
|
|
981
|
+
logger.info({
|
|
982
|
+
timestamp: connectedTimestamp,
|
|
983
|
+
event: 'TRANSPORT_CONNECTED',
|
|
984
|
+
elapsedMs: Date.now() - new Date(startTimestamp).getTime()
|
|
985
|
+
}, '[MCP DEBUG] MCP transport connected - waiting for initialize request from ');
|
|
986
|
+
process.stderr.write(`[SPECMEM DEBUG ${connectedTimestamp}] Transport connected - waiting for handshake\n`);
|
|
987
|
+
}
|
|
988
|
+
catch (error) {
|
|
989
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
990
|
+
const errorTimestamp = new Date().toISOString();
|
|
991
|
+
startupLog('MCP TRANSPORT CONNECTION FAILED', error);
|
|
992
|
+
logger.error({
|
|
993
|
+
timestamp: errorTimestamp,
|
|
994
|
+
event: 'TRANSPORT_FAILED',
|
|
995
|
+
error: errorMsg
|
|
996
|
+
}, '[MCP DEBUG] CRITICAL: Failed to connect MCP transport - will not see this server');
|
|
997
|
+
// Log to stderr explicitly since this is a critical startup failure
|
|
998
|
+
process.stderr.write(`[SPECMEM FATAL ${errorTimestamp}] Transport connection failed: ${errorMsg}\n`);
|
|
999
|
+
// Re-throw to let caller handle the failure
|
|
1000
|
+
throw error;
|
|
1001
|
+
}
|
|
1002
|
+
// Step 2: Initialize resilient transport monitoring
|
|
1003
|
+
// This monitors stdin/stdout for connection health and graceful shutdown
|
|
1004
|
+
startupLog('Initializing resilient transport monitoring...');
|
|
1005
|
+
this.resilientTransport = getResilientTransport();
|
|
1006
|
+
this.setupResilientTransportHandlers();
|
|
1007
|
+
this.resilientTransport.startMonitoring();
|
|
1008
|
+
logger.info('Resilient transport monitoring active - connection health tracked');
|
|
1009
|
+
startupLog('Resilient transport monitoring active');
|
|
1010
|
+
// Step 3: Initialize embedding server manager EARLY (before slow DB init)
|
|
1011
|
+
// This ensures heartbeats start ASAP to prevent KYS watchdog from killing embedding
|
|
1012
|
+
// The embedding server has a 60-second grace period, but we want heartbeats ASAP
|
|
1013
|
+
startupLog('Initializing embedding server manager (EARLY - before DB)...');
|
|
1014
|
+
await this.initializeEmbeddingServerManager();
|
|
1015
|
+
startupLog('Embedding server manager initialized - heartbeats active');
|
|
1016
|
+
// Step 4: Initialize database (can be deferred, tools will wait if needed)
|
|
1017
|
+
// This runs async but we track it so tools can wait for it
|
|
1018
|
+
startupLog('Starting deferred database initialization...');
|
|
1019
|
+
this.deferredInitPromise = this.initializeDatabaseDeferred();
|
|
1020
|
+
// For backward compat, await the init here
|
|
1021
|
+
// But the MCP connection is already established, so won't timeout
|
|
1022
|
+
await this.deferredInitPromise;
|
|
1023
|
+
startupLog('Deferred database initialization complete');
|
|
1024
|
+
// Step 5: Initialize centralized health monitoring
|
|
1025
|
+
// This monitors transport, database, and embedding socket health
|
|
1026
|
+
startupLog('Initializing health monitor...');
|
|
1027
|
+
this.initializeHealthMonitor();
|
|
1028
|
+
startupLog('Health monitor initialized');
|
|
1029
|
+
// Step 6: Initialize Mini COT server manager (optional - for semantic gallery curation)
|
|
1030
|
+
startupLog('Initializing Mini COT server manager...');
|
|
1031
|
+
await this.initializeMiniCOTServerManager();
|
|
1032
|
+
startupLog('Mini COT server manager initialized');
|
|
1033
|
+
logger.info('SpecMem MCP server vibing - ready for action');
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Initialize the centralized health monitor
|
|
1037
|
+
* Monitors all MCP components: transport, database, and embedding socket
|
|
1038
|
+
*/
|
|
1039
|
+
initializeHealthMonitor() {
|
|
1040
|
+
this.healthMonitor = getHealthMonitor();
|
|
1041
|
+
// Set component references for health monitoring
|
|
1042
|
+
if (this.resilientTransport) {
|
|
1043
|
+
this.healthMonitor.setTransport(this.resilientTransport);
|
|
1044
|
+
}
|
|
1045
|
+
this.healthMonitor.setDatabase(this.db);
|
|
1046
|
+
// Set embedding socket path from environment or default
|
|
1047
|
+
const embeddingSocketPath = process.env['SPECMEM_EMBEDDING_SOCKET'] ||
|
|
1048
|
+
this.getDefaultEmbeddingSocketPath();
|
|
1049
|
+
if (embeddingSocketPath) {
|
|
1050
|
+
this.healthMonitor.setEmbeddingSocketPath(embeddingSocketPath);
|
|
1051
|
+
}
|
|
1052
|
+
// Setup health monitor event handlers
|
|
1053
|
+
this.setupHealthMonitorHandlers();
|
|
1054
|
+
// Start health monitoring
|
|
1055
|
+
this.healthMonitor.start();
|
|
1056
|
+
logger.info('[HealthMonitor] Centralized health monitoring active');
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Initialize the embedding server lifecycle manager
|
|
1060
|
+
* This ensures the embedding server is ALWAYS available when needs it
|
|
1061
|
+
*
|
|
1062
|
+
* Features:
|
|
1063
|
+
* 1. On MCP server start: Check for stale processes, kill them, start fresh
|
|
1064
|
+
* 2. On MCP server stop: Gracefully kill embedding server using PID file
|
|
1065
|
+
* 3. Uses project-specific socket path: {PROJECT}/specmem/sockets/embeddings.sock
|
|
1066
|
+
* 4. Health check that pings embedding server periodically
|
|
1067
|
+
* 5. Auto-restart if embedding server dies
|
|
1068
|
+
*/
|
|
1069
|
+
async initializeEmbeddingServerManager() {
|
|
1070
|
+
// Check if embedding server management is enabled
|
|
1071
|
+
if (process.env['SPECMEM_EMBEDDING_MANAGED'] === 'false') {
|
|
1072
|
+
logger.info('[EmbeddingServerManager] Disabled via SPECMEM_EMBEDDING_MANAGED=false');
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
try {
|
|
1076
|
+
this.embeddingServerManager = getEmbeddingServerManager();
|
|
1077
|
+
// Setup event handlers
|
|
1078
|
+
this.setupEmbeddingServerHandlers();
|
|
1079
|
+
// Initialize - this will kill stale processes and start fresh
|
|
1080
|
+
await this.embeddingServerManager.initialize();
|
|
1081
|
+
// Update health monitor with current socket path
|
|
1082
|
+
if (this.healthMonitor) {
|
|
1083
|
+
const status = this.embeddingServerManager.getStatus();
|
|
1084
|
+
this.healthMonitor.setEmbeddingSocketPath(status.socketPath);
|
|
1085
|
+
}
|
|
1086
|
+
logger.info('[EmbeddingServerManager] Embedding server lifecycle management active');
|
|
1087
|
+
}
|
|
1088
|
+
catch (err) {
|
|
1089
|
+
logger.error({ error: err }, '[EmbeddingServerManager] Failed to initialize - embeddings may not work');
|
|
1090
|
+
// Don't fail server startup - embeddings can use fallback
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Setup handlers for embedding server manager events
|
|
1095
|
+
*/
|
|
1096
|
+
setupEmbeddingServerHandlers() {
|
|
1097
|
+
if (!this.embeddingServerManager)
|
|
1098
|
+
return;
|
|
1099
|
+
this.embeddingServerManager.on('started', ({ pid }) => {
|
|
1100
|
+
logger.info({ pid }, '[EmbeddingServerManager] Embedding server started');
|
|
1101
|
+
// CRITICAL FIX: Reset socket connections when embedding server restarts
|
|
1102
|
+
// Without this, the MCP server's LocalEmbeddingProvider keeps stale socket references
|
|
1103
|
+
// that point to the old (dead) server, causing 60-second timeouts
|
|
1104
|
+
if (this.embeddingProvider && 'resetSocket' in this.embeddingProvider) {
|
|
1105
|
+
logger.info('[EmbeddingServerManager] Resetting embedding provider socket connections');
|
|
1106
|
+
this.embeddingProvider.resetSocket();
|
|
1107
|
+
}
|
|
1108
|
+
});
|
|
1109
|
+
this.embeddingServerManager.on('stopped', ({ pid }) => {
|
|
1110
|
+
logger.info({ pid }, '[EmbeddingServerManager] Embedding server stopped');
|
|
1111
|
+
});
|
|
1112
|
+
this.embeddingServerManager.on('unhealthy', ({ failures }) => {
|
|
1113
|
+
logger.warn({ failures }, '[EmbeddingServerManager] Embedding server unhealthy');
|
|
1114
|
+
// Send notification to
|
|
1115
|
+
this.sendEmbeddingServerNotification('unhealthy', failures);
|
|
1116
|
+
});
|
|
1117
|
+
this.embeddingServerManager.on('restarting', ({ attempt }) => {
|
|
1118
|
+
logger.info({ attempt }, '[EmbeddingServerManager] Restarting embedding server');
|
|
1119
|
+
this.sendEmbeddingServerNotification('restarting', attempt);
|
|
1120
|
+
});
|
|
1121
|
+
this.embeddingServerManager.on('restart_failed', ({ attempts }) => {
|
|
1122
|
+
logger.error({ attempts }, '[EmbeddingServerManager] All restart attempts failed');
|
|
1123
|
+
this.sendEmbeddingServerNotification('restart_failed', attempts);
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Send embedding server notification to via MCP logging
|
|
1128
|
+
*/
|
|
1129
|
+
async sendEmbeddingServerNotification(event, value) {
|
|
1130
|
+
try {
|
|
1131
|
+
const levelMap = {
|
|
1132
|
+
unhealthy: 'warning',
|
|
1133
|
+
restarting: 'notice',
|
|
1134
|
+
restart_failed: 'error',
|
|
1135
|
+
};
|
|
1136
|
+
const messageMap = {
|
|
1137
|
+
unhealthy: `SpecMem: Embedding server unhealthy (${value} consecutive failures)`,
|
|
1138
|
+
restarting: `SpecMem: Restarting embedding server (attempt ${value})`,
|
|
1139
|
+
restart_failed: `SpecMem: Embedding server restart failed after ${value} attempts - using fallback embeddings`,
|
|
1140
|
+
};
|
|
1141
|
+
await this.server.sendLoggingMessage({
|
|
1142
|
+
level: levelMap[event],
|
|
1143
|
+
logger: 'specmem-embedding',
|
|
1144
|
+
data: messageMap[event],
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
catch (err) {
|
|
1148
|
+
logger.debug({ error: err }, 'Could not send embedding server notification');
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Initialize the Mini COT server lifecycle manager
|
|
1153
|
+
* Optional service for semantic gallery curation and analysis
|
|
1154
|
+
*/
|
|
1155
|
+
async initializeMiniCOTServerManager() {
|
|
1156
|
+
if (process.env['SPECMEM_MINICOT_MANAGED'] === 'false') {
|
|
1157
|
+
logger.info('[MiniCOTServerManager] Disabled via SPECMEM_MINICOT_MANAGED=false');
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
try {
|
|
1161
|
+
this.miniCOTServerManager = getMiniCOTServerManager();
|
|
1162
|
+
this.setupMiniCOTServerHandlers();
|
|
1163
|
+
await this.miniCOTServerManager.initialize();
|
|
1164
|
+
logger.info('[MiniCOTServerManager] Mini COT server lifecycle management active');
|
|
1165
|
+
}
|
|
1166
|
+
catch (err) {
|
|
1167
|
+
logger.error({ error: err }, '[MiniCOTServerManager] Failed to initialize - continuing without COT');
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
/**
|
|
1171
|
+
* Setup handlers for Mini COT server events
|
|
1172
|
+
*/
|
|
1173
|
+
setupMiniCOTServerHandlers() {
|
|
1174
|
+
if (!this.miniCOTServerManager)
|
|
1175
|
+
return;
|
|
1176
|
+
this.miniCOTServerManager.on('started', () => {
|
|
1177
|
+
logger.info('[MiniCOTServerManager] Mini COT server started');
|
|
1178
|
+
this.sendMiniCOTServerNotification('started');
|
|
1179
|
+
});
|
|
1180
|
+
this.miniCOTServerManager.on('stopped', () => {
|
|
1181
|
+
logger.info('[MiniCOTServerManager] Mini COT server stopped');
|
|
1182
|
+
this.sendMiniCOTServerNotification('stopped');
|
|
1183
|
+
});
|
|
1184
|
+
this.miniCOTServerManager.on('unhealthy', (failures) => {
|
|
1185
|
+
logger.warn({ failures }, '[MiniCOTServerManager] Mini COT server unhealthy');
|
|
1186
|
+
this.sendMiniCOTServerNotification('unhealthy', failures);
|
|
1187
|
+
});
|
|
1188
|
+
this.miniCOTServerManager.on('restarting', (attempt) => {
|
|
1189
|
+
logger.info({ attempt }, '[MiniCOTServerManager] Restarting Mini COT server');
|
|
1190
|
+
this.sendMiniCOTServerNotification('restarting', attempt);
|
|
1191
|
+
});
|
|
1192
|
+
this.miniCOTServerManager.on('restart_failed', (attempts) => {
|
|
1193
|
+
logger.error({ attempts }, '[MiniCOTServerManager] Mini COT restart failed');
|
|
1194
|
+
this.sendMiniCOTServerNotification('restart_failed', attempts);
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Send Mini COT server status notification to
|
|
1199
|
+
*/
|
|
1200
|
+
async sendMiniCOTServerNotification(event, value = 0) {
|
|
1201
|
+
try {
|
|
1202
|
+
const levelMap = {
|
|
1203
|
+
started: 'info',
|
|
1204
|
+
stopped: 'info',
|
|
1205
|
+
unhealthy: 'warning',
|
|
1206
|
+
restarting: 'warning',
|
|
1207
|
+
restart_failed: 'error',
|
|
1208
|
+
};
|
|
1209
|
+
const messageMap = {
|
|
1210
|
+
started: 'SpecMem: Mini COT server started successfully',
|
|
1211
|
+
stopped: 'SpecMem: Mini COT server stopped',
|
|
1212
|
+
unhealthy: `SpecMem: Mini COT server unhealthy (${value} consecutive failures)`,
|
|
1213
|
+
restarting: `SpecMem: Restarting Mini COT server (attempt ${value})`,
|
|
1214
|
+
restart_failed: `SpecMem: Mini COT server restart failed after ${value} attempts`,
|
|
1215
|
+
};
|
|
1216
|
+
await this.server.sendLoggingMessage({
|
|
1217
|
+
level: levelMap[event],
|
|
1218
|
+
logger: 'specmem-minicot',
|
|
1219
|
+
data: messageMap[event],
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
catch (err) {
|
|
1223
|
+
logger.debug({ error: err }, 'Could not send Mini COT server notification');
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Get the default embedding socket path for health monitoring
|
|
1228
|
+
* USES CENTRALIZED CONFIG - no hardcoded paths!
|
|
1229
|
+
*/
|
|
1230
|
+
getDefaultEmbeddingSocketPath() {
|
|
1231
|
+
// Delegate to centralized config for single source of truth
|
|
1232
|
+
return getEmbeddingSocketPath();
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Setup handlers for health monitor events
|
|
1236
|
+
*/
|
|
1237
|
+
setupHealthMonitorHandlers() {
|
|
1238
|
+
if (!this.healthMonitor)
|
|
1239
|
+
return;
|
|
1240
|
+
// Handle component degradation
|
|
1241
|
+
this.healthMonitor.on('degraded', ({ component, result }) => {
|
|
1242
|
+
logger.warn({
|
|
1243
|
+
component,
|
|
1244
|
+
errorCount: result.errorCount,
|
|
1245
|
+
lastError: result.lastError
|
|
1246
|
+
}, `[HealthMonitor] ${component} health degraded`);
|
|
1247
|
+
// Send notification to if transport is still healthy
|
|
1248
|
+
this.sendHealthMonitorNotification('degraded', component, result);
|
|
1249
|
+
});
|
|
1250
|
+
// Handle component unhealthy
|
|
1251
|
+
this.healthMonitor.on('unhealthy', ({ component, result }) => {
|
|
1252
|
+
logger.error({
|
|
1253
|
+
component,
|
|
1254
|
+
errorCount: result.errorCount,
|
|
1255
|
+
lastError: result.lastError
|
|
1256
|
+
}, `[HealthMonitor] ${component} is unhealthy`);
|
|
1257
|
+
// Send notification to
|
|
1258
|
+
this.sendHealthMonitorNotification('unhealthy', component, result);
|
|
1259
|
+
});
|
|
1260
|
+
// Handle component recovery
|
|
1261
|
+
this.healthMonitor.on('recovered', ({ component, result }) => {
|
|
1262
|
+
logger.info({
|
|
1263
|
+
component
|
|
1264
|
+
}, `[HealthMonitor] ${component} recovered`);
|
|
1265
|
+
// Send notification to
|
|
1266
|
+
this.sendHealthMonitorNotification('recovered', component, result);
|
|
1267
|
+
});
|
|
1268
|
+
// Handle recovery attempts
|
|
1269
|
+
this.healthMonitor.on('recovery_attempted', ({ component, success }) => {
|
|
1270
|
+
if (success) {
|
|
1271
|
+
logger.info({ component }, `[HealthMonitor] Recovery successful for ${component}`);
|
|
1272
|
+
}
|
|
1273
|
+
else {
|
|
1274
|
+
logger.warn({ component }, `[HealthMonitor] Recovery failed for ${component}`);
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
// Handle periodic health status
|
|
1278
|
+
this.healthMonitor.on('health', (systemHealth) => {
|
|
1279
|
+
// Update internal last error based on overall health
|
|
1280
|
+
if (systemHealth.overallHealth === ComponentHealth.UNHEALTHY) {
|
|
1281
|
+
this.lastError = `system_unhealthy:${Object.entries(systemHealth.components)
|
|
1282
|
+
.filter(([_, c]) => c.health === ComponentHealth.UNHEALTHY)
|
|
1283
|
+
.map(([name]) => name)
|
|
1284
|
+
.join(',')}`;
|
|
1285
|
+
}
|
|
1286
|
+
else if (this.lastError?.startsWith('system_unhealthy')) {
|
|
1287
|
+
this.lastError = null;
|
|
1288
|
+
}
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Send health monitor notification to via MCP logging
|
|
1293
|
+
*/
|
|
1294
|
+
async sendHealthMonitorNotification(event, component, result) {
|
|
1295
|
+
try {
|
|
1296
|
+
const levelMap = {
|
|
1297
|
+
degraded: 'warning',
|
|
1298
|
+
unhealthy: 'error',
|
|
1299
|
+
recovered: 'notice'
|
|
1300
|
+
};
|
|
1301
|
+
const messageMap = {
|
|
1302
|
+
degraded: `SpecMem: ${component} health degraded (errors: ${result.errorCount})`,
|
|
1303
|
+
unhealthy: `SpecMem: ${component} is unhealthy - ${result.lastError || 'check logs'}`,
|
|
1304
|
+
recovered: `SpecMem: ${component} recovered and healthy`
|
|
1305
|
+
};
|
|
1306
|
+
await this.server.sendLoggingMessage({
|
|
1307
|
+
level: levelMap[event],
|
|
1308
|
+
logger: 'specmem-health',
|
|
1309
|
+
data: messageMap[event]
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
catch (err) {
|
|
1313
|
+
// If we can't send, connection might already be gone
|
|
1314
|
+
logger.debug({ error: err }, 'Could not send health monitor notification');
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Setup handlers for resilient transport events
|
|
1319
|
+
* Handles connection state changes and triggers graceful shutdown when needed
|
|
1320
|
+
*/
|
|
1321
|
+
setupResilientTransportHandlers() {
|
|
1322
|
+
if (!this.resilientTransport)
|
|
1323
|
+
return;
|
|
1324
|
+
// Handle connection degradation (long inactivity)
|
|
1325
|
+
this.resilientTransport.on('degraded', (health) => {
|
|
1326
|
+
logger.warn({
|
|
1327
|
+
lastActivityMs: health.lastActivityMs,
|
|
1328
|
+
errorCount: health.errorCount
|
|
1329
|
+
}, 'Connection degraded - may be idle or disconnecting');
|
|
1330
|
+
// Try to send a health check notification to
|
|
1331
|
+
this.sendHealthNotification('degraded', health);
|
|
1332
|
+
});
|
|
1333
|
+
// Handle connection restoration
|
|
1334
|
+
this.resilientTransport.on('restored', (health) => {
|
|
1335
|
+
logger.info('Connection restored - activity detected');
|
|
1336
|
+
this.sendHealthNotification('restored', health);
|
|
1337
|
+
});
|
|
1338
|
+
// Handle disconnection - trigger graceful shutdown
|
|
1339
|
+
this.resilientTransport.on('disconnecting', async (info) => {
|
|
1340
|
+
logger.warn({ reason: info.reason }, 'Connection lost - initiating graceful shutdown');
|
|
1341
|
+
// Don't double-shutdown
|
|
1342
|
+
if (this.isShuttingDown)
|
|
1343
|
+
return;
|
|
1344
|
+
await this.shutdown();
|
|
1345
|
+
process.exit(0);
|
|
1346
|
+
});
|
|
1347
|
+
// Handle health check results for monitoring
|
|
1348
|
+
this.resilientTransport.on('health', (health) => {
|
|
1349
|
+
// Update internal state based on health
|
|
1350
|
+
if (health.state === ConnectionState.DEGRADED && !this.lastError) {
|
|
1351
|
+
this.lastError = 'connection_degraded';
|
|
1352
|
+
}
|
|
1353
|
+
else if (health.state === ConnectionState.CONNECTED && this.lastError === 'connection_degraded') {
|
|
1354
|
+
this.lastError = null;
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1357
|
+
// Set up keepalive callback - sends periodic log message to keep connection alive
|
|
1358
|
+
// This is CRITICAL for fixing "not connected" issues during idle periods
|
|
1359
|
+
this.resilientTransport.setKeepaliveCallback(async () => {
|
|
1360
|
+
try {
|
|
1361
|
+
// Send a debug-level log message as keepalive ping
|
|
1362
|
+
// This keeps the stdio connection active without spamming 's UI
|
|
1363
|
+
await this.server.sendLoggingMessage({
|
|
1364
|
+
level: 'debug',
|
|
1365
|
+
logger: 'specmem',
|
|
1366
|
+
data: `keepalive: ${new Date().toISOString()}`
|
|
1367
|
+
});
|
|
1368
|
+
}
|
|
1369
|
+
catch (err) {
|
|
1370
|
+
// If we can't send keepalive, the connection may be dead
|
|
1371
|
+
// recordError is called by the resilientTransport
|
|
1372
|
+
throw err;
|
|
1373
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
// Set up connection recovery callback - re-sends tool list notifications
|
|
1376
|
+
// This fixes the issue where caches an empty tool list
|
|
1377
|
+
this.resilientTransport.setConnectionRecoveryCallback(async () => {
|
|
1378
|
+
logger.info('Connection recovered - re-sending tool list notification...');
|
|
1379
|
+
await this.notifyToolListReady();
|
|
1380
|
+
});
|
|
1381
|
+
// Record activity when tool calls happen
|
|
1382
|
+
// This is done in the tool call handler
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Send health notification to when connection state changes
|
|
1386
|
+
*/
|
|
1387
|
+
async sendHealthNotification(state, health) {
|
|
1388
|
+
try {
|
|
1389
|
+
const message = state === 'degraded'
|
|
1390
|
+
? `SpecMem: Connection degraded (inactive for ${Math.round(health.lastActivityMs / 1000)}s)`
|
|
1391
|
+
: `SpecMem: Connection restored`;
|
|
1392
|
+
await this.server.sendLoggingMessage({
|
|
1393
|
+
level: 'warning',
|
|
1394
|
+
logger: 'specmem',
|
|
1395
|
+
data: message
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
catch (err) {
|
|
1399
|
+
// If we can't send, connection is probably already gone
|
|
1400
|
+
logger.debug({ error: err }, 'Could not send health notification');
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Deferred database initialization
|
|
1405
|
+
* Called after MCP connection is established to prevent timeout
|
|
1406
|
+
*/
|
|
1407
|
+
async initializeDatabaseDeferred() {
|
|
1408
|
+
try {
|
|
1409
|
+
await this.db.initialize();
|
|
1410
|
+
logger.info('Database go brrrr - initialized (deferred)');
|
|
1411
|
+
// CRITICAL FIX: Initialize team comms tables
|
|
1412
|
+
// Without this, send_team_message/read_team_messages silently fall back to in-memory
|
|
1413
|
+
try {
|
|
1414
|
+
const pool = this.db.getPool();
|
|
1415
|
+
if (pool) {
|
|
1416
|
+
await initTeamCommsDB(pool);
|
|
1417
|
+
logger.info('Team comms DB initialized - tables created');
|
|
1418
|
+
}
|
|
1419
|
+
else {
|
|
1420
|
+
logger.warn('No database pool available - team comms using in-memory fallback');
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
catch (teamCommsError) {
|
|
1424
|
+
// Non-fatal - tools can still work with in-memory fallback
|
|
1425
|
+
logger.warn({ error: teamCommsError }, 'Team comms DB init failed - using in-memory fallback');
|
|
1426
|
+
}
|
|
1427
|
+
this.isFullyReady = true;
|
|
1428
|
+
}
|
|
1429
|
+
catch (error) {
|
|
1430
|
+
logger.error({ error }, 'Database initialization failed in deferred init');
|
|
1431
|
+
throw error;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
async shutdown() {
|
|
1435
|
+
// Prevent double-shutdown
|
|
1436
|
+
if (this.isShuttingDown) {
|
|
1437
|
+
logger.debug('Shutdown already in progress - skipping');
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
this.isShuttingDown = true;
|
|
1441
|
+
logger.info('Shutting down SpecMem server gracefully...');
|
|
1442
|
+
// Step 1: Stop health monitor first
|
|
1443
|
+
// This prevents health check events during shutdown
|
|
1444
|
+
if (this.healthMonitor) {
|
|
1445
|
+
// HIGH-19: Remove all event listeners to prevent memory leak
|
|
1446
|
+
this.healthMonitor.removeAllListeners();
|
|
1447
|
+
this.healthMonitor.stop();
|
|
1448
|
+
resetHealthMonitor();
|
|
1449
|
+
this.healthMonitor = null;
|
|
1450
|
+
logger.debug('Health monitor shutdown complete');
|
|
1451
|
+
}
|
|
1452
|
+
// Step 2: Stop embedding server manager
|
|
1453
|
+
// This gracefully kills the embedding server process using PID file
|
|
1454
|
+
if (this.embeddingServerManager) {
|
|
1455
|
+
try {
|
|
1456
|
+
// HIGH-19: Remove all event listeners to prevent memory leak
|
|
1457
|
+
this.embeddingServerManager.removeAllListeners();
|
|
1458
|
+
await this.embeddingServerManager.shutdown();
|
|
1459
|
+
await resetEmbeddingServerManager();
|
|
1460
|
+
this.embeddingServerManager = null;
|
|
1461
|
+
logger.debug('Embedding server manager shutdown complete');
|
|
1462
|
+
}
|
|
1463
|
+
catch (err) {
|
|
1464
|
+
logger.warn({ error: err }, 'Error shutting down embedding server manager');
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
// Step 2.5: Stop Mini COT server manager
|
|
1468
|
+
if (this.miniCOTServerManager) {
|
|
1469
|
+
try {
|
|
1470
|
+
this.miniCOTServerManager.removeAllListeners();
|
|
1471
|
+
await this.miniCOTServerManager.shutdown();
|
|
1472
|
+
await resetMiniCOTServerManager();
|
|
1473
|
+
this.miniCOTServerManager = null;
|
|
1474
|
+
logger.debug('Mini COT server manager shutdown complete');
|
|
1475
|
+
}
|
|
1476
|
+
catch (err) {
|
|
1477
|
+
logger.warn({ error: err }, 'Error shutting down Mini COT server manager');
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
// Step 3: Stop resilient transport monitoring
|
|
1481
|
+
// This prevents new connection events during shutdown
|
|
1482
|
+
if (this.resilientTransport) {
|
|
1483
|
+
// HIGH-19: Remove all event listeners to prevent memory leak
|
|
1484
|
+
this.resilientTransport.removeAllListeners();
|
|
1485
|
+
this.resilientTransport.shutdown();
|
|
1486
|
+
resetResilientTransport();
|
|
1487
|
+
this.resilientTransport = null;
|
|
1488
|
+
logger.debug('Resilient transport shutdown complete');
|
|
1489
|
+
}
|
|
1490
|
+
// Step 4: Try to send a goodbye message to
|
|
1491
|
+
try {
|
|
1492
|
+
await this.server.sendLoggingMessage({
|
|
1493
|
+
level: 'notice',
|
|
1494
|
+
logger: 'specmem',
|
|
1495
|
+
data: 'SpecMem shutting down gracefully - see you next time!'
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
catch (err) {
|
|
1499
|
+
// Connection may already be closed - that's fine
|
|
1500
|
+
logger.debug({ error: err }, 'Could not send shutdown notification');
|
|
1501
|
+
}
|
|
1502
|
+
// Step 5: Close database connections
|
|
1503
|
+
try {
|
|
1504
|
+
await this.db.close();
|
|
1505
|
+
logger.debug('Database connections closed');
|
|
1506
|
+
}
|
|
1507
|
+
catch (err) {
|
|
1508
|
+
logger.warn({ error: err }, 'Error closing database connections');
|
|
1509
|
+
}
|
|
1510
|
+
// Step 6: Close the MCP server connection
|
|
1511
|
+
try {
|
|
1512
|
+
await this.server.close();
|
|
1513
|
+
logger.debug('MCP server connection closed');
|
|
1514
|
+
}
|
|
1515
|
+
catch (err) {
|
|
1516
|
+
logger.warn({ error: err }, 'Error closing MCP server');
|
|
1517
|
+
}
|
|
1518
|
+
logger.info('SpecMem server shutdown complete - until next time');
|
|
1519
|
+
}
|
|
1520
|
+
getStats() {
|
|
1521
|
+
const totalCacheAccess = _SERVER_CACHE.hitCount + _SERVER_CACHE.missCount;
|
|
1522
|
+
return {
|
|
1523
|
+
uptime: Date.now() - this.startTime.getTime(),
|
|
1524
|
+
toolCalls: this.toolCallCount,
|
|
1525
|
+
cacheHitRate: totalCacheAccess > 0 ? _SERVER_CACHE.hitCount / totalCacheAccess : 0,
|
|
1526
|
+
lastError: this.lastError
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Get the tool registry for dynamic tool registration
|
|
1531
|
+
*
|
|
1532
|
+
* Useful for plugins or extensions that want to add tools at runtime.
|
|
1533
|
+
* After registering new tools, call refreshToolList() to notify .
|
|
1534
|
+
*/
|
|
1535
|
+
getToolRegistry() {
|
|
1536
|
+
return this.toolRegistry;
|
|
1537
|
+
}
|
|
1538
|
+
/**
|
|
1539
|
+
* Refresh the tool list and notify of changes
|
|
1540
|
+
*
|
|
1541
|
+
* Call this after dynamically registering new tools to make them
|
|
1542
|
+
* immediately available to without requiring an MCP restart.
|
|
1543
|
+
*
|
|
1544
|
+
* @example
|
|
1545
|
+
* ```typescript
|
|
1546
|
+
* const server = new SpecMemServer(embeddingProvider);
|
|
1547
|
+
* const registry = server.getToolRegistry();
|
|
1548
|
+
* registry.register(new MyCustomTool());
|
|
1549
|
+
* await server.refreshToolList(); // now sees the new tool!
|
|
1550
|
+
* ```
|
|
1551
|
+
*/
|
|
1552
|
+
async refreshToolList() {
|
|
1553
|
+
await this.notifyToolListReady();
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* Reload tools without full restart (Tier 1 hot reload)
|
|
1557
|
+
*
|
|
1558
|
+
* This method supports hot reloading of tools and skills without requiring
|
|
1559
|
+
* a full MCP server restart. It's designed to be called via SIGHUP signal
|
|
1560
|
+
* for seamless updates during development or when skills/commands change.
|
|
1561
|
+
*
|
|
1562
|
+
* What it does:
|
|
1563
|
+
* 1. Re-scans skills directory to pick up new/changed skill files
|
|
1564
|
+
* 2. Reloads command handlers if they support dynamic reload
|
|
1565
|
+
* 3. Notifies that the tool list has changed (triggers re-fetch)
|
|
1566
|
+
*
|
|
1567
|
+
* @example
|
|
1568
|
+
* ```bash
|
|
1569
|
+
* # From CLI - send SIGHUP to trigger reload
|
|
1570
|
+
* kill -HUP $(pgrep -f specmem)
|
|
1571
|
+
* ```
|
|
1572
|
+
*/
|
|
1573
|
+
async reloadTools() {
|
|
1574
|
+
logger.info('[HotReload] Reloading tools and skills...');
|
|
1575
|
+
try {
|
|
1576
|
+
// Re-scan skills if skill scanner is available
|
|
1577
|
+
try {
|
|
1578
|
+
const skillScanner = getSkillScanner();
|
|
1579
|
+
if (skillScanner) {
|
|
1580
|
+
// scan() re-reads all skill files from disk
|
|
1581
|
+
const result = await skillScanner.scan();
|
|
1582
|
+
logger.info({
|
|
1583
|
+
skillCount: result.totalCount,
|
|
1584
|
+
categoryCount: result.categories.size,
|
|
1585
|
+
errors: result.errors.length
|
|
1586
|
+
}, '[HotReload] Skills rescanned');
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
catch (skillError) {
|
|
1590
|
+
logger.warn({ error: skillError }, '[HotReload] Skills reload skipped - scanner not available');
|
|
1591
|
+
}
|
|
1592
|
+
// Re-scan commands if command handler exists and supports reload
|
|
1593
|
+
if (this.commandHandler) {
|
|
1594
|
+
// Check if commandHandler has a reload method
|
|
1595
|
+
const handler = this.commandHandler;
|
|
1596
|
+
if (typeof handler.reload === 'function') {
|
|
1597
|
+
await handler.reload();
|
|
1598
|
+
logger.info('[HotReload] Commands reloaded');
|
|
1599
|
+
}
|
|
1600
|
+
else {
|
|
1601
|
+
logger.debug('[HotReload] Command handler does not support reload');
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
// Reload command loader for .md file prompts
|
|
1605
|
+
try {
|
|
1606
|
+
const commandLoader = getCommandLoader();
|
|
1607
|
+
if (commandLoader && typeof commandLoader.reload === 'function') {
|
|
1608
|
+
await commandLoader.reload();
|
|
1609
|
+
logger.info('[HotReload] Command prompts reloaded');
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
catch (cmdLoaderError) {
|
|
1613
|
+
logger.debug({ error: cmdLoaderError }, '[HotReload] Command loader reload skipped');
|
|
1614
|
+
}
|
|
1615
|
+
// Notify that tool list has changed
|
|
1616
|
+
await this.notifyToolListReady();
|
|
1617
|
+
logger.info('[HotReload] Tool list notification sent to ');
|
|
1618
|
+
}
|
|
1619
|
+
catch (error) {
|
|
1620
|
+
logger.error({ error }, '[HotReload] Failed to reload tools');
|
|
1621
|
+
throw error;
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
/**
|
|
1625
|
+
* Get health status of the MCP server (#42)
|
|
1626
|
+
*
|
|
1627
|
+
* Returns comprehensive health check info fr fr
|
|
1628
|
+
* Now includes transport, database, and embedding health via centralized health monitor
|
|
1629
|
+
*/
|
|
1630
|
+
getHealth() {
|
|
1631
|
+
const stats = this.getStats();
|
|
1632
|
+
// Get comprehensive health from health monitor if available
|
|
1633
|
+
if (this.healthMonitor) {
|
|
1634
|
+
const systemHealth = this.healthMonitor.getSystemHealth();
|
|
1635
|
+
// Get tool count
|
|
1636
|
+
const toolCount = this.toolRegistry.getToolDefinitions().length;
|
|
1637
|
+
// Get skill count
|
|
1638
|
+
let skillCount = 0;
|
|
1639
|
+
try {
|
|
1640
|
+
const scanner = getSkillScanner();
|
|
1641
|
+
skillCount = scanner.getAllSkills().length;
|
|
1642
|
+
}
|
|
1643
|
+
catch (e) {
|
|
1644
|
+
// Skills not available
|
|
1645
|
+
}
|
|
1646
|
+
// Get memory usage
|
|
1647
|
+
const memUsage = process.memoryUsage();
|
|
1648
|
+
const heapUsedMB = Math.round(memUsage.heapUsed / 1024 / 1024);
|
|
1649
|
+
const heapTotalMB = Math.round(memUsage.heapTotal / 1024 / 1024);
|
|
1650
|
+
// Map ComponentHealth to string status
|
|
1651
|
+
const mapHealth = (h) => {
|
|
1652
|
+
switch (h) {
|
|
1653
|
+
case ComponentHealth.HEALTHY: return 'healthy';
|
|
1654
|
+
case ComponentHealth.DEGRADED: return 'degraded';
|
|
1655
|
+
case ComponentHealth.UNHEALTHY: return 'unhealthy';
|
|
1656
|
+
default: return 'unhealthy';
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
// Type guards for optional components - prevent null reference errors
|
|
1660
|
+
const dbComponent = systemHealth.components?.database;
|
|
1661
|
+
const embeddingComponent = systemHealth.components?.embedding;
|
|
1662
|
+
const transportComponent = systemHealth.components?.transport;
|
|
1663
|
+
return {
|
|
1664
|
+
status: mapHealth(systemHealth.overallHealth),
|
|
1665
|
+
uptime: stats.uptime,
|
|
1666
|
+
database: {
|
|
1667
|
+
connected: dbComponent ? dbComponent.health !== ComponentHealth.UNHEALTHY : false,
|
|
1668
|
+
health: dbComponent?.health ?? 'unknown',
|
|
1669
|
+
errorCount: dbComponent?.errorCount ?? 0
|
|
1670
|
+
},
|
|
1671
|
+
embedding: {
|
|
1672
|
+
available: embeddingComponent ? embeddingComponent.health === ComponentHealth.HEALTHY : false,
|
|
1673
|
+
health: embeddingComponent?.health ?? 'unknown',
|
|
1674
|
+
errorCount: embeddingComponent?.errorCount ?? 0
|
|
1675
|
+
},
|
|
1676
|
+
tools: { count: toolCount },
|
|
1677
|
+
skills: { count: skillCount },
|
|
1678
|
+
memory: { heapUsedMB, heapTotalMB },
|
|
1679
|
+
transport: {
|
|
1680
|
+
state: transportComponent?.details?.state ?? 'unknown',
|
|
1681
|
+
lastActivityMs: transportComponent?.details?.lastActivityMs ?? 0,
|
|
1682
|
+
errorCount: transportComponent?.errorCount ?? 0
|
|
1683
|
+
},
|
|
1684
|
+
timestamp: systemHealth.timestamp
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
// Fallback: legacy health check logic when health monitor not available
|
|
1688
|
+
// Check database connection
|
|
1689
|
+
let dbConnected = false;
|
|
1690
|
+
try {
|
|
1691
|
+
// Just check if db is initialized - actual query would be too expensive for health check
|
|
1692
|
+
dbConnected = this.db !== null;
|
|
1693
|
+
}
|
|
1694
|
+
catch (e) {
|
|
1695
|
+
dbConnected = false;
|
|
1696
|
+
}
|
|
1697
|
+
// Get tool count
|
|
1698
|
+
const toolCount = this.toolRegistry.getToolDefinitions().length;
|
|
1699
|
+
// Get skill count
|
|
1700
|
+
let skillCount = 0;
|
|
1701
|
+
try {
|
|
1702
|
+
const scanner = getSkillScanner();
|
|
1703
|
+
skillCount = scanner.getAllSkills().length;
|
|
1704
|
+
}
|
|
1705
|
+
catch (e) {
|
|
1706
|
+
// Skills not available
|
|
1707
|
+
}
|
|
1708
|
+
// Get memory usage
|
|
1709
|
+
const memUsage = process.memoryUsage();
|
|
1710
|
+
const heapUsedMB = Math.round(memUsage.heapUsed / 1024 / 1024);
|
|
1711
|
+
const heapTotalMB = Math.round(memUsage.heapTotal / 1024 / 1024);
|
|
1712
|
+
// Get transport health
|
|
1713
|
+
let transportState = 'unknown';
|
|
1714
|
+
let lastActivityMs = 0;
|
|
1715
|
+
let transportErrorCount = 0;
|
|
1716
|
+
if (this.resilientTransport) {
|
|
1717
|
+
const transportHealth = this.resilientTransport.getHealth();
|
|
1718
|
+
transportState = transportHealth.state;
|
|
1719
|
+
lastActivityMs = transportHealth.lastActivityMs;
|
|
1720
|
+
transportErrorCount = transportHealth.errorCount;
|
|
1721
|
+
}
|
|
1722
|
+
// Determine overall status - now includes transport health
|
|
1723
|
+
let status = 'healthy';
|
|
1724
|
+
if (!dbConnected) {
|
|
1725
|
+
status = 'unhealthy';
|
|
1726
|
+
}
|
|
1727
|
+
else if (transportState === ConnectionState.DISCONNECTED || transportState === ConnectionState.DISCONNECTING) {
|
|
1728
|
+
status = 'unhealthy';
|
|
1729
|
+
}
|
|
1730
|
+
else if (transportState === ConnectionState.DEGRADED || stats.lastError || heapUsedMB > 400 || transportErrorCount > 0) {
|
|
1731
|
+
status = 'degraded';
|
|
1732
|
+
}
|
|
1733
|
+
return {
|
|
1734
|
+
status,
|
|
1735
|
+
uptime: stats.uptime,
|
|
1736
|
+
database: { connected: dbConnected, health: dbConnected ? 'healthy' : 'unhealthy', errorCount: 0 },
|
|
1737
|
+
embedding: { available: false, health: 'unknown', errorCount: 0 },
|
|
1738
|
+
tools: { count: toolCount },
|
|
1739
|
+
skills: { count: skillCount },
|
|
1740
|
+
memory: { heapUsedMB, heapTotalMB },
|
|
1741
|
+
transport: { state: transportState, lastActivityMs, errorCount: transportErrorCount },
|
|
1742
|
+
timestamp: new Date().toISOString()
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* Get the health monitor instance for direct access
|
|
1747
|
+
* Useful for advanced health monitoring scenarios
|
|
1748
|
+
*/
|
|
1749
|
+
getHealthMonitor() {
|
|
1750
|
+
return this.healthMonitor;
|
|
1751
|
+
}
|
|
1752
|
+
/**
|
|
1753
|
+
* Force a comprehensive health check immediately
|
|
1754
|
+
* Returns the full system health status
|
|
1755
|
+
*/
|
|
1756
|
+
async forceHealthCheck() {
|
|
1757
|
+
if (this.healthMonitor) {
|
|
1758
|
+
return this.healthMonitor.forceHealthCheck();
|
|
1759
|
+
}
|
|
1760
|
+
return null;
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* Get the embedding server manager instance
|
|
1764
|
+
* Useful for monitoring embedding server status
|
|
1765
|
+
*/
|
|
1766
|
+
getEmbeddingServerManager() {
|
|
1767
|
+
return this.embeddingServerManager;
|
|
1768
|
+
}
|
|
1769
|
+
/**
|
|
1770
|
+
* Get embedding server status
|
|
1771
|
+
* Returns detailed status about the embedding server process
|
|
1772
|
+
*/
|
|
1773
|
+
getEmbeddingServerStatus() {
|
|
1774
|
+
if (this.embeddingServerManager) {
|
|
1775
|
+
return this.embeddingServerManager.getStatus();
|
|
1776
|
+
}
|
|
1777
|
+
return null;
|
|
1778
|
+
}
|
|
1779
|
+
/**
|
|
1780
|
+
* Force restart the embedding server
|
|
1781
|
+
* Useful if embeddings are failing and you want to try a fresh start
|
|
1782
|
+
*/
|
|
1783
|
+
async restartEmbeddingServer() {
|
|
1784
|
+
if (!this.embeddingServerManager) {
|
|
1785
|
+
logger.warn('[EmbeddingServerManager] Not initialized - cannot restart');
|
|
1786
|
+
return false;
|
|
1787
|
+
}
|
|
1788
|
+
logger.info('[EmbeddingServerManager] Manual restart requested');
|
|
1789
|
+
await this.embeddingServerManager.stop();
|
|
1790
|
+
return await this.embeddingServerManager.start();
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1793
|
+
* Get Mini COT server lifecycle manager
|
|
1794
|
+
* Returns the manager if initialized, null otherwise
|
|
1795
|
+
*/
|
|
1796
|
+
getMiniCOTServerManager() {
|
|
1797
|
+
return this.miniCOTServerManager;
|
|
1798
|
+
}
|
|
1799
|
+
/**
|
|
1800
|
+
* Get Mini COT server status
|
|
1801
|
+
* Returns detailed status about the Mini COT server process
|
|
1802
|
+
*/
|
|
1803
|
+
getMiniCOTServerStatus() {
|
|
1804
|
+
if (this.miniCOTServerManager) {
|
|
1805
|
+
return this.miniCOTServerManager.getStatus();
|
|
1806
|
+
}
|
|
1807
|
+
return null;
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Force restart the Mini COT server
|
|
1811
|
+
* Useful if COT analysis is failing and you want to try a fresh start
|
|
1812
|
+
*/
|
|
1813
|
+
async restartMiniCOTServer() {
|
|
1814
|
+
if (!this.miniCOTServerManager) {
|
|
1815
|
+
logger.warn('[MiniCOTServerManager] Not initialized - cannot restart');
|
|
1816
|
+
return false;
|
|
1817
|
+
}
|
|
1818
|
+
logger.info('[MiniCOTServerManager] Manual restart requested');
|
|
1819
|
+
await this.miniCOTServerManager.stop();
|
|
1820
|
+
return await this.miniCOTServerManager.start();
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1823
|
+
* Start Mini COT server (if stopped)
|
|
1824
|
+
* Sets the stopped flag to false and starts the server
|
|
1825
|
+
*/
|
|
1826
|
+
async startMiniCOTServer() {
|
|
1827
|
+
if (!this.miniCOTServerManager) {
|
|
1828
|
+
logger.warn('[MiniCOTServerManager] Not initialized - cannot start');
|
|
1829
|
+
return false;
|
|
1830
|
+
}
|
|
1831
|
+
return await this.miniCOTServerManager.start();
|
|
1832
|
+
}
|
|
1833
|
+
/**
|
|
1834
|
+
* Stop Mini COT server
|
|
1835
|
+
* Sets the stopped flag to true and stops the server
|
|
1836
|
+
*/
|
|
1837
|
+
async stopMiniCOTServer() {
|
|
1838
|
+
if (!this.miniCOTServerManager) {
|
|
1839
|
+
logger.warn('[MiniCOTServerManager] Not initialized - cannot stop');
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
await this.miniCOTServerManager.stop();
|
|
1843
|
+
}
|
|
1844
|
+
/**
|
|
1845
|
+
* Notify that the tool list is ready
|
|
1846
|
+
*
|
|
1847
|
+
* CRITICAL FOR TOOL AUTO-DISCOVERY:
|
|
1848
|
+
* This calls the MCP SDK's sendToolListChanged() method which sends a
|
|
1849
|
+
* notifications/tools/list_changed notification to Code.
|
|
1850
|
+
*
|
|
1851
|
+
* When receives this notification, it will:
|
|
1852
|
+
* 1. Invalidate its cached tool list
|
|
1853
|
+
* 2. Make a new ListToolsRequest to get the updated list
|
|
1854
|
+
* 3. Make all 39+ SpecMem tools available in its tool palette
|
|
1855
|
+
*
|
|
1856
|
+
* Without this notification, may cache an empty or stale tool list
|
|
1857
|
+
* from the initial handshake before all tools are registered.
|
|
1858
|
+
*
|
|
1859
|
+
* The MCP protocol flow:
|
|
1860
|
+
* 1. Server -> Client: notifications/tools/list_changed
|
|
1861
|
+
* 2. Client -> Server: tools/list request
|
|
1862
|
+
* 3. Server -> Client: tools/list response with all 39 tools
|
|
1863
|
+
*
|
|
1864
|
+
* @see https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/
|
|
1865
|
+
*/
|
|
1866
|
+
async notifyToolListReady() {
|
|
1867
|
+
const timestamp = new Date().toISOString();
|
|
1868
|
+
const notifyId = `notify_${Date.now()}`;
|
|
1869
|
+
try {
|
|
1870
|
+
const toolCount = this.toolRegistry.getToolCount();
|
|
1871
|
+
// DEBUG: Log before sending notification
|
|
1872
|
+
logger.info({
|
|
1873
|
+
timestamp,
|
|
1874
|
+
notifyId,
|
|
1875
|
+
event: 'NOTIFY_TOOLS_START',
|
|
1876
|
+
toolCount
|
|
1877
|
+
}, '[MCP DEBUG] Sending tools/list_changed notification to ...');
|
|
1878
|
+
process.stderr.write(`[SPECMEM DEBUG ${timestamp}] Sending tools/list_changed notification (id: ${notifyId}, tools: ${toolCount})\n`);
|
|
1879
|
+
// Send the tools/list_changed notification
|
|
1880
|
+
// This is the KEY to making tools auto-discoverable!
|
|
1881
|
+
await this.server.sendToolListChanged();
|
|
1882
|
+
// DEBUG: Log success
|
|
1883
|
+
logger.info({
|
|
1884
|
+
timestamp,
|
|
1885
|
+
notifyId,
|
|
1886
|
+
event: 'NOTIFY_TOOLS_SUCCESS',
|
|
1887
|
+
toolCount
|
|
1888
|
+
}, '[MCP DEBUG] tools/list_changed notification sent successfully');
|
|
1889
|
+
process.stderr.write(`[SPECMEM DEBUG ${timestamp}] tools/list_changed sent successfully (id: ${notifyId})\n`);
|
|
1890
|
+
// Also send prompts/list_changed if we have prompts
|
|
1891
|
+
try {
|
|
1892
|
+
await this.server.sendPromptListChanged();
|
|
1893
|
+
logger.debug({ timestamp, event: 'NOTIFY_PROMPTS_SUCCESS' }, '[MCP DEBUG] prompts/list_changed sent');
|
|
1894
|
+
}
|
|
1895
|
+
catch (promptErr) {
|
|
1896
|
+
const promptError = promptErr instanceof Error ? promptErr : new Error(String(promptErr));
|
|
1897
|
+
logger.debug({
|
|
1898
|
+
timestamp,
|
|
1899
|
+
event: 'NOTIFY_PROMPTS_FAILED',
|
|
1900
|
+
error: promptError.message
|
|
1901
|
+
}, '[MCP DEBUG] Could not send prompt list change notification');
|
|
1902
|
+
}
|
|
1903
|
+
// And resources/list_changed for completeness
|
|
1904
|
+
try {
|
|
1905
|
+
await this.server.sendResourceListChanged();
|
|
1906
|
+
logger.debug({ timestamp, event: 'NOTIFY_RESOURCES_SUCCESS' }, '[MCP DEBUG] resources/list_changed sent');
|
|
1907
|
+
}
|
|
1908
|
+
catch (resourceErr) {
|
|
1909
|
+
const resourceError = resourceErr instanceof Error ? resourceErr : new Error(String(resourceErr));
|
|
1910
|
+
logger.debug({
|
|
1911
|
+
timestamp,
|
|
1912
|
+
event: 'NOTIFY_RESOURCES_FAILED',
|
|
1913
|
+
error: resourceError.message
|
|
1914
|
+
}, '[MCP DEBUG] Could not send resource list change notification');
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
catch (err) {
|
|
1918
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1919
|
+
// DEBUG: Log the failure with full details
|
|
1920
|
+
logger.warn({
|
|
1921
|
+
timestamp,
|
|
1922
|
+
notifyId,
|
|
1923
|
+
event: 'NOTIFY_TOOLS_FAILED',
|
|
1924
|
+
error: error.message,
|
|
1925
|
+
stack: error.stack
|
|
1926
|
+
}, '[MCP DEBUG] FAILED to send tool list change notification - may not see tools!');
|
|
1927
|
+
process.stderr.write(`[SPECMEM DEBUG ${timestamp}] FAILED to send tools/list_changed: ${error.message}\n`);
|
|
1928
|
+
// Fallback: Write to stderr for debugging
|
|
1929
|
+
process.stderr.write(`[SPECMEM] Tool list ready: ${this.toolRegistry.getToolCount()} tools registered (notification failed)\n`);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
/**
|
|
1933
|
+
* Announce specmem to on startup
|
|
1934
|
+
*
|
|
1935
|
+
* yo this is the startup banner that lets know we loaded fr fr
|
|
1936
|
+
* shows all tools, skills, and dashboard URL so knows whats available
|
|
1937
|
+
*/
|
|
1938
|
+
announceToOnStartup() {
|
|
1939
|
+
try {
|
|
1940
|
+
// get all available tools
|
|
1941
|
+
const tools = this.toolRegistry.getToolDefinitions();
|
|
1942
|
+
const commandTool = getCommandExecutorToolDefinition();
|
|
1943
|
+
// get skills if available
|
|
1944
|
+
let skills = [];
|
|
1945
|
+
try {
|
|
1946
|
+
const scanner = getSkillScanner();
|
|
1947
|
+
skills = scanner.getAllSkills().map(s => s.name);
|
|
1948
|
+
}
|
|
1949
|
+
catch (e) {
|
|
1950
|
+
// skills not available - this is fine, just means skills system not initialized
|
|
1951
|
+
logger.debug({ error: e }, 'skills scanner not available yet, that is ok fr fr');
|
|
1952
|
+
}
|
|
1953
|
+
// get dashboard URL from config - use getDashboardUrl helper for proper host handling
|
|
1954
|
+
const dashboardPort = parseInt(process.env['SPECMEM_DASHBOARD_PORT'] || '8595', 10);
|
|
1955
|
+
const dashboardHost = process.env['SPECMEM_DASHBOARD_HOST'] || '127.0.0.1';
|
|
1956
|
+
const dashboardEnabled = process.env['SPECMEM_DASHBOARD_ENABLED'] !== 'false';
|
|
1957
|
+
const dashboardUrl = dashboardEnabled ? getDashboardUrl(dashboardHost, dashboardPort) : null;
|
|
1958
|
+
// build the announcement message with emojis for CLI display
|
|
1959
|
+
const toolsList = tools.map(t => ` - ${t.name}: ${t.description?.split('.')[0] || 'no description'}`).join('\n');
|
|
1960
|
+
// Use emojis as specified in requirements
|
|
1961
|
+
let announcement = `SpecMem Loaded
|
|
1962
|
+
|
|
1963
|
+
Available Tools:
|
|
1964
|
+
${toolsList}
|
|
1965
|
+
- ${commandTool.name}: ${commandTool.description?.split('.')[0] || 'Execute slash commands'}`;
|
|
1966
|
+
if (skills.length > 0) {
|
|
1967
|
+
announcement += `\n\nSkills: ${skills.join(', ')}`;
|
|
1968
|
+
}
|
|
1969
|
+
if (dashboardUrl) {
|
|
1970
|
+
// Include dashboard URL with emoji as specified
|
|
1971
|
+
announcement += `\n\nDashboard: ${dashboardUrl}`;
|
|
1972
|
+
}
|
|
1973
|
+
announcement += `\n\nType save_memory to store, find_memory to search.`;
|
|
1974
|
+
// FIX #11: Auto-announce with retry mechanism
|
|
1975
|
+
// The MCP connection might not be fully established when we first try to send
|
|
1976
|
+
// So we implement retry logic with exponential backoff
|
|
1977
|
+
const maxRetries = parseInt(process.env['SPECMEM_ANNOUNCE_MAX_RETRIES'] || '3', 10);
|
|
1978
|
+
const initialDelayMs = parseInt(process.env['SPECMEM_ANNOUNCE_RETRY_DELAY'] || '1000', 10);
|
|
1979
|
+
// Fire-and-forget with error logging - don't block startup on announcement
|
|
1980
|
+
this.sendAnnouncementWithRetry(announcement, maxRetries, initialDelayMs)
|
|
1981
|
+
.catch((err) => {
|
|
1982
|
+
logger.debug({ error: err }, 'Announcement retry chain failed - non-fatal');
|
|
1983
|
+
});
|
|
1984
|
+
logger.info('scheduled startup announcement to ');
|
|
1985
|
+
}
|
|
1986
|
+
catch (error) {
|
|
1987
|
+
logger.debug({ error }, 'failed to generate startup announcement - continuing anyway');
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
/**
|
|
1991
|
+
* Send announcement with retry logic
|
|
1992
|
+
*
|
|
1993
|
+
* Implements exponential backoff retry for sending the startup announcement
|
|
1994
|
+
* because the MCP connection might not be fully ready on first attempt
|
|
1995
|
+
*/
|
|
1996
|
+
async sendAnnouncementWithRetry(announcement, maxRetries, delayMs, attempt = 1) {
|
|
1997
|
+
try {
|
|
1998
|
+
// Check if debug mode is enabled
|
|
1999
|
+
const debugAnnounce = process.env['SPECMEM_DEBUG_ANNOUNCE'] === 'true';
|
|
2000
|
+
if (debugAnnounce) {
|
|
2001
|
+
logger.info({ attempt, announcement: announcement.slice(0, 200) }, 'attempting to send announcement');
|
|
2002
|
+
}
|
|
2003
|
+
await this.server.sendLoggingMessage({
|
|
2004
|
+
level: 'notice',
|
|
2005
|
+
logger: 'specmem',
|
|
2006
|
+
data: announcement
|
|
2007
|
+
});
|
|
2008
|
+
logger.info({ attempt }, 'successfully sent startup announcement to ');
|
|
2009
|
+
}
|
|
2010
|
+
catch (err) {
|
|
2011
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
2012
|
+
if (attempt < maxRetries) {
|
|
2013
|
+
// Calculate delay with exponential backoff
|
|
2014
|
+
const nextDelay = delayMs * Math.pow(2, attempt - 1);
|
|
2015
|
+
logger.debug({
|
|
2016
|
+
attempt,
|
|
2017
|
+
maxRetries,
|
|
2018
|
+
nextDelay,
|
|
2019
|
+
error: error.message
|
|
2020
|
+
}, 'announcement send failed, scheduling retry');
|
|
2021
|
+
// Schedule retry
|
|
2022
|
+
setTimeout(() => {
|
|
2023
|
+
this.sendAnnouncementWithRetry(announcement, maxRetries, delayMs, attempt + 1);
|
|
2024
|
+
}, nextDelay);
|
|
2025
|
+
}
|
|
2026
|
+
else {
|
|
2027
|
+
// All retries exhausted - log warning but don't crash
|
|
2028
|
+
logger.warn({
|
|
2029
|
+
attempts: maxRetries,
|
|
2030
|
+
error: error.message
|
|
2031
|
+
}, 'could not send startup announcement after all retries - may not see tools list');
|
|
2032
|
+
// Alternative: try sending as a notification if logging fails
|
|
2033
|
+
try {
|
|
2034
|
+
// Just log to stderr as fallback
|
|
2035
|
+
logger.info('='.repeat(60));
|
|
2036
|
+
logger.info('SPECMEM STARTUP - TOOLS AVAILABLE:');
|
|
2037
|
+
logger.info(announcement);
|
|
2038
|
+
logger.info('='.repeat(60));
|
|
2039
|
+
}
|
|
2040
|
+
catch (fallbackError) {
|
|
2041
|
+
// Truly silent fail - we tried our best
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
export { _SERVER_CACHE };
|
|
2048
|
+
//# sourceMappingURL=specMemServer.js.map
|