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,1953 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team Communication MCP Tools (PostgreSQL-backed)
|
|
3
|
+
*
|
|
4
|
+
* REPLACES HTTP-BASED TEAM_MEMBER COMMUNICATION with MCP tool-based communication.
|
|
5
|
+
* All inter-team-member communication MUST go through these MCP tools.
|
|
6
|
+
*
|
|
7
|
+
* This is the Slack-like communication system for team members (formerly team members).
|
|
8
|
+
* Messages are stored in PostgreSQL with channel/threading support.
|
|
9
|
+
*
|
|
10
|
+
* Tools:
|
|
11
|
+
* - send_team_message: Send messages to team channel (replaces HTTP POST)
|
|
12
|
+
* - read_team_messages: Read messages from team channels (replaces HTTP GET)
|
|
13
|
+
* - claim_task: Claim a task/file to work on
|
|
14
|
+
* - release_task: Release a claimed task
|
|
15
|
+
* - get_team_status: Show what everyone is working on
|
|
16
|
+
* - request_help: Broadcast help request to team
|
|
17
|
+
* - respond_to_help: Respond to help requests
|
|
18
|
+
* - broadcast_to_team: Broadcast status/progress to all
|
|
19
|
+
*
|
|
20
|
+
* Database tables:
|
|
21
|
+
* - team_channels: Slack-like channels (by task_id or project)
|
|
22
|
+
* - team_messages: Messages with threading support
|
|
23
|
+
* - task_claims: Active file/task claims
|
|
24
|
+
* - help_requests: Open help requests
|
|
25
|
+
*
|
|
26
|
+
* @author hardwicksoftwareservices
|
|
27
|
+
*/
|
|
28
|
+
import { logger } from '../../utils/logger.js';
|
|
29
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
30
|
+
import { createHash } from 'crypto';
|
|
31
|
+
import fs from 'fs';
|
|
32
|
+
import { getProjectPathForInsert } from '../../services/ProjectContext.js';
|
|
33
|
+
import { getFileCommsTransport } from '../../comms/fileCommsTransport.js';
|
|
34
|
+
import { smartCompress } from '../../utils/tokenCompressor.js';
|
|
35
|
+
// yooo gotta import schema helpers for proper project isolation no cap
|
|
36
|
+
import { getProjectSchema } from '../../db/projectNamespacing.js';
|
|
37
|
+
import { stripNewlines } from '../../utils/compactXmlResponse.js';
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// PER-PROJECT CHANNEL IDs - Each project gets isolated channels
|
|
40
|
+
// ============================================================================
|
|
41
|
+
/**
|
|
42
|
+
* Generate a deterministic UUID for the default team channel based on project path.
|
|
43
|
+
* This ensures each project gets its own isolated team channel.
|
|
44
|
+
*/
|
|
45
|
+
function getProjectDefaultChannelId() {
|
|
46
|
+
const projectPath = getProjectPathForInsert();
|
|
47
|
+
const hash = createHash('sha256').update(`team-default:${projectPath}`).digest('hex');
|
|
48
|
+
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-a${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Generate a deterministic UUID for the broadcast channel based on project path.
|
|
52
|
+
*/
|
|
53
|
+
function getProjectBroadcastChannelId() {
|
|
54
|
+
const projectPath = getProjectPathForInsert();
|
|
55
|
+
const hash = createHash('sha256').update(`team-broadcast:${projectPath}`).digest('hex');
|
|
56
|
+
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-a${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Generate a deterministic UUID for a swarm channel based on project path and swarm number.
|
|
60
|
+
* Swarm channels (1-5) allow agent pairs to communicate privately while still seeing main channel.
|
|
61
|
+
*/
|
|
62
|
+
function getSwarmChannelId(swarmNum) {
|
|
63
|
+
const projectPath = getProjectPathForInsert();
|
|
64
|
+
const hash = createHash('sha256').update(`team-swarm-${swarmNum}:${projectPath}`).digest('hex');
|
|
65
|
+
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-a${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get channel ID from channel name (main, swarm-1, swarm-2, etc.)
|
|
69
|
+
*/
|
|
70
|
+
function getChannelIdByName(channelName) {
|
|
71
|
+
if (!channelName || channelName === 'main' || channelName === 'default') {
|
|
72
|
+
return getProjectDefaultChannelId();
|
|
73
|
+
}
|
|
74
|
+
if (channelName === 'broadcast') {
|
|
75
|
+
return getProjectBroadcastChannelId();
|
|
76
|
+
}
|
|
77
|
+
// Check for swarm-N pattern
|
|
78
|
+
const swarmMatch = channelName.match(/^swarm-(\d+)$/);
|
|
79
|
+
if (swarmMatch) {
|
|
80
|
+
const swarmNum = parseInt(swarmMatch[1], 10);
|
|
81
|
+
if (swarmNum >= 1 && swarmNum <= 5) {
|
|
82
|
+
return getSwarmChannelId(swarmNum);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Default to main channel
|
|
86
|
+
return getProjectDefaultChannelId();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the per-project channel name.
|
|
90
|
+
*/
|
|
91
|
+
function getProjectChannelName() {
|
|
92
|
+
const projectPath = getProjectPathForInsert();
|
|
93
|
+
const projectName = projectPath.split('/').filter(Boolean).pop() || 'default';
|
|
94
|
+
return `team-${projectName}`;
|
|
95
|
+
}
|
|
96
|
+
// Legacy constants (kept for backwards compatibility, but tools use per-project functions)
|
|
97
|
+
const DEFAULT_CHANNEL_ID = '00000000-0000-0000-0000-000000000001';
|
|
98
|
+
const BROADCAST_CHANNEL_ID = '00000000-0000-0000-0000-000000000002';
|
|
99
|
+
const DEFAULT_CHANNEL = 'team-main';
|
|
100
|
+
// ============================================================================
|
|
101
|
+
// REMINDERS - Compact hints for team members on how to use tools
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Ultra-compact reminders - minimal tokens
|
|
104
|
+
const TEAM_COMMS_REMINDER = ``;
|
|
105
|
+
const READ_MESSAGES_REMINDER = ``;
|
|
106
|
+
const SEND_MESSAGE_REMINDER = ``;
|
|
107
|
+
const CLAIM_TASK_REMINDER = ``;
|
|
108
|
+
const TEAM_STATUS_REMINDER = ``;
|
|
109
|
+
const HELP_REQUEST_REMINDER = ``;
|
|
110
|
+
const CLEAR_MESSAGES_REMINDER = ``;
|
|
111
|
+
// Database pool - will be set by initTeamCommsDB
|
|
112
|
+
let dbPool = null;
|
|
113
|
+
// Session start timestamp - messages before this are filtered out
|
|
114
|
+
// This prevents agents from seeing stale messages from previous sessions
|
|
115
|
+
let sessionStartTime = null;
|
|
116
|
+
/**
|
|
117
|
+
* Get the session start timestamp.
|
|
118
|
+
* Returns the time when initTeamCommsDB was called for this session.
|
|
119
|
+
* If not initialized, returns epoch (includes all messages).
|
|
120
|
+
*/
|
|
121
|
+
export function getSessionStartTime() {
|
|
122
|
+
return sessionStartTime || new Date(0);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Reset session start time (useful for testing or explicit session restart).
|
|
126
|
+
* Call this before deploying new agents to ensure they start fresh.
|
|
127
|
+
*/
|
|
128
|
+
export function resetSessionStartTime() {
|
|
129
|
+
sessionStartTime = new Date();
|
|
130
|
+
logger.info({ sessionStartTime: sessionStartTime.toISOString() }, '[TeamComms] Session start time reset');
|
|
131
|
+
}
|
|
132
|
+
// Fallback in-memory stores (used when DB is not available)
|
|
133
|
+
const teamMessagesMemory = new Map();
|
|
134
|
+
const taskClaimsMemory = new Map();
|
|
135
|
+
const helpRequestsMemory = new Map();
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// Database Initialization
|
|
138
|
+
// ============================================================================
|
|
139
|
+
/**
|
|
140
|
+
* Initialize the team communications database schema
|
|
141
|
+
* Creates tables for channels, messages, claims, and help requests
|
|
142
|
+
*
|
|
143
|
+
* CRITICAL: Sets search_path to project schema FIRST to avoid polluting public schema!
|
|
144
|
+
* This ensures all tables are created in the correct project-isolated schema.
|
|
145
|
+
*/
|
|
146
|
+
export async function initTeamCommsDB(pool) {
|
|
147
|
+
dbPool = pool;
|
|
148
|
+
// Record session start time - all messages before this will be filtered out
|
|
149
|
+
// This ensures agents don't see stale messages from previous sessions
|
|
150
|
+
sessionStartTime = new Date();
|
|
151
|
+
logger.info({ sessionStartTime: sessionStartTime.toISOString() }, '[TeamComms] Session started - old messages will be filtered');
|
|
152
|
+
const client = await pool.connect();
|
|
153
|
+
try {
|
|
154
|
+
// yooo gotta set search_path FIRST or tables end up in public schema bruh
|
|
155
|
+
// this is the key fix for project isolation - each project gets its own schema
|
|
156
|
+
const schemaName = getProjectSchema();
|
|
157
|
+
logger.info({ schemaName }, '[TeamComms] Setting search_path for project schema isolation');
|
|
158
|
+
// Create the project schema if it doesn't exist (schema names are safe - generated by getProjectSchema)
|
|
159
|
+
await client.query(`CREATE SCHEMA IF NOT EXISTS ${schemaName}`);
|
|
160
|
+
// Set search_path so all subsequent CREATE TABLE statements go to the project schema
|
|
161
|
+
await client.query(`SET search_path TO ${schemaName}, public`);
|
|
162
|
+
// Create team_channels table
|
|
163
|
+
await client.query(`
|
|
164
|
+
CREATE TABLE IF NOT EXISTS team_channels (
|
|
165
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
166
|
+
name VARCHAR(255) NOT NULL,
|
|
167
|
+
channel_type VARCHAR(50) NOT NULL DEFAULT 'task',
|
|
168
|
+
task_id VARCHAR(255),
|
|
169
|
+
project_id VARCHAR(255),
|
|
170
|
+
project_path VARCHAR(500) NOT NULL DEFAULT '/',
|
|
171
|
+
members TEXT[] NOT NULL DEFAULT '{}',
|
|
172
|
+
created_by VARCHAR(255) NOT NULL,
|
|
173
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
174
|
+
last_activity TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
175
|
+
metadata JSONB NOT NULL DEFAULT '{}',
|
|
176
|
+
CONSTRAINT valid_channel_type CHECK (channel_type IN ('task', 'project', 'direct', 'broadcast', 'default'))
|
|
177
|
+
)
|
|
178
|
+
`);
|
|
179
|
+
// Add project_path column if it doesn't exist (migration for existing tables)
|
|
180
|
+
await client.query(`
|
|
181
|
+
DO $$
|
|
182
|
+
BEGIN
|
|
183
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
184
|
+
WHERE table_name = 'team_channels' AND column_name = 'project_path') THEN
|
|
185
|
+
ALTER TABLE team_channels ADD COLUMN project_path VARCHAR(500) NOT NULL DEFAULT '/';
|
|
186
|
+
END IF;
|
|
187
|
+
END $$;
|
|
188
|
+
`);
|
|
189
|
+
// MIGRATION: Add missing columns to team_channels for older schemas
|
|
190
|
+
// This fixes the "column X does not exist" errors when indexes try to reference them
|
|
191
|
+
await client.query(`
|
|
192
|
+
DO $$
|
|
193
|
+
BEGIN
|
|
194
|
+
-- Add channel_type if missing
|
|
195
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
196
|
+
WHERE table_name = 'team_channels' AND column_name = 'channel_type') THEN
|
|
197
|
+
ALTER TABLE team_channels ADD COLUMN channel_type VARCHAR(50) DEFAULT 'default';
|
|
198
|
+
END IF;
|
|
199
|
+
-- Add project_id if missing
|
|
200
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
201
|
+
WHERE table_name = 'team_channels' AND column_name = 'project_id') THEN
|
|
202
|
+
ALTER TABLE team_channels ADD COLUMN project_id VARCHAR(255);
|
|
203
|
+
END IF;
|
|
204
|
+
-- Add members if missing
|
|
205
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
206
|
+
WHERE table_name = 'team_channels' AND column_name = 'members') THEN
|
|
207
|
+
ALTER TABLE team_channels ADD COLUMN members TEXT[] DEFAULT '{}';
|
|
208
|
+
END IF;
|
|
209
|
+
-- Add created_by if missing
|
|
210
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
211
|
+
WHERE table_name = 'team_channels' AND column_name = 'created_by') THEN
|
|
212
|
+
ALTER TABLE team_channels ADD COLUMN created_by VARCHAR(255) DEFAULT 'system';
|
|
213
|
+
END IF;
|
|
214
|
+
-- Add last_activity if missing
|
|
215
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
216
|
+
WHERE table_name = 'team_channels' AND column_name = 'last_activity') THEN
|
|
217
|
+
ALTER TABLE team_channels ADD COLUMN last_activity TIMESTAMPTZ DEFAULT NOW();
|
|
218
|
+
END IF;
|
|
219
|
+
-- Add metadata if missing
|
|
220
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
221
|
+
WHERE table_name = 'team_channels' AND column_name = 'metadata') THEN
|
|
222
|
+
ALTER TABLE team_channels ADD COLUMN metadata JSONB DEFAULT '{}';
|
|
223
|
+
END IF;
|
|
224
|
+
END $$;
|
|
225
|
+
`);
|
|
226
|
+
// Create team_messages table
|
|
227
|
+
await client.query(`
|
|
228
|
+
CREATE TABLE IF NOT EXISTS team_messages (
|
|
229
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
230
|
+
channel_id UUID NOT NULL REFERENCES team_channels(id) ON DELETE CASCADE,
|
|
231
|
+
sender_id VARCHAR(255) NOT NULL,
|
|
232
|
+
sender_name VARCHAR(255) NOT NULL DEFAULT 'Unknown',
|
|
233
|
+
content TEXT NOT NULL,
|
|
234
|
+
message_type VARCHAR(50) NOT NULL DEFAULT 'update',
|
|
235
|
+
priority VARCHAR(20) NOT NULL DEFAULT 'normal',
|
|
236
|
+
thread_id UUID,
|
|
237
|
+
mentions TEXT[] NOT NULL DEFAULT '{}',
|
|
238
|
+
metadata JSONB NOT NULL DEFAULT '{}',
|
|
239
|
+
project_path VARCHAR(500) NOT NULL DEFAULT '/',
|
|
240
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
241
|
+
read_by TEXT[] NOT NULL DEFAULT '{}',
|
|
242
|
+
CONSTRAINT valid_message_type CHECK (message_type IN ('status', 'question', 'update', 'broadcast', 'help_request', 'help_response')),
|
|
243
|
+
CONSTRAINT valid_priority CHECK (priority IN ('low', 'normal', 'high', 'urgent'))
|
|
244
|
+
)
|
|
245
|
+
`);
|
|
246
|
+
// Add project_path column to team_messages if it doesn't exist
|
|
247
|
+
await client.query(`
|
|
248
|
+
DO $$
|
|
249
|
+
BEGIN
|
|
250
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
251
|
+
WHERE table_name = 'team_messages' AND column_name = 'project_path') THEN
|
|
252
|
+
ALTER TABLE team_messages ADD COLUMN project_path VARCHAR(500) NOT NULL DEFAULT '/';
|
|
253
|
+
END IF;
|
|
254
|
+
END $$;
|
|
255
|
+
`);
|
|
256
|
+
// Create task_claims table
|
|
257
|
+
await client.query(`
|
|
258
|
+
CREATE TABLE IF NOT EXISTS task_claims (
|
|
259
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
260
|
+
description TEXT NOT NULL,
|
|
261
|
+
files TEXT[] NOT NULL DEFAULT '{}',
|
|
262
|
+
claimed_by VARCHAR(255) NOT NULL,
|
|
263
|
+
claimed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
264
|
+
status VARCHAR(20) NOT NULL DEFAULT 'active',
|
|
265
|
+
metadata JSONB NOT NULL DEFAULT '{}',
|
|
266
|
+
project_path VARCHAR(500) NOT NULL DEFAULT '/',
|
|
267
|
+
CONSTRAINT valid_claim_status CHECK (status IN ('active', 'released'))
|
|
268
|
+
)
|
|
269
|
+
`);
|
|
270
|
+
// Add project_path column to task_claims if it doesn't exist
|
|
271
|
+
await client.query(`
|
|
272
|
+
DO $$
|
|
273
|
+
BEGIN
|
|
274
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
275
|
+
WHERE table_name = 'task_claims' AND column_name = 'project_path') THEN
|
|
276
|
+
ALTER TABLE task_claims ADD COLUMN project_path VARCHAR(500) NOT NULL DEFAULT '/';
|
|
277
|
+
END IF;
|
|
278
|
+
END $$;
|
|
279
|
+
`);
|
|
280
|
+
// Create help_requests table
|
|
281
|
+
await client.query(`
|
|
282
|
+
CREATE TABLE IF NOT EXISTS help_requests (
|
|
283
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
284
|
+
question TEXT NOT NULL,
|
|
285
|
+
context TEXT,
|
|
286
|
+
requested_by VARCHAR(255) NOT NULL,
|
|
287
|
+
requested_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
288
|
+
status VARCHAR(20) NOT NULL DEFAULT 'open',
|
|
289
|
+
channel_id UUID REFERENCES team_channels(id) ON DELETE SET NULL,
|
|
290
|
+
metadata JSONB NOT NULL DEFAULT '{}',
|
|
291
|
+
project_path VARCHAR(500) NOT NULL DEFAULT '/',
|
|
292
|
+
CONSTRAINT valid_help_status CHECK (status IN ('open', 'answered'))
|
|
293
|
+
)
|
|
294
|
+
`);
|
|
295
|
+
// Add project_path column to help_requests if it doesn't exist
|
|
296
|
+
await client.query(`
|
|
297
|
+
DO $$
|
|
298
|
+
BEGIN
|
|
299
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
300
|
+
WHERE table_name = 'help_requests' AND column_name = 'project_path') THEN
|
|
301
|
+
ALTER TABLE help_requests ADD COLUMN project_path VARCHAR(500) NOT NULL DEFAULT '/';
|
|
302
|
+
END IF;
|
|
303
|
+
END $$;
|
|
304
|
+
`);
|
|
305
|
+
// Create indexes for efficient queries
|
|
306
|
+
await client.query(`
|
|
307
|
+
CREATE INDEX IF NOT EXISTS idx_team_messages_channel_id ON team_messages(channel_id);
|
|
308
|
+
CREATE INDEX IF NOT EXISTS idx_team_messages_sender_id ON team_messages(sender_id);
|
|
309
|
+
CREATE INDEX IF NOT EXISTS idx_team_messages_created_at ON team_messages(created_at DESC);
|
|
310
|
+
CREATE INDEX IF NOT EXISTS idx_team_messages_thread_id ON team_messages(thread_id) WHERE thread_id IS NOT NULL;
|
|
311
|
+
CREATE INDEX IF NOT EXISTS idx_team_messages_mentions ON team_messages USING GIN(mentions);
|
|
312
|
+
CREATE INDEX IF NOT EXISTS idx_team_messages_project_path ON team_messages(project_path);
|
|
313
|
+
CREATE INDEX IF NOT EXISTS idx_team_channels_task_id ON team_channels(task_id) WHERE task_id IS NOT NULL;
|
|
314
|
+
CREATE INDEX IF NOT EXISTS idx_team_channels_project_id ON team_channels(project_id) WHERE project_id IS NOT NULL;
|
|
315
|
+
CREATE INDEX IF NOT EXISTS idx_team_channels_project_path ON team_channels(project_path);
|
|
316
|
+
CREATE INDEX IF NOT EXISTS idx_task_claims_status ON task_claims(status) WHERE status = 'active';
|
|
317
|
+
CREATE INDEX IF NOT EXISTS idx_task_claims_files ON task_claims USING GIN(files) WHERE status = 'active';
|
|
318
|
+
CREATE INDEX IF NOT EXISTS idx_task_claims_project_path ON task_claims(project_path);
|
|
319
|
+
CREATE INDEX IF NOT EXISTS idx_help_requests_status ON help_requests(status) WHERE status = 'open';
|
|
320
|
+
CREATE INDEX IF NOT EXISTS idx_help_requests_project_path ON help_requests(project_path);
|
|
321
|
+
`);
|
|
322
|
+
// Create per-project default channel if it doesn't exist
|
|
323
|
+
const projectDefaultChannelId = getProjectDefaultChannelId();
|
|
324
|
+
const projectDefaultChannelName = getProjectChannelName();
|
|
325
|
+
await client.query(`
|
|
326
|
+
INSERT INTO team_channels (id, name, channel_type, created_by, project_path)
|
|
327
|
+
VALUES ($1, $2, 'default', 'system', $3)
|
|
328
|
+
ON CONFLICT (id) DO NOTHING
|
|
329
|
+
`, [projectDefaultChannelId, projectDefaultChannelName, getProjectPathForInsert()]);
|
|
330
|
+
// Create per-project broadcast channel if it doesn't exist
|
|
331
|
+
const projectBroadcastChannelId = getProjectBroadcastChannelId();
|
|
332
|
+
await client.query(`
|
|
333
|
+
INSERT INTO team_channels (id, name, channel_type, created_by, project_path)
|
|
334
|
+
VALUES ($1, $2, 'broadcast', 'system', $3)
|
|
335
|
+
ON CONFLICT (id) DO NOTHING
|
|
336
|
+
`, [projectBroadcastChannelId, `${projectDefaultChannelName}-broadcast`, getProjectPathForInsert()]);
|
|
337
|
+
// FIX: Create swarm channels (swarm-1 through swarm-5) if they don't exist
|
|
338
|
+
// Previously, swarm channels were never created, causing messages to fail
|
|
339
|
+
// when agents tried to send/read from swarm-specific channels
|
|
340
|
+
const projectPath = getProjectPathForInsert();
|
|
341
|
+
for (let swarmNum = 1; swarmNum <= 5; swarmNum++) {
|
|
342
|
+
const swarmChannelId = getSwarmChannelId(swarmNum);
|
|
343
|
+
const swarmChannelName = `${projectDefaultChannelName}-swarm-${swarmNum}`;
|
|
344
|
+
await client.query(`
|
|
345
|
+
INSERT INTO team_channels (id, name, channel_type, created_by, project_path)
|
|
346
|
+
VALUES ($1, $2, 'default', 'system', $3)
|
|
347
|
+
ON CONFLICT (id) DO NOTHING
|
|
348
|
+
`, [swarmChannelId, swarmChannelName, projectPath]);
|
|
349
|
+
}
|
|
350
|
+
logger.info({ schemaName }, 'Team communications database schema initialized in project schema - POSTGRES MODE ACTIVATED no cap');
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
logger.error({ error }, 'Failed to initialize team communications database schema');
|
|
354
|
+
throw error;
|
|
355
|
+
}
|
|
356
|
+
finally {
|
|
357
|
+
client.release();
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Check if database is available
|
|
362
|
+
*/
|
|
363
|
+
function isDBAvailable() {
|
|
364
|
+
return dbPool !== null;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Set search_path for project isolation on a client connection.
|
|
368
|
+
* MUST be called after acquiring a client from pool, before any queries.
|
|
369
|
+
* This ensures tables are accessed from the correct project schema.
|
|
370
|
+
*/
|
|
371
|
+
async function setClientSearchPath(client) {
|
|
372
|
+
const schemaName = getProjectSchema();
|
|
373
|
+
await client.query(`SET search_path TO ${schemaName}, public`);
|
|
374
|
+
return schemaName;
|
|
375
|
+
}
|
|
376
|
+
// ============================================================================
|
|
377
|
+
// Utility Functions
|
|
378
|
+
// ============================================================================
|
|
379
|
+
function generateId() {
|
|
380
|
+
return uuidv4();
|
|
381
|
+
}
|
|
382
|
+
function getMemberId() {
|
|
383
|
+
// Get team member ID from environment or generate one
|
|
384
|
+
return process.env['SPECMEM_MEMBER_ID'] || process.env['SPECMEM_TEAM_MEMBER_ID'] || `member-${process.pid}`;
|
|
385
|
+
}
|
|
386
|
+
function getMemberName() {
|
|
387
|
+
return process.env['SPECMEM_MEMBER_NAME'] || process.env['SPECMEM_TEAM_MEMBER_NAME'] || getMemberId();
|
|
388
|
+
}
|
|
389
|
+
function parseMentions(content) {
|
|
390
|
+
const mentionRegex = /@([a-z0-9][a-z0-9_-]*)/gi;
|
|
391
|
+
const matches = content.match(mentionRegex) || [];
|
|
392
|
+
return [...new Set(matches.map(m => m.substring(1).toLowerCase()))];
|
|
393
|
+
}
|
|
394
|
+
function logToTeamChannel(action, details) {
|
|
395
|
+
logger.info({ channel: getProjectChannelName(), action, ...details }, 'Team channel activity');
|
|
396
|
+
}
|
|
397
|
+
export class SendTeamMessage {
|
|
398
|
+
name = 'send_team_message';
|
|
399
|
+
description = `Send a message to the team channel via MCP (NOT HTTP).
|
|
400
|
+
|
|
401
|
+
This is the PRIMARY tool for team member communication. Use this instead of
|
|
402
|
+
any HTTP/REST endpoints for inter-team communication.
|
|
403
|
+
|
|
404
|
+
Use this to:
|
|
405
|
+
- Share status updates with the team
|
|
406
|
+
- Ask questions to team members
|
|
407
|
+
- Post updates about your work progress
|
|
408
|
+
- Reply to messages in a thread
|
|
409
|
+
|
|
410
|
+
Supports @mentions - use @member-id to notify specific team members.
|
|
411
|
+
|
|
412
|
+
Message types:
|
|
413
|
+
- status: Current work status (what you're doing)
|
|
414
|
+
- question: Asking the team for input
|
|
415
|
+
- update: General updates about progress or findings
|
|
416
|
+
|
|
417
|
+
Examples:
|
|
418
|
+
- "Starting work on authentication module" (status)
|
|
419
|
+
- "@backend-team can you review my API changes?" (question with mention)
|
|
420
|
+
- "Completed the database migration, moving to testing" (update)`;
|
|
421
|
+
inputSchema = {
|
|
422
|
+
type: 'object',
|
|
423
|
+
properties: {
|
|
424
|
+
message: {
|
|
425
|
+
type: 'string',
|
|
426
|
+
description: 'The message content to send (supports @mentions)'
|
|
427
|
+
},
|
|
428
|
+
type: {
|
|
429
|
+
type: 'string',
|
|
430
|
+
enum: ['status', 'question', 'update', 'broadcast', 'help_request', 'help_response'],
|
|
431
|
+
description: 'Type of message (default: update)',
|
|
432
|
+
default: 'update'
|
|
433
|
+
},
|
|
434
|
+
priority: {
|
|
435
|
+
type: 'string',
|
|
436
|
+
enum: ['low', 'normal', 'high', 'urgent'],
|
|
437
|
+
description: 'Message priority (default: normal)',
|
|
438
|
+
default: 'normal'
|
|
439
|
+
},
|
|
440
|
+
channel: {
|
|
441
|
+
type: 'string',
|
|
442
|
+
enum: ['main', 'swarm-1', 'swarm-2', 'swarm-3', 'swarm-4', 'swarm-5'],
|
|
443
|
+
description: 'Team channel: main (all agents), swarm-1 through swarm-5 (private swarm pairs)',
|
|
444
|
+
default: 'main'
|
|
445
|
+
},
|
|
446
|
+
task_id: {
|
|
447
|
+
type: 'string',
|
|
448
|
+
description: 'Optional task ID to send to task-specific channel'
|
|
449
|
+
},
|
|
450
|
+
project_id: {
|
|
451
|
+
type: 'string',
|
|
452
|
+
description: 'Optional project ID to send to project-specific channel'
|
|
453
|
+
},
|
|
454
|
+
thread_id: {
|
|
455
|
+
type: 'string',
|
|
456
|
+
description: 'Optional thread ID for replies'
|
|
457
|
+
},
|
|
458
|
+
sender_name: {
|
|
459
|
+
type: 'string',
|
|
460
|
+
description: 'Optional display name for sender'
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
required: ['message']
|
|
464
|
+
};
|
|
465
|
+
async execute(params) {
|
|
466
|
+
const { message, type = 'update', priority = 'normal', channel = 'main', task_id, project_id, thread_id, sender_name } = params;
|
|
467
|
+
// Validate input
|
|
468
|
+
if (!message || message.trim().length === 0) {
|
|
469
|
+
throw new Error('Message content cannot be empty');
|
|
470
|
+
}
|
|
471
|
+
// ════════════════════════════════════════════════════════════════════════
|
|
472
|
+
// CHANNEL ENFORCEMENT - Agents can only post to their assigned channel
|
|
473
|
+
// ════════════════════════════════════════════════════════════════════════
|
|
474
|
+
// Check for agent channel assignment from file (written by agent-loading-hook)
|
|
475
|
+
// Agents can post to:
|
|
476
|
+
// 1. Their assigned channel (e.g., swarm-1)
|
|
477
|
+
// 2. The main channel (for broadcasts visible to everyone)
|
|
478
|
+
// Agents CANNOT post to other swarm channels (prevents crosstalk).
|
|
479
|
+
const requestedChannel = channel || 'main';
|
|
480
|
+
let assignedChannel = null;
|
|
481
|
+
let agentId = null;
|
|
482
|
+
// Check for agent ID in the current context (set by hook via prompt injection)
|
|
483
|
+
// Also check environment as fallback
|
|
484
|
+
const projectPath = getProjectPathForInsert();
|
|
485
|
+
const projectHash = createHash('sha256').update(projectPath).digest('hex').slice(0, 12);
|
|
486
|
+
const channelEnforcementDir = `/tmp/specmem-${projectHash}/agent-channels`;
|
|
487
|
+
// Try to find this agent's channel assignment
|
|
488
|
+
// The agent ID is extracted from process context or recent files
|
|
489
|
+
try {
|
|
490
|
+
if (fs.existsSync(channelEnforcementDir)) {
|
|
491
|
+
const files = fs.readdirSync(channelEnforcementDir);
|
|
492
|
+
// Find the most recent assignment file (likely this agent)
|
|
493
|
+
// In practice, the agent-loading-hook injects the ID into the prompt
|
|
494
|
+
let latestFile = null;
|
|
495
|
+
let latestTime = 0;
|
|
496
|
+
for (const file of files) {
|
|
497
|
+
if (file.endsWith('.json')) {
|
|
498
|
+
const stat = fs.statSync(`${channelEnforcementDir}/${file}`);
|
|
499
|
+
if (stat.mtimeMs > latestTime) {
|
|
500
|
+
latestTime = stat.mtimeMs;
|
|
501
|
+
latestFile = file;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (latestFile && Date.now() - latestTime < 300000) { // Only use if <5 min old
|
|
506
|
+
const assignment = JSON.parse(fs.readFileSync(`${channelEnforcementDir}/${latestFile}`, 'utf8'));
|
|
507
|
+
assignedChannel = assignment.channel;
|
|
508
|
+
agentId = assignment.agentId;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
catch (e) {
|
|
513
|
+
// Silently continue - enforcement relaxed if can't read
|
|
514
|
+
}
|
|
515
|
+
if (assignedChannel && assignedChannel !== 'main') {
|
|
516
|
+
const normalizedAssigned = assignedChannel.toLowerCase().trim();
|
|
517
|
+
const normalizedRequested = requestedChannel.toLowerCase().trim();
|
|
518
|
+
// Allowed: main, broadcast, or their assigned channel
|
|
519
|
+
const allowedChannels = ['main', 'default', 'broadcast', normalizedAssigned];
|
|
520
|
+
if (!allowedChannels.includes(normalizedRequested)) {
|
|
521
|
+
// Agent is trying to post to a channel they're not assigned to
|
|
522
|
+
logger.warn({
|
|
523
|
+
agentId,
|
|
524
|
+
assigned: normalizedAssigned,
|
|
525
|
+
attempted: normalizedRequested,
|
|
526
|
+
blocked: true
|
|
527
|
+
}, 'Channel enforcement: Agent attempted to post to unauthorized channel');
|
|
528
|
+
throw new Error(`Channel access denied. You're assigned to "${normalizedAssigned}" but tried to post to "${normalizedRequested}". ` +
|
|
529
|
+
`Agents can only post to their assigned channel or "main". ` +
|
|
530
|
+
`If you need to communicate with another swarm, post to "main" and @mention them.`);
|
|
531
|
+
}
|
|
532
|
+
// Log successful channel access for debugging
|
|
533
|
+
logger.debug({
|
|
534
|
+
agentId,
|
|
535
|
+
assigned: normalizedAssigned,
|
|
536
|
+
posting: normalizedRequested,
|
|
537
|
+
allowed: true
|
|
538
|
+
}, 'Channel enforcement: Agent posting to authorized channel');
|
|
539
|
+
}
|
|
540
|
+
// ════════════════════════════════════════════════════════════════════════
|
|
541
|
+
const messageId = generateId();
|
|
542
|
+
const timestamp = new Date().toISOString();
|
|
543
|
+
const sender = getMemberId();
|
|
544
|
+
const senderDisplayName = sender_name || getMemberName();
|
|
545
|
+
const mentions = parseMentions(message);
|
|
546
|
+
// Determine channel ID based on channel param - use per-project channels
|
|
547
|
+
// Route to the correct channel (main, swarm-1, swarm-2, etc.)
|
|
548
|
+
let channelId = getChannelIdByName(requestedChannel);
|
|
549
|
+
let channelName = requestedChannel === 'main' || !requestedChannel
|
|
550
|
+
? getProjectChannelName()
|
|
551
|
+
: `${getProjectChannelName()}-${requestedChannel}`;
|
|
552
|
+
// projectPath already defined above for channel enforcement
|
|
553
|
+
if (isDBAvailable()) {
|
|
554
|
+
// Use PostgreSQL
|
|
555
|
+
const client = await dbPool.connect();
|
|
556
|
+
try {
|
|
557
|
+
// CRITICAL: Set search_path for project isolation
|
|
558
|
+
await setClientSearchPath(client);
|
|
559
|
+
// Get or create appropriate channel
|
|
560
|
+
if (task_id) {
|
|
561
|
+
const channelResult = await client.query(`
|
|
562
|
+
INSERT INTO team_channels (name, channel_type, task_id, created_by, project_path)
|
|
563
|
+
VALUES ($1, 'task', $2, $3, $4)
|
|
564
|
+
ON CONFLICT (task_id) WHERE task_id IS NOT NULL
|
|
565
|
+
DO UPDATE SET last_activity = NOW()
|
|
566
|
+
RETURNING id, name
|
|
567
|
+
`, [`task-${task_id}`, task_id, sender, projectPath]);
|
|
568
|
+
if (channelResult.rows.length > 0) {
|
|
569
|
+
channelId = channelResult.rows[0].id;
|
|
570
|
+
channelName = channelResult.rows[0].name;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
else if (project_id) {
|
|
574
|
+
const channelResult = await client.query(`
|
|
575
|
+
INSERT INTO team_channels (name, channel_type, project_id, created_by, project_path)
|
|
576
|
+
VALUES ($1, 'project', $2, $3, $4)
|
|
577
|
+
ON CONFLICT (project_id) WHERE project_id IS NOT NULL
|
|
578
|
+
DO UPDATE SET last_activity = NOW()
|
|
579
|
+
RETURNING id, name
|
|
580
|
+
`, [`project-${project_id}`, project_id, sender, projectPath]);
|
|
581
|
+
if (channelResult.rows.length > 0) {
|
|
582
|
+
channelId = channelResult.rows[0].id;
|
|
583
|
+
channelName = channelResult.rows[0].name;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
// Insert message
|
|
587
|
+
await client.query(`
|
|
588
|
+
INSERT INTO team_messages (
|
|
589
|
+
id, channel_id, sender_id, sender_name, content,
|
|
590
|
+
message_type, priority, thread_id, mentions, metadata, project_path
|
|
591
|
+
)
|
|
592
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
593
|
+
`, [
|
|
594
|
+
messageId,
|
|
595
|
+
channelId,
|
|
596
|
+
sender,
|
|
597
|
+
senderDisplayName,
|
|
598
|
+
message,
|
|
599
|
+
type,
|
|
600
|
+
priority,
|
|
601
|
+
thread_id || null,
|
|
602
|
+
mentions,
|
|
603
|
+
JSON.stringify({ timestamp }),
|
|
604
|
+
projectPath
|
|
605
|
+
]);
|
|
606
|
+
// Update channel last_activity
|
|
607
|
+
await client.query(`
|
|
608
|
+
UPDATE team_channels SET last_activity = NOW() WHERE id = $1
|
|
609
|
+
`, [channelId]);
|
|
610
|
+
}
|
|
611
|
+
finally {
|
|
612
|
+
client.release();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
// FALLBACK MODE: In-memory storage with file-based cross-process communication
|
|
617
|
+
// LIMITATION: In-memory Map is process-local - messages won't be visible to other processes
|
|
618
|
+
// unless the file fallback succeeds. For full cross-process visibility, ensure PostgreSQL is running.
|
|
619
|
+
// See: https://specmem.dev/docs/team-comms-limitations
|
|
620
|
+
const teamMessage = {
|
|
621
|
+
id: messageId,
|
|
622
|
+
sender,
|
|
623
|
+
sender_name: senderDisplayName,
|
|
624
|
+
content: message,
|
|
625
|
+
type,
|
|
626
|
+
priority,
|
|
627
|
+
timestamp,
|
|
628
|
+
channel_id: channelId,
|
|
629
|
+
thread_id,
|
|
630
|
+
mentions,
|
|
631
|
+
read_by: [],
|
|
632
|
+
metadata: {}
|
|
633
|
+
};
|
|
634
|
+
teamMessagesMemory.set(messageId, teamMessage);
|
|
635
|
+
// File-based fallback for cross-process visibility when DB is unavailable
|
|
636
|
+
// NOTE: This is a best-effort fallback - file I/O may fail or race under high load
|
|
637
|
+
try {
|
|
638
|
+
const fileComms = getFileCommsTransport(sender);
|
|
639
|
+
const fileType = type === 'broadcast' ? 'broadcast' : type === 'status' ? 'status' : 'message';
|
|
640
|
+
const filePriority = priority === 'urgent' ? 'urgent' : priority === 'high' ? 'high' : 'medium';
|
|
641
|
+
fileComms.send('all', `[${senderDisplayName}] ${message}`, {
|
|
642
|
+
type: fileType,
|
|
643
|
+
priority: filePriority
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
catch (fileErr) {
|
|
647
|
+
// File fallback failed - message only in this process memory
|
|
648
|
+
// WARNING: Other team members won't see this message without DB or file transport
|
|
649
|
+
logger.warn({ error: fileErr }, '[TeamComms] File fallback failed - message only visible in current process');
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
logToTeamChannel('send_message', {
|
|
653
|
+
messageId,
|
|
654
|
+
type,
|
|
655
|
+
priority,
|
|
656
|
+
sender,
|
|
657
|
+
mentions,
|
|
658
|
+
messageLength: message.length,
|
|
659
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
660
|
+
});
|
|
661
|
+
// Human-readable response
|
|
662
|
+
return {
|
|
663
|
+
content: [{
|
|
664
|
+
type: 'text',
|
|
665
|
+
text: `[SENT] Message sent (id: ${messageId.slice(0, 8)}, type: ${type})`
|
|
666
|
+
}]
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
export class ReadTeamMessages {
|
|
671
|
+
name = 'read_team_messages';
|
|
672
|
+
description = `Read messages from team communication channels via MCP (NOT HTTP).
|
|
673
|
+
|
|
674
|
+
This is the PRIMARY tool for reading team messages. Use this instead of
|
|
675
|
+
any HTTP/REST endpoints for retrieving inter-team communication.
|
|
676
|
+
|
|
677
|
+
Use this to:
|
|
678
|
+
- Check for updates from other team members
|
|
679
|
+
- See recent questions that need answers
|
|
680
|
+
- Stay informed about team activity
|
|
681
|
+
- Check messages where you are mentioned
|
|
682
|
+
|
|
683
|
+
Returns messages sorted by newest first.`;
|
|
684
|
+
inputSchema = {
|
|
685
|
+
type: 'object',
|
|
686
|
+
properties: {
|
|
687
|
+
limit: {
|
|
688
|
+
type: 'number',
|
|
689
|
+
description: 'Maximum number of messages to return (default: 10, max: 100)',
|
|
690
|
+
default: 10
|
|
691
|
+
},
|
|
692
|
+
since: {
|
|
693
|
+
type: 'string',
|
|
694
|
+
description: 'Only return messages after this timestamp (ISO 8601 format)'
|
|
695
|
+
},
|
|
696
|
+
task_id: {
|
|
697
|
+
type: 'string',
|
|
698
|
+
description: 'Filter to messages from specific task channel'
|
|
699
|
+
},
|
|
700
|
+
project_id: {
|
|
701
|
+
type: 'string',
|
|
702
|
+
description: 'Filter to messages from specific project channel'
|
|
703
|
+
},
|
|
704
|
+
mentions_only: {
|
|
705
|
+
type: 'boolean',
|
|
706
|
+
description: 'Only show messages where you are mentioned',
|
|
707
|
+
default: false
|
|
708
|
+
},
|
|
709
|
+
unread_only: {
|
|
710
|
+
type: 'boolean',
|
|
711
|
+
description: 'Only show unread messages',
|
|
712
|
+
default: false
|
|
713
|
+
},
|
|
714
|
+
include_broadcasts: {
|
|
715
|
+
type: 'boolean',
|
|
716
|
+
description: 'Include broadcast messages (default: true)',
|
|
717
|
+
default: true
|
|
718
|
+
},
|
|
719
|
+
include_swarms: {
|
|
720
|
+
type: 'boolean',
|
|
721
|
+
description: 'Also include messages from all swarm channels (swarm-1 through swarm-5). Use this to see private channel activity.',
|
|
722
|
+
default: false
|
|
723
|
+
},
|
|
724
|
+
channel: {
|
|
725
|
+
type: 'string',
|
|
726
|
+
enum: ['main', 'swarm-1', 'swarm-2', 'swarm-3', 'swarm-4', 'swarm-5', 'all'],
|
|
727
|
+
description: 'Filter to specific channel: main, swarm-1 through swarm-5, or "all" for all channels'
|
|
728
|
+
},
|
|
729
|
+
compress: {
|
|
730
|
+
type: 'boolean',
|
|
731
|
+
description: 'Enable Chinese token compression for compact output (default: true). Uses round-trip verified compression.',
|
|
732
|
+
default: true
|
|
733
|
+
}
|
|
734
|
+
},
|
|
735
|
+
required: []
|
|
736
|
+
};
|
|
737
|
+
async execute(params) {
|
|
738
|
+
const { limit = 10, // Default to 10 for token efficiency
|
|
739
|
+
since, channel, task_id, project_id, mentions_only = false, unread_only = false, include_broadcasts = true, include_swarms = false, compress = true } = params;
|
|
740
|
+
const memberId = getMemberId();
|
|
741
|
+
// Get current project path for filtering
|
|
742
|
+
const projectPath = getProjectPathForInsert();
|
|
743
|
+
let messages = [];
|
|
744
|
+
let channelName = getProjectChannelName();
|
|
745
|
+
if (isDBAvailable()) {
|
|
746
|
+
// Use PostgreSQL
|
|
747
|
+
const client = await dbPool.connect();
|
|
748
|
+
try {
|
|
749
|
+
// CRITICAL: Set search_path for project isolation
|
|
750
|
+
await setClientSearchPath(client);
|
|
751
|
+
// MED-20 FIX: Restructure query to avoid OR conditions that prevent index usage
|
|
752
|
+
// Previously: WHERE (project_path = $2 OR project_path = '/') AND (channel_id = X OR ...)
|
|
753
|
+
// This prevented idx_team_messages_project_path from being used effectively
|
|
754
|
+
//
|
|
755
|
+
// New approach: Use UNION ALL to let each subquery use indexes independently
|
|
756
|
+
// PostgreSQL can use idx_team_messages_project_path for each branch separately
|
|
757
|
+
// Build channel ID array for IN clause (more index-friendly than multiple ORs)
|
|
758
|
+
// FIX: Use the channel parameter to filter by the requested channel
|
|
759
|
+
// Previously this was ignored, causing all messages to be returned regardless of channel param
|
|
760
|
+
const channelIds = [];
|
|
761
|
+
// Handle channel parameter - 'all' means all channels, otherwise filter to specific channel
|
|
762
|
+
if (channel === 'all') {
|
|
763
|
+
// Include main channel
|
|
764
|
+
channelIds.push(getProjectDefaultChannelId());
|
|
765
|
+
// Include all swarm channels (1-5)
|
|
766
|
+
for (let i = 1; i <= 5; i++) {
|
|
767
|
+
channelIds.push(getSwarmChannelId(i));
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
else if (channel && channel !== 'main') {
|
|
771
|
+
// Specific channel requested (e.g., swarm-1, swarm-2)
|
|
772
|
+
channelIds.push(getChannelIdByName(channel));
|
|
773
|
+
// Also include main channel for visibility (agents need to see main + their swarm)
|
|
774
|
+
channelIds.push(getProjectDefaultChannelId());
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
// Default: main channel only
|
|
778
|
+
channelIds.push(getProjectDefaultChannelId());
|
|
779
|
+
}
|
|
780
|
+
// Handle include_swarms flag - adds all swarm channels to the list
|
|
781
|
+
if (include_swarms && channel !== 'all') {
|
|
782
|
+
for (let i = 1; i <= 5; i++) {
|
|
783
|
+
const swarmId = getSwarmChannelId(i);
|
|
784
|
+
if (!channelIds.includes(swarmId)) {
|
|
785
|
+
channelIds.push(swarmId);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
// Always include broadcasts if requested
|
|
790
|
+
if (include_broadcasts) {
|
|
791
|
+
channelIds.push(getProjectBroadcastChannelId());
|
|
792
|
+
}
|
|
793
|
+
// Build dynamic filters
|
|
794
|
+
const extraFilters = [];
|
|
795
|
+
const queryParams = [memberId, projectPath, channelIds];
|
|
796
|
+
let paramIndex = 4;
|
|
797
|
+
// Task/project channel filters require join conditions
|
|
798
|
+
let taskChannelJoin = '';
|
|
799
|
+
let projectChannelJoin = '';
|
|
800
|
+
if (task_id) {
|
|
801
|
+
taskChannelJoin = ` OR c.task_id = $${paramIndex}`;
|
|
802
|
+
queryParams.push(task_id);
|
|
803
|
+
paramIndex++;
|
|
804
|
+
}
|
|
805
|
+
if (project_id) {
|
|
806
|
+
projectChannelJoin = ` OR c.project_id = $${paramIndex}`;
|
|
807
|
+
queryParams.push(project_id);
|
|
808
|
+
paramIndex++;
|
|
809
|
+
}
|
|
810
|
+
// Time filter - user-specified "since" parameter
|
|
811
|
+
if (since) {
|
|
812
|
+
extraFilters.push(`m.created_at > $${paramIndex}`);
|
|
813
|
+
queryParams.push(since);
|
|
814
|
+
paramIndex++;
|
|
815
|
+
}
|
|
816
|
+
// Session start filter - DISABLED for now
|
|
817
|
+
// BUG: Each MCP instance has its own sessionStartTime, causing agents to not see
|
|
818
|
+
// each other's messages. Until we have a shared session timestamp, disable this filter.
|
|
819
|
+
// TODO: Use a file-based or DB-based shared session start time
|
|
820
|
+
// const sessionStart = getSessionStartTime();
|
|
821
|
+
// extraFilters.push(`m.created_at >= $${paramIndex}`);
|
|
822
|
+
// queryParams.push(sessionStart.toISOString());
|
|
823
|
+
// paramIndex++;
|
|
824
|
+
// Mentions filter
|
|
825
|
+
if (mentions_only) {
|
|
826
|
+
extraFilters.push(`$${paramIndex} = ANY(m.mentions)`);
|
|
827
|
+
queryParams.push(memberId.toLowerCase());
|
|
828
|
+
paramIndex++;
|
|
829
|
+
}
|
|
830
|
+
// Unread filter
|
|
831
|
+
if (unread_only) {
|
|
832
|
+
extraFilters.push(`NOT ($1 = ANY(m.read_by))`);
|
|
833
|
+
}
|
|
834
|
+
const extraFilterClause = extraFilters.length > 0
|
|
835
|
+
? ' AND ' + extraFilters.join(' AND ')
|
|
836
|
+
: '';
|
|
837
|
+
const channelFilter = `(c.id = ANY($3)${taskChannelJoin}${projectChannelJoin})`;
|
|
838
|
+
// MED-20 FIX: Use UNION ALL for project_path filtering
|
|
839
|
+
// Each branch can use idx_team_messages_project_path independently
|
|
840
|
+
// Then merge results and apply ORDER BY / LIMIT
|
|
841
|
+
const query = `
|
|
842
|
+
SELECT * FROM (
|
|
843
|
+
-- Branch 1: Messages from current project
|
|
844
|
+
SELECT
|
|
845
|
+
m.id, m.sender_id as sender, m.sender_name, m.content,
|
|
846
|
+
m.message_type as type, m.priority, m.created_at as timestamp,
|
|
847
|
+
m.mentions, m.thread_id,
|
|
848
|
+
NOT ($1 = ANY(m.read_by)) as is_unread,
|
|
849
|
+
c.name as channel_name
|
|
850
|
+
FROM team_messages m
|
|
851
|
+
JOIN team_channels c ON m.channel_id = c.id
|
|
852
|
+
WHERE m.project_path = $2
|
|
853
|
+
AND ${channelFilter}${extraFilterClause}
|
|
854
|
+
|
|
855
|
+
UNION ALL
|
|
856
|
+
|
|
857
|
+
-- Branch 2: Global broadcasts (project_path = '/')
|
|
858
|
+
SELECT
|
|
859
|
+
m.id, m.sender_id as sender, m.sender_name, m.content,
|
|
860
|
+
m.message_type as type, m.priority, m.created_at as timestamp,
|
|
861
|
+
m.mentions, m.thread_id,
|
|
862
|
+
NOT ($1 = ANY(m.read_by)) as is_unread,
|
|
863
|
+
c.name as channel_name
|
|
864
|
+
FROM team_messages m
|
|
865
|
+
JOIN team_channels c ON m.channel_id = c.id
|
|
866
|
+
WHERE m.project_path = '/'
|
|
867
|
+
AND ${channelFilter}${extraFilterClause}
|
|
868
|
+
) combined
|
|
869
|
+
ORDER BY timestamp DESC
|
|
870
|
+
LIMIT $${paramIndex}
|
|
871
|
+
`;
|
|
872
|
+
queryParams.push(limit);
|
|
873
|
+
const result = await client.query(query, queryParams);
|
|
874
|
+
messages = result.rows.map((row) => {
|
|
875
|
+
// Apply Chinese token compression if enabled
|
|
876
|
+
const content = compress && row.content && row.content.length > 30
|
|
877
|
+
? smartCompress(row.content, { threshold: 0.75 }).result
|
|
878
|
+
: row.content;
|
|
879
|
+
return {
|
|
880
|
+
id: row.id,
|
|
881
|
+
sender: row.sender,
|
|
882
|
+
sender_name: row.sender_name,
|
|
883
|
+
content,
|
|
884
|
+
type: row.type,
|
|
885
|
+
priority: row.priority,
|
|
886
|
+
timestamp: row.timestamp.toISOString(),
|
|
887
|
+
mentions: row.mentions || [],
|
|
888
|
+
is_unread: row.is_unread,
|
|
889
|
+
thread_id: row.thread_id || undefined
|
|
890
|
+
};
|
|
891
|
+
});
|
|
892
|
+
if (result.rows.length > 0) {
|
|
893
|
+
channelName = result.rows[0].channel_name;
|
|
894
|
+
}
|
|
895
|
+
// Mark messages as read
|
|
896
|
+
if (messages.length > 0) {
|
|
897
|
+
const messageIds = messages.map(m => m.id);
|
|
898
|
+
await client.query(`
|
|
899
|
+
UPDATE team_messages
|
|
900
|
+
SET read_by = array_append(read_by, $1)
|
|
901
|
+
WHERE id = ANY($2) AND NOT ($1 = ANY(read_by))
|
|
902
|
+
`, [memberId, messageIds]);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
finally {
|
|
906
|
+
client.release();
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
else {
|
|
910
|
+
// Fallback to in-memory
|
|
911
|
+
const sessionStart = getSessionStartTime();
|
|
912
|
+
// FIX: Build channel ID list for in-memory filtering (mirrors DB logic above)
|
|
913
|
+
const memChannelIds = [];
|
|
914
|
+
if (channel === 'all') {
|
|
915
|
+
memChannelIds.push(getProjectDefaultChannelId());
|
|
916
|
+
for (let i = 1; i <= 5; i++) {
|
|
917
|
+
memChannelIds.push(getSwarmChannelId(i));
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
else if (channel && channel !== 'main') {
|
|
921
|
+
memChannelIds.push(getChannelIdByName(channel));
|
|
922
|
+
memChannelIds.push(getProjectDefaultChannelId());
|
|
923
|
+
}
|
|
924
|
+
else {
|
|
925
|
+
memChannelIds.push(getProjectDefaultChannelId());
|
|
926
|
+
}
|
|
927
|
+
if (include_swarms && channel !== 'all') {
|
|
928
|
+
for (let i = 1; i <= 5; i++) {
|
|
929
|
+
const swarmId = getSwarmChannelId(i);
|
|
930
|
+
if (!memChannelIds.includes(swarmId)) {
|
|
931
|
+
memChannelIds.push(swarmId);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
if (include_broadcasts) {
|
|
936
|
+
memChannelIds.push(getProjectBroadcastChannelId());
|
|
937
|
+
}
|
|
938
|
+
let memMessages = Array.from(teamMessagesMemory.values())
|
|
939
|
+
.filter(msg => memChannelIds.includes(msg.channel_id))
|
|
940
|
+
// Session start filter - exclude messages from before current session
|
|
941
|
+
.filter(msg => new Date(msg.timestamp) >= sessionStart);
|
|
942
|
+
if (since) {
|
|
943
|
+
const sinceDate = new Date(since);
|
|
944
|
+
memMessages = memMessages.filter(msg => new Date(msg.timestamp) > sinceDate);
|
|
945
|
+
}
|
|
946
|
+
if (mentions_only) {
|
|
947
|
+
memMessages = memMessages.filter(msg => msg.mentions.includes(memberId.toLowerCase()));
|
|
948
|
+
}
|
|
949
|
+
if (unread_only) {
|
|
950
|
+
memMessages = memMessages.filter(msg => !msg.read_by.includes(memberId));
|
|
951
|
+
}
|
|
952
|
+
memMessages.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
953
|
+
messages = memMessages.slice(0, limit).map(msg => {
|
|
954
|
+
// Apply Chinese token compression if enabled
|
|
955
|
+
const content = compress && msg.content && msg.content.length > 30
|
|
956
|
+
? smartCompress(msg.content, { threshold: 0.75 }).result
|
|
957
|
+
: msg.content;
|
|
958
|
+
return {
|
|
959
|
+
id: msg.id,
|
|
960
|
+
sender: msg.sender,
|
|
961
|
+
sender_name: msg.sender_name,
|
|
962
|
+
content,
|
|
963
|
+
type: msg.type,
|
|
964
|
+
priority: msg.priority,
|
|
965
|
+
timestamp: msg.timestamp,
|
|
966
|
+
mentions: msg.mentions,
|
|
967
|
+
is_unread: !msg.read_by.includes(memberId),
|
|
968
|
+
thread_id: msg.thread_id
|
|
969
|
+
};
|
|
970
|
+
});
|
|
971
|
+
// Mark as read
|
|
972
|
+
for (const msg of messages) {
|
|
973
|
+
const original = teamMessagesMemory.get(msg.id);
|
|
974
|
+
if (original && !original.read_by.includes(memberId)) {
|
|
975
|
+
original.read_by.push(memberId);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
const unreadCount = messages.filter(m => m.is_unread).length;
|
|
980
|
+
logToTeamChannel('read_messages', {
|
|
981
|
+
count: messages.length,
|
|
982
|
+
unreadCount,
|
|
983
|
+
limit,
|
|
984
|
+
since,
|
|
985
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
986
|
+
});
|
|
987
|
+
// Human-readable format like find_memory/Read tool
|
|
988
|
+
const typeEmoji = {
|
|
989
|
+
status: '🔄',
|
|
990
|
+
question: '❓',
|
|
991
|
+
update: '📝',
|
|
992
|
+
broadcast: '📢',
|
|
993
|
+
help_request: '🆘',
|
|
994
|
+
help_response: '💡'
|
|
995
|
+
};
|
|
996
|
+
const formatTimeAgo = (date) => {
|
|
997
|
+
const now = Date.now();
|
|
998
|
+
const then = new Date(date).getTime();
|
|
999
|
+
const diffSec = Math.floor((now - then) / 1000);
|
|
1000
|
+
if (diffSec < 60) return `${diffSec}s ago`;
|
|
1001
|
+
const diffMin = Math.floor(diffSec / 60);
|
|
1002
|
+
if (diffMin < 60) return `${diffMin}m ago`;
|
|
1003
|
+
const diffHr = Math.floor(diffMin / 60);
|
|
1004
|
+
if (diffHr < 24) return `${diffHr}h ago`;
|
|
1005
|
+
return `${Math.floor(diffHr / 24)}d ago`;
|
|
1006
|
+
};
|
|
1007
|
+
const formatMessage = (m, idx) => {
|
|
1008
|
+
const emoji = typeEmoji[m.type] || '💬';
|
|
1009
|
+
const unread = m.is_unread ? ' ★ NEW' : '';
|
|
1010
|
+
const time = formatTimeAgo(m.created_at);
|
|
1011
|
+
const from = m.sender_name || 'unknown';
|
|
1012
|
+
// Compress content with smartCompress for token savings
|
|
1013
|
+
const rawContent = m.content.slice(0, 400);
|
|
1014
|
+
const { result: compressedContent } = smartCompress(rawContent, { threshold: 0.6 });
|
|
1015
|
+
const content = compressedContent.replace(/\n/g, '\n│ ');
|
|
1016
|
+
const truncated = m.content.length > 400 ? '...' : '';
|
|
1017
|
+
return `┌─${unread}────────────────────────────────────
|
|
1018
|
+
│ ${emoji} ${from} • ${m.type} • ${time}
|
|
1019
|
+
│ ${content}${truncated}
|
|
1020
|
+
└──────────────────────────────────────────`;
|
|
1021
|
+
};
|
|
1022
|
+
// Use [SPECMEM-*] tag format for consistency with other tools
|
|
1023
|
+
const header = `[SPECMEM-TEAM-MESSAGES]
|
|
1024
|
+
📬 ${messages.length} messages • ${unreadCount} unread`;
|
|
1025
|
+
const msgList = messages.map((m, i) => formatMessage(m, i)).join('\n');
|
|
1026
|
+
const footer = `\n💬 send_team_message({message}) 回覆
|
|
1027
|
+
[/SPECMEM-TEAM-MESSAGES]`;
|
|
1028
|
+
const output = messages.length > 0
|
|
1029
|
+
? `${header}\n${msgList}${footer}`
|
|
1030
|
+
: `${header}\n 無訊息\n${footer}`;
|
|
1031
|
+
return { content: [{ type: 'text', text: output }] };
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
export class BroadcastToTeam {
|
|
1035
|
+
name = 'broadcast_to_team';
|
|
1036
|
+
description = `Broadcast a status or progress update to ALL team members via MCP.
|
|
1037
|
+
|
|
1038
|
+
Use this to:
|
|
1039
|
+
- Share progress updates: "Completed 75% of database migration"
|
|
1040
|
+
- Announce important status changes: "API endpoints ready for testing"
|
|
1041
|
+
- Notify about blockers or issues: "Waiting on external service"
|
|
1042
|
+
- Celebrate milestones: "Feature X is complete and tested"
|
|
1043
|
+
|
|
1044
|
+
By default, broadcasts only reach team members in the SAME PROJECT.
|
|
1045
|
+
Use cross_project: true for system-wide announcements (use sparingly).`;
|
|
1046
|
+
inputSchema = {
|
|
1047
|
+
type: 'object',
|
|
1048
|
+
properties: {
|
|
1049
|
+
message: {
|
|
1050
|
+
type: 'string',
|
|
1051
|
+
description: 'The broadcast message'
|
|
1052
|
+
},
|
|
1053
|
+
broadcast_type: {
|
|
1054
|
+
type: 'string',
|
|
1055
|
+
enum: ['status', 'progress', 'announcement'],
|
|
1056
|
+
description: 'Type of broadcast (default: status)'
|
|
1057
|
+
},
|
|
1058
|
+
priority: {
|
|
1059
|
+
type: 'string',
|
|
1060
|
+
enum: ['low', 'normal', 'high', 'urgent'],
|
|
1061
|
+
description: 'Broadcast priority (default: normal)'
|
|
1062
|
+
},
|
|
1063
|
+
metadata: {
|
|
1064
|
+
type: 'object',
|
|
1065
|
+
description: 'Optional metadata (e.g., { progress: 75 })'
|
|
1066
|
+
},
|
|
1067
|
+
cross_project: {
|
|
1068
|
+
type: 'boolean',
|
|
1069
|
+
description: 'If true, broadcast to ALL projects (use sparingly for system-wide announcements)',
|
|
1070
|
+
default: false
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
required: ['message']
|
|
1074
|
+
};
|
|
1075
|
+
async execute(params) {
|
|
1076
|
+
const { message, broadcast_type = 'status', priority = 'normal', metadata = {}, cross_project = false } = params;
|
|
1077
|
+
if (!message || message.trim().length === 0) {
|
|
1078
|
+
throw new Error('Broadcast message cannot be empty');
|
|
1079
|
+
}
|
|
1080
|
+
const messageId = generateId();
|
|
1081
|
+
const timestamp = new Date().toISOString();
|
|
1082
|
+
const sender = getMemberId();
|
|
1083
|
+
const senderName = getMemberName();
|
|
1084
|
+
// Get current project path for filtering
|
|
1085
|
+
// Use '/' (root) for cross-project broadcasts to make them visible everywhere
|
|
1086
|
+
const projectPath = cross_project ? '/' : getProjectPathForInsert();
|
|
1087
|
+
if (isDBAvailable()) {
|
|
1088
|
+
const client = await dbPool.connect();
|
|
1089
|
+
try {
|
|
1090
|
+
// CRITICAL: Set search_path for project isolation
|
|
1091
|
+
await setClientSearchPath(client);
|
|
1092
|
+
await client.query(`
|
|
1093
|
+
INSERT INTO team_messages (
|
|
1094
|
+
id, channel_id, sender_id, sender_name, content,
|
|
1095
|
+
message_type, priority, metadata, project_path
|
|
1096
|
+
)
|
|
1097
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
1098
|
+
`, [
|
|
1099
|
+
messageId,
|
|
1100
|
+
getProjectBroadcastChannelId(),
|
|
1101
|
+
sender,
|
|
1102
|
+
senderName,
|
|
1103
|
+
`[${broadcast_type.toUpperCase()}]${cross_project ? ' [GLOBAL]' : ''} ${message}`,
|
|
1104
|
+
'broadcast',
|
|
1105
|
+
priority,
|
|
1106
|
+
JSON.stringify({ ...metadata, broadcast_type, cross_project }),
|
|
1107
|
+
projectPath
|
|
1108
|
+
]);
|
|
1109
|
+
await client.query(`
|
|
1110
|
+
UPDATE team_channels SET last_activity = NOW() WHERE id = $1
|
|
1111
|
+
`, [getProjectBroadcastChannelId()]);
|
|
1112
|
+
}
|
|
1113
|
+
finally {
|
|
1114
|
+
client.release();
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
else {
|
|
1118
|
+
const teamMessage = {
|
|
1119
|
+
id: messageId,
|
|
1120
|
+
sender,
|
|
1121
|
+
sender_name: senderName,
|
|
1122
|
+
content: `[${broadcast_type.toUpperCase()}] ${message}`,
|
|
1123
|
+
type: 'broadcast',
|
|
1124
|
+
priority,
|
|
1125
|
+
timestamp,
|
|
1126
|
+
channel_id: getProjectBroadcastChannelId(),
|
|
1127
|
+
mentions: [],
|
|
1128
|
+
read_by: [],
|
|
1129
|
+
metadata: { ...metadata, broadcast_type }
|
|
1130
|
+
};
|
|
1131
|
+
teamMessagesMemory.set(messageId, teamMessage);
|
|
1132
|
+
}
|
|
1133
|
+
logToTeamChannel('broadcast', {
|
|
1134
|
+
messageId,
|
|
1135
|
+
broadcast_type,
|
|
1136
|
+
priority,
|
|
1137
|
+
sender,
|
|
1138
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
1139
|
+
});
|
|
1140
|
+
// Human-readable response
|
|
1141
|
+
return {
|
|
1142
|
+
content: [{
|
|
1143
|
+
type: 'text',
|
|
1144
|
+
text: `[BROADCAST] ${broadcast_type} sent to team (id: ${messageId.slice(0, 8)})`
|
|
1145
|
+
}]
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
export class ClaimTask {
|
|
1150
|
+
name = 'claim_task';
|
|
1151
|
+
description = `Claim a specific task or file to work on.
|
|
1152
|
+
|
|
1153
|
+
Use this to:
|
|
1154
|
+
- Declare what you're working on to avoid conflicts
|
|
1155
|
+
- Prevent duplicate work on the same files
|
|
1156
|
+
- Coordinate with other team members
|
|
1157
|
+
|
|
1158
|
+
If the files you want to claim are already claimed by another member,
|
|
1159
|
+
you'll receive a warning but the claim will still be created.
|
|
1160
|
+
|
|
1161
|
+
Best practice: Always claim before starting work on a task.`;
|
|
1162
|
+
inputSchema = {
|
|
1163
|
+
type: 'object',
|
|
1164
|
+
properties: {
|
|
1165
|
+
description: {
|
|
1166
|
+
type: 'string',
|
|
1167
|
+
description: 'Description of the task you are claiming'
|
|
1168
|
+
},
|
|
1169
|
+
files: {
|
|
1170
|
+
type: 'array',
|
|
1171
|
+
items: { type: 'string' },
|
|
1172
|
+
description: 'Optional array of file paths you will be working on'
|
|
1173
|
+
}
|
|
1174
|
+
},
|
|
1175
|
+
required: ['description']
|
|
1176
|
+
};
|
|
1177
|
+
async execute(params) {
|
|
1178
|
+
const { description, files = [] } = params;
|
|
1179
|
+
if (!description || description.trim().length === 0) {
|
|
1180
|
+
throw new Error('Task description cannot be empty');
|
|
1181
|
+
}
|
|
1182
|
+
const claimId = generateId();
|
|
1183
|
+
const claimedBy = getMemberId();
|
|
1184
|
+
const claimedAt = new Date().toISOString();
|
|
1185
|
+
const warnings = [];
|
|
1186
|
+
// Get current project path for filtering
|
|
1187
|
+
const projectPath = getProjectPathForInsert();
|
|
1188
|
+
if (isDBAvailable()) {
|
|
1189
|
+
const client = await dbPool.connect();
|
|
1190
|
+
try {
|
|
1191
|
+
// CRITICAL: Set search_path for project isolation
|
|
1192
|
+
await setClientSearchPath(client);
|
|
1193
|
+
// Check for file conflicts (within same project)
|
|
1194
|
+
if (files.length > 0) {
|
|
1195
|
+
const conflictResult = await client.query(`
|
|
1196
|
+
SELECT id, claimed_by, files
|
|
1197
|
+
FROM task_claims
|
|
1198
|
+
WHERE status = 'active' AND claimed_by != $1 AND files && $2 AND project_path = $3
|
|
1199
|
+
`, [claimedBy, files, projectPath]);
|
|
1200
|
+
for (const row of conflictResult.rows) {
|
|
1201
|
+
const conflictingFiles = files.filter(f => row.files.includes(f));
|
|
1202
|
+
for (const file of conflictingFiles) {
|
|
1203
|
+
warnings.push(`File "${file}" is already claimed by ${row.claimed_by} (claim: ${row.id})`);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
// Insert claim
|
|
1208
|
+
await client.query(`
|
|
1209
|
+
INSERT INTO task_claims (id, description, files, claimed_by, claimed_at, status, project_path)
|
|
1210
|
+
VALUES ($1, $2, $3, $4, $5, 'active', $6)
|
|
1211
|
+
`, [claimId, description, files, claimedBy, claimedAt, projectPath]);
|
|
1212
|
+
}
|
|
1213
|
+
finally {
|
|
1214
|
+
client.release();
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
else {
|
|
1218
|
+
// Check for conflicts in memory
|
|
1219
|
+
const activeClaims = Array.from(taskClaimsMemory.values()).filter(c => c.status === 'active');
|
|
1220
|
+
for (const existingClaim of activeClaims) {
|
|
1221
|
+
if (existingClaim.claimedBy === claimedBy)
|
|
1222
|
+
continue;
|
|
1223
|
+
for (const file of files) {
|
|
1224
|
+
if (existingClaim.files.includes(file)) {
|
|
1225
|
+
warnings.push(`File "${file}" is already claimed by ${existingClaim.claimedBy} (claim: ${existingClaim.id})`);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
const claim = {
|
|
1230
|
+
id: claimId,
|
|
1231
|
+
description,
|
|
1232
|
+
files,
|
|
1233
|
+
claimedBy,
|
|
1234
|
+
claimedAt,
|
|
1235
|
+
status: 'active'
|
|
1236
|
+
};
|
|
1237
|
+
taskClaimsMemory.set(claimId, claim);
|
|
1238
|
+
}
|
|
1239
|
+
// Broadcast claim to team
|
|
1240
|
+
const sendMessage = new SendTeamMessage();
|
|
1241
|
+
const fileList = files.length > 0 ? ` (files: ${files.join(', ')})` : '';
|
|
1242
|
+
await sendMessage.execute({
|
|
1243
|
+
message: `[CLAIM] ${description}${fileList}`,
|
|
1244
|
+
type: 'status',
|
|
1245
|
+
priority: 'normal'
|
|
1246
|
+
});
|
|
1247
|
+
logToTeamChannel('claim_task', {
|
|
1248
|
+
claimId,
|
|
1249
|
+
description,
|
|
1250
|
+
files,
|
|
1251
|
+
claimedBy,
|
|
1252
|
+
warnings,
|
|
1253
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
1254
|
+
});
|
|
1255
|
+
// Ultra-compact return
|
|
1256
|
+
return {
|
|
1257
|
+
success: true,
|
|
1258
|
+
claimId: claimId.slice(0, 8),
|
|
1259
|
+
description: stripNewlines(description).slice(0, 50),
|
|
1260
|
+
files,
|
|
1261
|
+
timestamp: claimedAt,
|
|
1262
|
+
warnings
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
export class ReleaseTask {
|
|
1267
|
+
name = 'release_task';
|
|
1268
|
+
description = `Release files or entire task claims.
|
|
1269
|
+
|
|
1270
|
+
Use this to:
|
|
1271
|
+
- Release specific files: release_task({claimId: "abc", files: ["src/foo.ts"]}) - releases just those files, keeps claim active
|
|
1272
|
+
- Release entire claim: release_task({claimId: "abc"}) - releases all files in that claim
|
|
1273
|
+
- Release everything: release_task({claimId: "all"}) - releases ALL your active claims
|
|
1274
|
+
|
|
1275
|
+
Best practice: Release files as you finish them, release entire claim when task is complete.`;
|
|
1276
|
+
inputSchema = {
|
|
1277
|
+
type: 'object',
|
|
1278
|
+
properties: {
|
|
1279
|
+
claimId: {
|
|
1280
|
+
type: 'string',
|
|
1281
|
+
description: 'The claim ID to release, or "all" to release all your claims'
|
|
1282
|
+
},
|
|
1283
|
+
files: {
|
|
1284
|
+
type: 'array',
|
|
1285
|
+
items: { type: 'string' },
|
|
1286
|
+
description: 'Optional: Release only these specific files from the claim (keeps claim active for remaining files)'
|
|
1287
|
+
}
|
|
1288
|
+
},
|
|
1289
|
+
required: ['claimId']
|
|
1290
|
+
};
|
|
1291
|
+
async execute(params) {
|
|
1292
|
+
const { claimId, files } = params;
|
|
1293
|
+
const memberId = getMemberId();
|
|
1294
|
+
const releasedClaims = [];
|
|
1295
|
+
const releasedFiles = [];
|
|
1296
|
+
if (isDBAvailable()) {
|
|
1297
|
+
const client = await dbPool.connect();
|
|
1298
|
+
try {
|
|
1299
|
+
// CRITICAL: Set search_path for project isolation
|
|
1300
|
+
await setClientSearchPath(client);
|
|
1301
|
+
if (claimId === 'all') {
|
|
1302
|
+
// FIX HIGH-13: Add project_path filter to prevent releasing claims from other projects
|
|
1303
|
+
const projectPath = getProjectPathForInsert();
|
|
1304
|
+
const result = await client.query(`
|
|
1305
|
+
UPDATE task_claims
|
|
1306
|
+
SET status = 'released'
|
|
1307
|
+
WHERE claimed_by = $1 AND status = 'active' AND project_path = $2
|
|
1308
|
+
RETURNING id
|
|
1309
|
+
`, [memberId, projectPath]);
|
|
1310
|
+
releasedClaims.push(...result.rows.map((r) => r.id));
|
|
1311
|
+
}
|
|
1312
|
+
else if (files && files.length > 0) {
|
|
1313
|
+
// PARTIAL RELEASE: Remove specific files from claim
|
|
1314
|
+
const claimResult = await client.query(`
|
|
1315
|
+
SELECT claimed_by, files FROM task_claims WHERE id = $1 AND status = 'active'
|
|
1316
|
+
`, [claimId]);
|
|
1317
|
+
if (claimResult.rows.length === 0) {
|
|
1318
|
+
throw new Error(`Active claim not found: ${claimId}`);
|
|
1319
|
+
}
|
|
1320
|
+
if (claimResult.rows[0].claimed_by !== memberId) {
|
|
1321
|
+
throw new Error(`Cannot modify claim owned by another member`);
|
|
1322
|
+
}
|
|
1323
|
+
const currentFiles = claimResult.rows[0].files || [];
|
|
1324
|
+
const remainingFiles = currentFiles.filter(f => !files.includes(f));
|
|
1325
|
+
releasedFiles.push(...files.filter(f => currentFiles.includes(f)));
|
|
1326
|
+
if (remainingFiles.length === 0) {
|
|
1327
|
+
// No files left, release entire claim
|
|
1328
|
+
await client.query(`UPDATE task_claims SET status = 'released' WHERE id = $1`, [claimId]);
|
|
1329
|
+
releasedClaims.push(claimId);
|
|
1330
|
+
}
|
|
1331
|
+
else {
|
|
1332
|
+
// Update claim with remaining files
|
|
1333
|
+
await client.query(`UPDATE task_claims SET files = $1 WHERE id = $2`, [remainingFiles, claimId]);
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
else {
|
|
1337
|
+
// FULL RELEASE: Release entire claim
|
|
1338
|
+
const claimResult = await client.query(`
|
|
1339
|
+
SELECT claimed_by FROM task_claims WHERE id = $1
|
|
1340
|
+
`, [claimId]);
|
|
1341
|
+
if (claimResult.rows.length === 0) {
|
|
1342
|
+
throw new Error(`Claim not found: ${claimId}`);
|
|
1343
|
+
}
|
|
1344
|
+
if (claimResult.rows[0].claimed_by !== memberId) {
|
|
1345
|
+
throw new Error(`Cannot release claim owned by another member: ${claimResult.rows[0].claimed_by}`);
|
|
1346
|
+
}
|
|
1347
|
+
await client.query(`UPDATE task_claims SET status = 'released' WHERE id = $1`, [claimId]);
|
|
1348
|
+
releasedClaims.push(claimId);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
finally {
|
|
1352
|
+
client.release();
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
else {
|
|
1356
|
+
if (claimId === 'all') {
|
|
1357
|
+
for (const [id, claim] of taskClaimsMemory.entries()) {
|
|
1358
|
+
if (claim.claimedBy === memberId && claim.status === 'active') {
|
|
1359
|
+
claim.status = 'released';
|
|
1360
|
+
releasedClaims.push(id);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
else if (files && files.length > 0) {
|
|
1365
|
+
// PARTIAL RELEASE (memory fallback)
|
|
1366
|
+
const claim = taskClaimsMemory.get(claimId);
|
|
1367
|
+
if (!claim || claim.status !== 'active') {
|
|
1368
|
+
throw new Error(`Active claim not found: ${claimId}`);
|
|
1369
|
+
}
|
|
1370
|
+
if (claim.claimedBy !== memberId) {
|
|
1371
|
+
throw new Error(`Cannot modify claim owned by another member`);
|
|
1372
|
+
}
|
|
1373
|
+
releasedFiles.push(...files.filter(f => claim.files.includes(f)));
|
|
1374
|
+
claim.files = claim.files.filter(f => !files.includes(f));
|
|
1375
|
+
if (claim.files.length === 0) {
|
|
1376
|
+
claim.status = 'released';
|
|
1377
|
+
releasedClaims.push(claimId);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
else {
|
|
1381
|
+
const claim = taskClaimsMemory.get(claimId);
|
|
1382
|
+
if (!claim) {
|
|
1383
|
+
throw new Error(`Claim not found: ${claimId}`);
|
|
1384
|
+
}
|
|
1385
|
+
if (claim.claimedBy !== memberId) {
|
|
1386
|
+
throw new Error(`Cannot release claim owned by another member: ${claim.claimedBy}`);
|
|
1387
|
+
}
|
|
1388
|
+
if (claim.status === 'released') {
|
|
1389
|
+
throw new Error(`Claim already released: ${claimId}`);
|
|
1390
|
+
}
|
|
1391
|
+
claim.status = 'released';
|
|
1392
|
+
releasedClaims.push(claimId);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
// Broadcast release
|
|
1396
|
+
const sendMessage = new SendTeamMessage();
|
|
1397
|
+
if (releasedFiles.length > 0 && releasedClaims.length === 0) {
|
|
1398
|
+
// Partial file release
|
|
1399
|
+
await sendMessage.execute({
|
|
1400
|
+
message: `[FILE-RELEASE] Released files: ${releasedFiles.join(', ')} (claim still active)`,
|
|
1401
|
+
type: 'status',
|
|
1402
|
+
priority: 'low'
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
else if (releasedClaims.length > 0) {
|
|
1406
|
+
await sendMessage.execute({
|
|
1407
|
+
message: `[RELEASE] Released ${releasedClaims.length} claim(s): ${releasedClaims.map(c => c.slice(0, 8)).join(', ')}`,
|
|
1408
|
+
type: 'status',
|
|
1409
|
+
priority: 'low'
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
logToTeamChannel('release_task', {
|
|
1413
|
+
claimId,
|
|
1414
|
+
releasedClaims,
|
|
1415
|
+
memberId,
|
|
1416
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
1417
|
+
});
|
|
1418
|
+
// Ultra-compact
|
|
1419
|
+
const message = releasedClaims.length === 1
|
|
1420
|
+
? `Released claim ${releasedClaims[0].slice(0, 8)}`
|
|
1421
|
+
: `Released ${releasedClaims.length} claims`;
|
|
1422
|
+
return {
|
|
1423
|
+
success: true,
|
|
1424
|
+
releasedClaims: releasedClaims.map(id => id.slice(0, 8)),
|
|
1425
|
+
message
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
export class GetTeamStatus {
|
|
1430
|
+
name = 'get_team_status';
|
|
1431
|
+
description = `Show what each team member is working on.
|
|
1432
|
+
|
|
1433
|
+
Returns:
|
|
1434
|
+
- Active task claims from all team members
|
|
1435
|
+
- Recent team activity (messages, claims, help requests)
|
|
1436
|
+
- Number of open help requests
|
|
1437
|
+
|
|
1438
|
+
Use this to:
|
|
1439
|
+
- Understand current team workload
|
|
1440
|
+
- Avoid working on claimed tasks
|
|
1441
|
+
- See if anyone needs help`;
|
|
1442
|
+
inputSchema = {
|
|
1443
|
+
type: 'object',
|
|
1444
|
+
properties: {},
|
|
1445
|
+
required: []
|
|
1446
|
+
};
|
|
1447
|
+
async execute(_params) {
|
|
1448
|
+
// Get current project path for filtering
|
|
1449
|
+
const projectPath = getProjectPathForInsert();
|
|
1450
|
+
let activeClaims = [];
|
|
1451
|
+
let recentActivity = [];
|
|
1452
|
+
let openHelpRequests = 0;
|
|
1453
|
+
if (isDBAvailable()) {
|
|
1454
|
+
const client = await dbPool.connect();
|
|
1455
|
+
try {
|
|
1456
|
+
// CRITICAL: Set search_path for project isolation
|
|
1457
|
+
await setClientSearchPath(client);
|
|
1458
|
+
// Get active claims (filtered by project)
|
|
1459
|
+
const claimsResult = await client.query(`
|
|
1460
|
+
SELECT id, description, files, claimed_by, claimed_at
|
|
1461
|
+
FROM task_claims
|
|
1462
|
+
WHERE status = 'active' AND project_path = $1
|
|
1463
|
+
ORDER BY claimed_at DESC
|
|
1464
|
+
LIMIT 5
|
|
1465
|
+
`, [projectPath]);
|
|
1466
|
+
activeClaims = claimsResult.rows.map((row) => ({
|
|
1467
|
+
claimId: row.id.substring(0, 8), // Short ID
|
|
1468
|
+
description: row.description.substring(0, 50),
|
|
1469
|
+
claimedBy: row.claimed_by
|
|
1470
|
+
}));
|
|
1471
|
+
// Get recent activity - just 3 most recent
|
|
1472
|
+
const activityResult = await client.query(`
|
|
1473
|
+
SELECT sender_id, content, message_type
|
|
1474
|
+
FROM team_messages
|
|
1475
|
+
WHERE project_path = $1
|
|
1476
|
+
ORDER BY created_at DESC
|
|
1477
|
+
LIMIT 3
|
|
1478
|
+
`, [projectPath]);
|
|
1479
|
+
recentActivity = activityResult.rows.map((row) => ({
|
|
1480
|
+
who: row.sender_id.substring(7, 13), // Just ID suffix
|
|
1481
|
+
msg: row.content.substring(0, 40)
|
|
1482
|
+
}));
|
|
1483
|
+
// Count open help requests (filtered by project)
|
|
1484
|
+
const helpResult = await client.query(`
|
|
1485
|
+
SELECT COUNT(*) as count FROM help_requests WHERE status = 'open' AND project_path = $1
|
|
1486
|
+
`, [projectPath]);
|
|
1487
|
+
openHelpRequests = parseInt(helpResult.rows[0].count);
|
|
1488
|
+
}
|
|
1489
|
+
finally {
|
|
1490
|
+
client.release();
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
else {
|
|
1494
|
+
activeClaims = Array.from(taskClaimsMemory.values())
|
|
1495
|
+
.filter(c => c.status === 'active')
|
|
1496
|
+
.slice(0, 5)
|
|
1497
|
+
.map(c => ({
|
|
1498
|
+
claimId: c.id.substring(0, 8),
|
|
1499
|
+
description: c.description.substring(0, 50),
|
|
1500
|
+
claimedBy: c.claimedBy
|
|
1501
|
+
}));
|
|
1502
|
+
recentActivity = Array.from(teamMessagesMemory.values())
|
|
1503
|
+
.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
|
|
1504
|
+
.slice(0, 3)
|
|
1505
|
+
.map(msg => ({
|
|
1506
|
+
who: msg.sender.substring(7, 13),
|
|
1507
|
+
msg: msg.content.substring(0, 40)
|
|
1508
|
+
}));
|
|
1509
|
+
openHelpRequests = Array.from(helpRequestsMemory.values())
|
|
1510
|
+
.filter(h => h.status === 'open').length;
|
|
1511
|
+
}
|
|
1512
|
+
logToTeamChannel('get_status', {
|
|
1513
|
+
activeClaims: activeClaims.length,
|
|
1514
|
+
openHelpRequests,
|
|
1515
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
1516
|
+
});
|
|
1517
|
+
// Human-readable format like find_memory
|
|
1518
|
+
const lines = ['[TEAM-STATUS]'];
|
|
1519
|
+
lines.push(`Claims: ${activeClaims.length} | Help requests: ${openHelpRequests} | Recent: ${recentActivity.length}`);
|
|
1520
|
+
if (activeClaims.length > 0) {
|
|
1521
|
+
lines.push('Active claims:');
|
|
1522
|
+
activeClaims.forEach((c, i) => {
|
|
1523
|
+
lines.push(` [${i + 1}] ${c.claimedBy || 'unknown'}: ${c.description}`);
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1526
|
+
if (recentActivity.length > 0) {
|
|
1527
|
+
lines.push('Recent activity:');
|
|
1528
|
+
recentActivity.forEach((a) => {
|
|
1529
|
+
lines.push(` • ${a.who}: ${a.msg}`);
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
lines.push('[/TEAM-STATUS]');
|
|
1533
|
+
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
export class RequestHelp {
|
|
1537
|
+
name = 'request_help';
|
|
1538
|
+
description = `Broadcast a help request to the team via MCP.
|
|
1539
|
+
|
|
1540
|
+
Use this when you:
|
|
1541
|
+
- Are stuck on a problem
|
|
1542
|
+
- Need input from team members with specific expertise
|
|
1543
|
+
- Want a second opinion on an approach
|
|
1544
|
+
|
|
1545
|
+
The help request will be visible to all team members and they can
|
|
1546
|
+
respond using the respond_to_help tool.`;
|
|
1547
|
+
inputSchema = {
|
|
1548
|
+
type: 'object',
|
|
1549
|
+
properties: {
|
|
1550
|
+
question: {
|
|
1551
|
+
type: 'string',
|
|
1552
|
+
description: 'The question or issue you need help with'
|
|
1553
|
+
},
|
|
1554
|
+
context: {
|
|
1555
|
+
type: 'string',
|
|
1556
|
+
description: 'Optional additional context about the problem'
|
|
1557
|
+
},
|
|
1558
|
+
skills_needed: {
|
|
1559
|
+
type: 'array',
|
|
1560
|
+
items: { type: 'string' },
|
|
1561
|
+
description: 'Optional list of skills needed (e.g., ["database", "typescript"])'
|
|
1562
|
+
}
|
|
1563
|
+
},
|
|
1564
|
+
required: ['question']
|
|
1565
|
+
};
|
|
1566
|
+
async execute(params) {
|
|
1567
|
+
const { question, context, skills_needed = [] } = params;
|
|
1568
|
+
if (!question || question.trim().length === 0) {
|
|
1569
|
+
throw new Error('Question cannot be empty');
|
|
1570
|
+
}
|
|
1571
|
+
const requestId = generateId();
|
|
1572
|
+
const requestedBy = getMemberId();
|
|
1573
|
+
const requestedAt = new Date().toISOString();
|
|
1574
|
+
// Get current project path for filtering
|
|
1575
|
+
const projectPath = getProjectPathForInsert();
|
|
1576
|
+
if (isDBAvailable()) {
|
|
1577
|
+
const client = await dbPool.connect();
|
|
1578
|
+
try {
|
|
1579
|
+
// CRITICAL: Set search_path for project isolation
|
|
1580
|
+
await setClientSearchPath(client);
|
|
1581
|
+
await client.query(`
|
|
1582
|
+
INSERT INTO help_requests (id, question, context, requested_by, requested_at, status, metadata, project_path)
|
|
1583
|
+
VALUES ($1, $2, $3, $4, $5, 'open', $6, $7)
|
|
1584
|
+
`, [requestId, question, context || null, requestedBy, requestedAt, JSON.stringify({ skills_needed }), projectPath]);
|
|
1585
|
+
}
|
|
1586
|
+
finally {
|
|
1587
|
+
client.release();
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
else {
|
|
1591
|
+
const helpRequest = {
|
|
1592
|
+
id: requestId,
|
|
1593
|
+
question,
|
|
1594
|
+
context,
|
|
1595
|
+
requestedBy,
|
|
1596
|
+
requestedAt,
|
|
1597
|
+
status: 'open'
|
|
1598
|
+
};
|
|
1599
|
+
helpRequestsMemory.set(requestId, helpRequest);
|
|
1600
|
+
}
|
|
1601
|
+
// Broadcast help request with high priority
|
|
1602
|
+
const contextStr = context ? `\nContext: ${context}` : '';
|
|
1603
|
+
const skillsStr = skills_needed.length > 0 ? `\nSkills needed: ${skills_needed.join(', ')}` : '';
|
|
1604
|
+
const broadcast = new BroadcastToTeam();
|
|
1605
|
+
await broadcast.execute({
|
|
1606
|
+
message: `HELP NEEDED: ${question}${contextStr}${skillsStr}\n(Request ID: ${requestId})`,
|
|
1607
|
+
broadcast_type: 'announcement',
|
|
1608
|
+
priority: 'high',
|
|
1609
|
+
metadata: { request_id: requestId, skills_needed }
|
|
1610
|
+
});
|
|
1611
|
+
logToTeamChannel('request_help', {
|
|
1612
|
+
requestId,
|
|
1613
|
+
requestedBy,
|
|
1614
|
+
questionLength: question.length,
|
|
1615
|
+
skills_needed,
|
|
1616
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
1617
|
+
});
|
|
1618
|
+
// Ultra-compact
|
|
1619
|
+
return {
|
|
1620
|
+
success: true,
|
|
1621
|
+
requestId: requestId.slice(0, 8),
|
|
1622
|
+
timestamp: requestedAt,
|
|
1623
|
+
message: 'Help request broadcasted to team'
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
export class RespondToHelp {
|
|
1628
|
+
name = 'respond_to_help';
|
|
1629
|
+
description = `Respond to a help request from another team member via MCP.
|
|
1630
|
+
|
|
1631
|
+
Use this to:
|
|
1632
|
+
- Answer questions from team members
|
|
1633
|
+
- Provide suggestions or guidance
|
|
1634
|
+
- Share relevant knowledge
|
|
1635
|
+
|
|
1636
|
+
Your response will be attached to the help request and the requester
|
|
1637
|
+
will be notified.`;
|
|
1638
|
+
inputSchema = {
|
|
1639
|
+
type: 'object',
|
|
1640
|
+
properties: {
|
|
1641
|
+
requestId: {
|
|
1642
|
+
type: 'string',
|
|
1643
|
+
description: 'The ID of the help request you are responding to'
|
|
1644
|
+
},
|
|
1645
|
+
response: {
|
|
1646
|
+
type: 'string',
|
|
1647
|
+
description: 'Your response or answer to the help request'
|
|
1648
|
+
}
|
|
1649
|
+
},
|
|
1650
|
+
required: ['requestId', 'response']
|
|
1651
|
+
};
|
|
1652
|
+
async execute(params) {
|
|
1653
|
+
const { requestId, response } = params;
|
|
1654
|
+
if (!response || response.trim().length === 0) {
|
|
1655
|
+
throw new Error('Response cannot be empty');
|
|
1656
|
+
}
|
|
1657
|
+
const responseId = generateId();
|
|
1658
|
+
const respondedBy = getMemberId();
|
|
1659
|
+
const respondedAt = new Date().toISOString();
|
|
1660
|
+
let requester = 'unknown';
|
|
1661
|
+
let questionSummary = '';
|
|
1662
|
+
if (isDBAvailable()) {
|
|
1663
|
+
const client = await dbPool.connect();
|
|
1664
|
+
try {
|
|
1665
|
+
// CRITICAL: Set search_path for project isolation
|
|
1666
|
+
await setClientSearchPath(client);
|
|
1667
|
+
// Get the help request
|
|
1668
|
+
const helpResult = await client.query(`
|
|
1669
|
+
SELECT requested_by, question FROM help_requests WHERE id = $1
|
|
1670
|
+
`, [requestId]);
|
|
1671
|
+
if (helpResult.rows.length === 0) {
|
|
1672
|
+
throw new Error(`Help request not found: ${requestId}`);
|
|
1673
|
+
}
|
|
1674
|
+
requester = helpResult.rows[0].requested_by;
|
|
1675
|
+
questionSummary = helpResult.rows[0].question.substring(0, 30);
|
|
1676
|
+
// Store response as a message
|
|
1677
|
+
// FIX MED-11: Add project_path to INSERT for proper isolation
|
|
1678
|
+
const projectPath = getProjectPathForInsert();
|
|
1679
|
+
await client.query(`
|
|
1680
|
+
INSERT INTO team_messages (
|
|
1681
|
+
id, channel_id, sender_id, sender_name, content,
|
|
1682
|
+
message_type, priority, metadata, project_path
|
|
1683
|
+
)
|
|
1684
|
+
VALUES ($1, $2, $3, $4, $5, 'help_response', 'high', $6, $7)
|
|
1685
|
+
`, [
|
|
1686
|
+
responseId,
|
|
1687
|
+
getProjectBroadcastChannelId(),
|
|
1688
|
+
respondedBy,
|
|
1689
|
+
getMemberName(),
|
|
1690
|
+
`[HELP RESPONSE] Re: "${questionSummary}..."\n${response}`,
|
|
1691
|
+
JSON.stringify({ request_id: requestId }),
|
|
1692
|
+
projectPath
|
|
1693
|
+
]);
|
|
1694
|
+
// Mark request as answered if this is the first response
|
|
1695
|
+
await client.query(`
|
|
1696
|
+
UPDATE help_requests SET status = 'answered' WHERE id = $1 AND status = 'open'
|
|
1697
|
+
`, [requestId]);
|
|
1698
|
+
}
|
|
1699
|
+
finally {
|
|
1700
|
+
client.release();
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
else {
|
|
1704
|
+
const helpRequest = helpRequestsMemory.get(requestId);
|
|
1705
|
+
if (!helpRequest) {
|
|
1706
|
+
throw new Error(`Help request not found: ${requestId}`);
|
|
1707
|
+
}
|
|
1708
|
+
requester = helpRequest.requestedBy;
|
|
1709
|
+
questionSummary = helpRequest.question.substring(0, 30);
|
|
1710
|
+
helpRequest.status = 'answered';
|
|
1711
|
+
// Store as message
|
|
1712
|
+
const teamMessage = {
|
|
1713
|
+
id: responseId,
|
|
1714
|
+
sender: respondedBy,
|
|
1715
|
+
sender_name: getMemberName(),
|
|
1716
|
+
content: `[HELP RESPONSE] Re: "${questionSummary}..."\n${response}`,
|
|
1717
|
+
type: 'help_response',
|
|
1718
|
+
priority: 'high',
|
|
1719
|
+
timestamp: respondedAt,
|
|
1720
|
+
channel_id: getProjectBroadcastChannelId(),
|
|
1721
|
+
mentions: [requester],
|
|
1722
|
+
read_by: [],
|
|
1723
|
+
metadata: { request_id: requestId }
|
|
1724
|
+
};
|
|
1725
|
+
teamMessagesMemory.set(responseId, teamMessage);
|
|
1726
|
+
}
|
|
1727
|
+
// Also send direct notification
|
|
1728
|
+
const sendMessage = new SendTeamMessage();
|
|
1729
|
+
await sendMessage.execute({
|
|
1730
|
+
message: `@${requester} Response to your help request: ${response.substring(0, 100)}${response.length > 100 ? '...' : ''}`,
|
|
1731
|
+
type: 'help_response',
|
|
1732
|
+
priority: 'high'
|
|
1733
|
+
});
|
|
1734
|
+
logToTeamChannel('respond_to_help', {
|
|
1735
|
+
requestId,
|
|
1736
|
+
responseId,
|
|
1737
|
+
respondedBy,
|
|
1738
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
1739
|
+
});
|
|
1740
|
+
// Ultra-compact
|
|
1741
|
+
return {
|
|
1742
|
+
success: true,
|
|
1743
|
+
responseId: responseId.slice(0, 8),
|
|
1744
|
+
requestId: requestId.slice(0, 8),
|
|
1745
|
+
timestamp: respondedAt,
|
|
1746
|
+
message: `Response sent to ${requester}`
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
export class ClearTeamMessages {
|
|
1751
|
+
name = 'clear_team_messages';
|
|
1752
|
+
description = `Clear old team messages before deploying new team members.
|
|
1753
|
+
|
|
1754
|
+
Use this to:
|
|
1755
|
+
- Wipe the slate clean before new deployments
|
|
1756
|
+
- Prevent new team members from seeing old noise/context
|
|
1757
|
+
- Clean up after a deployment session ends
|
|
1758
|
+
|
|
1759
|
+
IMPORTANT: Call this BEFORE spawning new team members to ensure they
|
|
1760
|
+
start fresh without being spammed by old messages.
|
|
1761
|
+
|
|
1762
|
+
NOTE: This also resets the session start timestamp, so even if DB delete fails,
|
|
1763
|
+
read_team_messages will not return any pre-existing messages. New session = clean slate.
|
|
1764
|
+
|
|
1765
|
+
Options:
|
|
1766
|
+
- confirm: Must be true to actually delete (safety check)
|
|
1767
|
+
- older_than_minutes: Only delete messages older than N minutes (default: all)
|
|
1768
|
+
- clear_claims: Also clear task claims (default: true)
|
|
1769
|
+
- clear_help_requests: Also clear help requests (default: true)
|
|
1770
|
+
|
|
1771
|
+
Example: clear_team_messages({confirm: true}) - wipes everything
|
|
1772
|
+
Example: clear_team_messages({confirm: true, older_than_minutes: 60}) - only old messages`;
|
|
1773
|
+
inputSchema = {
|
|
1774
|
+
type: 'object',
|
|
1775
|
+
properties: {
|
|
1776
|
+
confirm: {
|
|
1777
|
+
type: 'boolean',
|
|
1778
|
+
description: 'Must be true to actually delete (safety check)'
|
|
1779
|
+
},
|
|
1780
|
+
older_than_minutes: {
|
|
1781
|
+
type: 'number',
|
|
1782
|
+
description: 'Only delete messages older than N minutes (optional - default: all)'
|
|
1783
|
+
},
|
|
1784
|
+
clear_claims: {
|
|
1785
|
+
type: 'boolean',
|
|
1786
|
+
description: 'Also clear task claims (default: true)',
|
|
1787
|
+
default: true
|
|
1788
|
+
},
|
|
1789
|
+
clear_help_requests: {
|
|
1790
|
+
type: 'boolean',
|
|
1791
|
+
description: 'Also clear help requests (default: true)',
|
|
1792
|
+
default: true
|
|
1793
|
+
}
|
|
1794
|
+
},
|
|
1795
|
+
required: ['confirm']
|
|
1796
|
+
};
|
|
1797
|
+
async execute(params) {
|
|
1798
|
+
const { confirm, older_than_minutes, clear_claims = true, clear_help_requests = true } = params;
|
|
1799
|
+
if (!confirm) {
|
|
1800
|
+
return {
|
|
1801
|
+
success: false,
|
|
1802
|
+
messagesDeleted: 0,
|
|
1803
|
+
claimsCleared: 0,
|
|
1804
|
+
helpRequestsCleared: 0,
|
|
1805
|
+
message: 'Aborted: confirm must be true to delete messages'
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
// Reset session start time - this ensures read_team_messages won't return
|
|
1809
|
+
// any messages that existed before this clear operation, even if DB delete fails
|
|
1810
|
+
// Critical for clean agent coordination - clearing = fresh start
|
|
1811
|
+
resetSessionStartTime();
|
|
1812
|
+
// Get current project path for filtering
|
|
1813
|
+
const projectPath = getProjectPathForInsert();
|
|
1814
|
+
let messagesDeleted = 0;
|
|
1815
|
+
let claimsCleared = 0;
|
|
1816
|
+
let helpRequestsCleared = 0;
|
|
1817
|
+
if (isDBAvailable()) {
|
|
1818
|
+
const client = await dbPool.connect();
|
|
1819
|
+
try {
|
|
1820
|
+
// CRITICAL: Set search_path for project isolation
|
|
1821
|
+
await setClientSearchPath(client);
|
|
1822
|
+
// Build time filter if specified
|
|
1823
|
+
let timeFilter = '';
|
|
1824
|
+
const timeParams = [projectPath];
|
|
1825
|
+
if (older_than_minutes !== undefined) {
|
|
1826
|
+
timeFilter = ` AND created_at < NOW() - INTERVAL '${older_than_minutes} minutes'`;
|
|
1827
|
+
}
|
|
1828
|
+
// Delete messages
|
|
1829
|
+
const msgResult = await client.query(`
|
|
1830
|
+
DELETE FROM team_messages
|
|
1831
|
+
WHERE project_path = $1${timeFilter}
|
|
1832
|
+
RETURNING id
|
|
1833
|
+
`, timeParams);
|
|
1834
|
+
messagesDeleted = msgResult.rowCount || 0;
|
|
1835
|
+
// Clear claims if requested
|
|
1836
|
+
if (clear_claims) {
|
|
1837
|
+
const claimTimeFilter = older_than_minutes !== undefined
|
|
1838
|
+
? ` AND claimed_at < NOW() - INTERVAL '${older_than_minutes} minutes'`
|
|
1839
|
+
: '';
|
|
1840
|
+
const claimResult = await client.query(`
|
|
1841
|
+
DELETE FROM task_claims
|
|
1842
|
+
WHERE project_path = $1${claimTimeFilter}
|
|
1843
|
+
RETURNING id
|
|
1844
|
+
`, [projectPath]);
|
|
1845
|
+
claimsCleared = claimResult.rowCount || 0;
|
|
1846
|
+
}
|
|
1847
|
+
// Clear help requests if requested
|
|
1848
|
+
if (clear_help_requests) {
|
|
1849
|
+
const helpTimeFilter = older_than_minutes !== undefined
|
|
1850
|
+
? ` AND requested_at < NOW() - INTERVAL '${older_than_minutes} minutes'`
|
|
1851
|
+
: '';
|
|
1852
|
+
const helpResult = await client.query(`
|
|
1853
|
+
DELETE FROM help_requests
|
|
1854
|
+
WHERE project_path = $1${helpTimeFilter}
|
|
1855
|
+
RETURNING id
|
|
1856
|
+
`, [projectPath]);
|
|
1857
|
+
helpRequestsCleared = helpResult.rowCount || 0;
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
finally {
|
|
1861
|
+
client.release();
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
else {
|
|
1865
|
+
// In-memory cleanup
|
|
1866
|
+
const cutoffTime = older_than_minutes
|
|
1867
|
+
? new Date(Date.now() - older_than_minutes * 60 * 1000)
|
|
1868
|
+
: null;
|
|
1869
|
+
// Clear messages
|
|
1870
|
+
for (const [id, msg] of teamMessagesMemory.entries()) {
|
|
1871
|
+
if (!cutoffTime || new Date(msg.timestamp) < cutoffTime) {
|
|
1872
|
+
teamMessagesMemory.delete(id);
|
|
1873
|
+
messagesDeleted++;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
// Clear claims
|
|
1877
|
+
if (clear_claims) {
|
|
1878
|
+
for (const [id, claim] of taskClaimsMemory.entries()) {
|
|
1879
|
+
if (!cutoffTime || new Date(claim.claimedAt) < cutoffTime) {
|
|
1880
|
+
taskClaimsMemory.delete(id);
|
|
1881
|
+
claimsCleared++;
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
// Clear help requests
|
|
1886
|
+
if (clear_help_requests) {
|
|
1887
|
+
for (const [id, req] of helpRequestsMemory.entries()) {
|
|
1888
|
+
if (!cutoffTime || new Date(req.requestedAt) < cutoffTime) {
|
|
1889
|
+
helpRequestsMemory.delete(id);
|
|
1890
|
+
helpRequestsCleared++;
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
const timeInfo = older_than_minutes
|
|
1896
|
+
? ` (older than ${older_than_minutes} minutes)`
|
|
1897
|
+
: '';
|
|
1898
|
+
logToTeamChannel('clear_messages', {
|
|
1899
|
+
messagesDeleted,
|
|
1900
|
+
claimsCleared,
|
|
1901
|
+
helpRequestsCleared,
|
|
1902
|
+
older_than_minutes,
|
|
1903
|
+
storage: isDBAvailable() ? 'postgresql' : 'memory'
|
|
1904
|
+
});
|
|
1905
|
+
// Ultra-compact: just counts
|
|
1906
|
+
const message = `Cleared ${messagesDeleted} messages, ${claimsCleared} claims, ${helpRequestsCleared} help requests${timeInfo}`;
|
|
1907
|
+
return {
|
|
1908
|
+
success: true,
|
|
1909
|
+
messagesDeleted,
|
|
1910
|
+
claimsCleared,
|
|
1911
|
+
helpRequestsCleared,
|
|
1912
|
+
message
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
// ============================================================================
|
|
1917
|
+
// Export all tools
|
|
1918
|
+
// ============================================================================
|
|
1919
|
+
export const teamCommTools = [
|
|
1920
|
+
SendTeamMessage,
|
|
1921
|
+
ReadTeamMessages,
|
|
1922
|
+
BroadcastToTeam,
|
|
1923
|
+
ClaimTask,
|
|
1924
|
+
ReleaseTask,
|
|
1925
|
+
GetTeamStatus,
|
|
1926
|
+
RequestHelp,
|
|
1927
|
+
RespondToHelp,
|
|
1928
|
+
ClearTeamMessages
|
|
1929
|
+
];
|
|
1930
|
+
/**
|
|
1931
|
+
* Create instances of all team communication tools
|
|
1932
|
+
*/
|
|
1933
|
+
export function createTeamCommTools() {
|
|
1934
|
+
return [
|
|
1935
|
+
new SendTeamMessage(),
|
|
1936
|
+
new ReadTeamMessages(),
|
|
1937
|
+
new BroadcastToTeam(),
|
|
1938
|
+
new ClaimTask(),
|
|
1939
|
+
new ReleaseTask(),
|
|
1940
|
+
new GetTeamStatus(),
|
|
1941
|
+
new RequestHelp(),
|
|
1942
|
+
new RespondToHelp(),
|
|
1943
|
+
new ClearTeamMessages()
|
|
1944
|
+
];
|
|
1945
|
+
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Initialize team comms with database pool and return tools
|
|
1948
|
+
*/
|
|
1949
|
+
export async function createTeamCommToolsWithDB(pool) {
|
|
1950
|
+
await initTeamCommsDB(pool);
|
|
1951
|
+
return createTeamCommTools();
|
|
1952
|
+
}
|
|
1953
|
+
//# sourceMappingURL=teamComms.js.map
|