@within-7/minto 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Tool.js +7 -0
- package/dist/Tool.js.map +2 -2
- package/dist/commands/agents/AgentsCommand.js +1 -1
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/agents/constants.js +2 -2
- package/dist/commands/agents/constants.js.map +2 -2
- package/dist/commands/clear.js +4 -3
- package/dist/commands/clear.js.map +2 -2
- package/dist/commands/compact.js +2 -2
- package/dist/commands/compact.js.map +1 -1
- package/dist/commands/context.js +3 -1
- package/dist/commands/context.js.map +2 -2
- package/dist/commands/login.js +128 -0
- package/dist/commands/login.js.map +7 -0
- package/dist/commands/memory.js +33 -82
- package/dist/commands/memory.js.map +2 -2
- package/dist/commands/quit.js +3 -1
- package/dist/commands/quit.js.map +2 -2
- package/dist/commands/resume.js +39 -239
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/tasks.js +1 -1
- package/dist/commands/tasks.js.map +2 -2
- package/dist/commands/terminalSetup.js +6 -2
- package/dist/commands/terminalSetup.js.map +2 -2
- package/dist/commands.js +2 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/AgentDetailView.js +126 -0
- package/dist/components/AgentDetailView.js.map +7 -0
- package/dist/components/AgentThinkingBlock.js +1 -1
- package/dist/components/AgentThinkingBlock.js.map +2 -2
- package/dist/components/AgentViewBanner.js +22 -0
- package/dist/components/AgentViewBanner.js.map +7 -0
- package/dist/components/HeaderBar.js +1 -1
- package/dist/components/HeaderBar.js.map +2 -2
- package/dist/components/Help.js +8 -1
- package/dist/components/Help.js.map +2 -2
- package/dist/components/HotkeyHelpPanel.js +26 -8
- package/dist/components/HotkeyHelpPanel.js.map +2 -2
- package/dist/components/IdleNotificationBar.js +10 -0
- package/dist/components/IdleNotificationBar.js.map +7 -0
- package/dist/components/ModelSelector/ModelSelector.js +55 -20
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/PromptInput.js +186 -115
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/RewindPanel.js +272 -0
- package/dist/components/RewindPanel.js.map +7 -0
- package/dist/components/Spinner.js +10 -21
- package/dist/components/Spinner.js.map +2 -2
- package/dist/components/StreamingTextPreview.js +29 -0
- package/dist/components/StreamingTextPreview.js.map +7 -0
- package/dist/components/SubagentBlock.js +3 -2
- package/dist/components/SubagentBlock.js.map +2 -2
- package/dist/components/SubagentProgress.js +4 -4
- package/dist/components/SubagentProgress.js.map +2 -2
- package/dist/components/TabbedListView/SearchInput.js +1 -1
- package/dist/components/TabbedListView/SearchInput.js.map +2 -2
- package/dist/components/TabbedListView/TabbedListView.js +87 -41
- package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
- package/dist/components/TaskCard.js +4 -4
- package/dist/components/TaskCard.js.map +2 -2
- package/dist/components/TeamMemberPanel.js +107 -0
- package/dist/components/TeamMemberPanel.js.map +7 -0
- package/dist/components/ThinkingSelector.js +84 -0
- package/dist/components/ThinkingSelector.js.map +7 -0
- package/dist/components/TitledDivider.js +26 -0
- package/dist/components/TitledDivider.js.map +7 -0
- package/dist/components/TodoPanel.js +31 -30
- package/dist/components/TodoPanel.js.map +2 -2
- package/dist/components/TokenWarning.js +28 -7
- package/dist/components/TokenWarning.js.map +2 -2
- package/dist/components/messages/AssistantTextMessage.js +5 -2
- package/dist/components/messages/AssistantTextMessage.js.map +2 -2
- package/dist/components/messages/AssistantToolUseMessage.js +9 -1
- package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
- package/dist/components/messages/DefaultToolResultFallback.js +11 -0
- package/dist/components/messages/DefaultToolResultFallback.js.map +7 -0
- package/dist/components/messages/ParallelTasksGroupView.js +14 -6
- package/dist/components/messages/ParallelTasksGroupView.js.map +2 -2
- package/dist/components/messages/TaskInModuleView.js +27 -27
- package/dist/components/messages/TaskInModuleView.js.map +2 -2
- package/dist/components/messages/UserGuidanceMessage.js +26 -0
- package/dist/components/messages/UserGuidanceMessage.js.map +7 -0
- package/dist/components/messages/UserPromptMessage.js +2 -1
- package/dist/components/messages/UserPromptMessage.js.map +2 -2
- package/dist/components/messages/UserTeamNotificationMessage.js +91 -0
- package/dist/components/messages/UserTeamNotificationMessage.js.map +7 -0
- package/dist/components/messages/UserTextMessage.js +8 -0
- package/dist/components/messages/UserTextMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +4 -2
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +18 -1
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +12 -1
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
- package/dist/components/permissions/PermissionRequest.js +4 -0
- package/dist/components/permissions/PermissionRequest.js.map +2 -2
- package/dist/components/permissions/PlanApprovalRequest.js +164 -0
- package/dist/components/permissions/PlanApprovalRequest.js.map +7 -0
- package/dist/constants/agentTeams.js +17 -0
- package/dist/constants/agentTeams.js.map +7 -0
- package/dist/constants/macros.js +2 -1
- package/dist/constants/macros.js.map +2 -2
- package/dist/constants/prompts/agentPrompt.js +1 -0
- package/dist/constants/prompts/agentPrompt.js.map +2 -2
- package/dist/constants/prompts/autoMemory.js +39 -0
- package/dist/constants/prompts/autoMemory.js.map +7 -0
- package/dist/constants/prompts/codeConventions.js +1 -13
- package/dist/constants/prompts/codeConventions.js.map +2 -2
- package/dist/constants/prompts/doingTasks.js +21 -2
- package/dist/constants/prompts/doingTasks.js.map +2 -2
- package/dist/constants/prompts/envInfo.js +6 -7
- package/dist/constants/prompts/envInfo.js.map +2 -2
- package/dist/constants/prompts/index.js +27 -5
- package/dist/constants/prompts/index.js.map +2 -2
- package/dist/constants/prompts/taskManagement.js +2 -43
- package/dist/constants/prompts/taskManagement.js.map +2 -2
- package/dist/constants/prompts/teamOverlays.js +50 -0
- package/dist/constants/prompts/teamOverlays.js.map +7 -0
- package/dist/constants/prompts/toneAndStyle.js +4 -29
- package/dist/constants/prompts/toneAndStyle.js.map +2 -2
- package/dist/constants/prompts/toolUsagePolicy.js +7 -22
- package/dist/constants/prompts/toolUsagePolicy.js.map +2 -2
- package/dist/constants/toolInputExamples.js +2 -2
- package/dist/constants/toolInputExamples.js.map +2 -2
- package/dist/context.js +39 -6
- package/dist/context.js.map +2 -2
- package/dist/core/backupManager.js +1 -1
- package/dist/core/backupManager.js.map +2 -2
- package/dist/core/permissions/rules/planModeRule.js +1 -1
- package/dist/core/permissions/rules/planModeRule.js.map +1 -1
- package/dist/core/permissions/rules/safeModeRule.js +1 -1
- package/dist/core/permissions/rules/safeModeRule.js.map +1 -1
- package/dist/engine/AgentEngine.js +902 -0
- package/dist/engine/AgentEngine.js.map +7 -0
- package/dist/engine/EngineRegistry.js +89 -0
- package/dist/engine/EngineRegistry.js.map +7 -0
- package/dist/engine/foregroundAdapter.js +191 -0
- package/dist/engine/foregroundAdapter.js.map +7 -0
- package/dist/engine/index.js +15 -0
- package/dist/engine/index.js.map +7 -0
- package/dist/engine/types.js +1 -0
- package/dist/engine/types.js.map +7 -0
- package/dist/entrypoints/cli.js +410 -79
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/hooks/useAgentEngine.js +129 -0
- package/dist/hooks/useAgentEngine.js.map +7 -0
- package/dist/hooks/useAgentTokenStats.js +0 -16
- package/dist/hooks/useAgentTokenStats.js.map +2 -2
- package/dist/hooks/useCanUseTool.js +47 -2
- package/dist/hooks/useCanUseTool.js.map +2 -2
- package/dist/hooks/useDeferredLoading.js +4 -1
- package/dist/hooks/useDeferredLoading.js.map +2 -2
- package/dist/hooks/useIdleNotifications.js +66 -0
- package/dist/hooks/useIdleNotifications.js.map +7 -0
- package/dist/hooks/useSessionTracking.js +9 -7
- package/dist/hooks/useSessionTracking.js.map +2 -2
- package/dist/hooks/useTeamMembers.js +51 -0
- package/dist/hooks/useTeamMembers.js.map +7 -0
- package/dist/i18n/locales/en.js +77 -12
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +77 -12
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js +113 -7
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +135 -37
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +504 -361
- package/dist/screens/REPL.js.map +3 -3
- package/dist/screens/ResumeConversation.js +199 -14
- package/dist/screens/ResumeConversation.js.map +2 -2
- package/dist/services/adapters/base.js.map +1 -1
- package/dist/services/agentTeams/backends/headless.js +108 -0
- package/dist/services/agentTeams/backends/headless.js.map +7 -0
- package/dist/services/agentTeams/backends/inProcess.js +102 -0
- package/dist/services/agentTeams/backends/inProcess.js.map +7 -0
- package/dist/services/agentTeams/backends/resolver.js +18 -0
- package/dist/services/agentTeams/backends/resolver.js.map +7 -0
- package/dist/services/agentTeams/backends/tmux.js +168 -0
- package/dist/services/agentTeams/backends/tmux.js.map +7 -0
- package/dist/services/agentTeams/backends/types.js +1 -0
- package/dist/services/agentTeams/backends/types.js.map +7 -0
- package/dist/services/agentTeams/heartbeat.js +88 -0
- package/dist/services/agentTeams/heartbeat.js.map +7 -0
- package/dist/services/agentTeams/index.js +42 -2
- package/dist/services/agentTeams/index.js.map +2 -2
- package/dist/services/agentTeams/injectionChannel.js +105 -0
- package/dist/services/agentTeams/injectionChannel.js.map +7 -0
- package/dist/services/agentTeams/mailbox.js +410 -30
- package/dist/services/agentTeams/mailbox.js.map +2 -2
- package/dist/services/agentTeams/messageFormatter.js +80 -0
- package/dist/services/agentTeams/messageFormatter.js.map +7 -0
- package/dist/services/agentTeams/permissionDelegation.js +71 -0
- package/dist/services/agentTeams/permissionDelegation.js.map +7 -0
- package/dist/services/agentTeams/teamEvents.js +45 -0
- package/dist/services/agentTeams/teamEvents.js.map +7 -0
- package/dist/services/agentTeams/teamManager.js +251 -34
- package/dist/services/agentTeams/teamManager.js.map +2 -2
- package/dist/services/agentTeams/teamTaskStore.js +290 -61
- package/dist/services/agentTeams/teamTaskStore.js.map +2 -2
- package/dist/services/agentTeams/teammateSpawner.js +99 -18
- package/dist/services/agentTeams/teammateSpawner.js.map +2 -2
- package/dist/services/hookExecutor.js +51 -8
- package/dist/services/hookExecutor.js.map +2 -2
- package/dist/services/llm/anthropicProvider.js +56 -59
- package/dist/services/llm/anthropicProvider.js.map +2 -2
- package/dist/services/llm/dispatch.js +24 -5
- package/dist/services/llm/dispatch.js.map +2 -2
- package/dist/services/llm/openaiProvider.js +115 -136
- package/dist/services/llm/openaiProvider.js.map +3 -3
- package/dist/services/llm/types.js +89 -15
- package/dist/services/llm/types.js.map +2 -2
- package/dist/services/mcpClient.js +80 -4
- package/dist/services/mcpClient.js.map +2 -2
- package/dist/services/mintoAuth.js +299 -0
- package/dist/services/mintoAuth.js.map +7 -0
- package/dist/services/oauth.js +3 -3
- package/dist/services/oauth.js.map +2 -2
- package/dist/services/openai.js +91 -20
- package/dist/services/openai.js.map +2 -2
- package/dist/services/plugins/pluginRuntime.js +11 -5
- package/dist/services/plugins/pluginRuntime.js.map +2 -2
- package/dist/services/plugins/pluginValidation.js +4 -2
- package/dist/services/plugins/pluginValidation.js.map +2 -2
- package/dist/services/sandbox/sandboxController.js +11 -3
- package/dist/services/sandbox/sandboxController.js.map +2 -2
- package/dist/services/sessionMemoryInjector.js +77 -0
- package/dist/services/sessionMemoryInjector.js.map +7 -0
- package/dist/services/systemReminder.js +130 -8
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/services/taskStore.js +199 -8
- package/dist/services/taskStore.js.map +3 -3
- package/dist/services/topicDetector.js +169 -0
- package/dist/services/topicDetector.js.map +7 -0
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +0 -13
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
- package/dist/tools/BashTool/BashTool.js +51 -28
- package/dist/tools/BashTool/BashTool.js.map +2 -2
- package/dist/tools/BashTool/prompt.js +95 -118
- package/dist/tools/BashTool/prompt.js.map +2 -2
- package/dist/tools/BashTool/utils.js +39 -1
- package/dist/tools/BashTool/utils.js.map +2 -2
- package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js +121 -0
- package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js.map +7 -0
- package/dist/tools/EnterWorktreeTool/prompt.js +22 -0
- package/dist/tools/EnterWorktreeTool/prompt.js.map +7 -0
- package/dist/tools/FileEditTool/FileEditTool.js +9 -4
- package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
- package/dist/tools/FileEditTool/prompt.js +3 -7
- package/dist/tools/FileEditTool/prompt.js.map +2 -2
- package/dist/tools/FileReadTool/FileReadTool.js +125 -3
- package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
- package/dist/tools/FileReadTool/prompt.js +1 -2
- package/dist/tools/FileReadTool/prompt.js.map +2 -2
- package/dist/tools/FileWriteTool/prompt.js +3 -5
- package/dist/tools/FileWriteTool/prompt.js.map +2 -2
- package/dist/tools/GlobTool/GlobTool.js +3 -2
- package/dist/tools/GlobTool/GlobTool.js.map +2 -2
- package/dist/tools/GrepTool/GrepTool.js +16 -5
- package/dist/tools/GrepTool/GrepTool.js.map +2 -2
- package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
- package/dist/tools/MCPSearchTool/MCPSearchTool.js +172 -0
- package/dist/tools/MCPSearchTool/MCPSearchTool.js.map +7 -0
- package/dist/tools/MCPSearchTool/prompt.js +77 -0
- package/dist/tools/MCPSearchTool/prompt.js.map +7 -0
- package/dist/tools/MultiEditTool/prompt.js +4 -7
- package/dist/tools/MultiEditTool/prompt.js.map +2 -2
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js +12 -8
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js +54 -1
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/prompt.js +23 -74
- package/dist/tools/PlanModeTool/prompt.js.map +2 -2
- package/dist/tools/SendMessageTool/SendMessageTool.js +341 -0
- package/dist/tools/SendMessageTool/SendMessageTool.js.map +7 -0
- package/dist/tools/SendMessageTool/prompt.js +44 -0
- package/dist/tools/SendMessageTool/prompt.js.map +7 -0
- package/dist/tools/TaskCreateTool/prompt.js +15 -4
- package/dist/tools/TaskCreateTool/prompt.js.map +2 -2
- package/dist/tools/TaskListTool/prompt.js +18 -3
- package/dist/tools/TaskListTool/prompt.js.map +2 -2
- package/dist/tools/TaskOutputTool/prompt.js +4 -3
- package/dist/tools/TaskOutputTool/prompt.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +762 -98
- package/dist/tools/TaskTool/TaskTool.js.map +3 -3
- package/dist/tools/TaskTool/constants.js +8 -2
- package/dist/tools/TaskTool/constants.js.map +2 -2
- package/dist/tools/TaskTool/prompt.js +74 -70
- package/dist/tools/TaskTool/prompt.js.map +2 -2
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js +15 -1
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +2 -2
- package/dist/tools/TeamCreateTool/TeamCreateTool.js +129 -0
- package/dist/tools/TeamCreateTool/TeamCreateTool.js.map +7 -0
- package/dist/tools/TeamCreateTool/prompt.js +58 -0
- package/dist/tools/TeamCreateTool/prompt.js.map +7 -0
- package/dist/tools/TeamDeleteTool/TeamDeleteTool.js +151 -0
- package/dist/tools/TeamDeleteTool/TeamDeleteTool.js.map +7 -0
- package/dist/tools/TeamDeleteTool/prompt.js +16 -0
- package/dist/tools/TeamDeleteTool/prompt.js.map +7 -0
- package/dist/tools/URLFetcherTool/URLFetcherTool.js +106 -15
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
- package/dist/tools/URLFetcherTool/prompt.js +3 -2
- package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
- package/dist/tools/WebSearchTool/WebSearchTool.js +2 -1
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
- package/dist/tools/WebSearchTool/prompt.js +5 -4
- package/dist/tools/WebSearchTool/prompt.js.map +2 -2
- package/dist/tools.js +100 -20
- package/dist/tools.js.map +2 -2
- package/dist/types/PermissionMode.js +35 -6
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/hooks.js +2 -0
- package/dist/types/hooks.js.map +2 -2
- package/dist/types/plugin.js +2 -0
- package/dist/types/plugin.js.map +3 -3
- package/dist/utils/CircuitBreaker.js +15 -9
- package/dist/utils/CircuitBreaker.js.map +2 -2
- package/dist/utils/agentLoader.js +249 -112
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/animationManager.js +40 -3
- package/dist/utils/animationManager.js.map +2 -2
- package/dist/utils/ask.js +7 -6
- package/dist/utils/ask.js.map +2 -2
- package/dist/utils/atomicWrite.js +23 -0
- package/dist/utils/atomicWrite.js.map +7 -0
- package/dist/utils/autoCompactCore.js +73 -56
- package/dist/utils/autoCompactCore.js.map +2 -2
- package/dist/utils/autoMemoryPaths.js +89 -0
- package/dist/utils/autoMemoryPaths.js.map +7 -0
- package/dist/utils/config.js +63 -38
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configSchema.js +13 -8
- package/dist/utils/configSchema.js.map +2 -2
- package/dist/utils/credentials/index.js +14 -0
- package/dist/utils/credentials/index.js.map +2 -2
- package/dist/utils/dualPath.js +24 -0
- package/dist/utils/dualPath.js.map +7 -0
- package/dist/utils/exit.js +66 -7
- package/dist/utils/exit.js.map +2 -2
- package/dist/utils/externalEditor.js +155 -0
- package/dist/utils/externalEditor.js.map +7 -0
- package/dist/utils/fileLock.js +67 -0
- package/dist/utils/fileLock.js.map +7 -0
- package/dist/utils/format.js +24 -14
- package/dist/utils/format.js.map +2 -2
- package/dist/utils/globalErrorHandler.js +5 -96
- package/dist/utils/globalErrorHandler.js.map +3 -3
- package/dist/utils/groupHandlers/parallelTasksHandler.js +5 -3
- package/dist/utils/groupHandlers/parallelTasksHandler.js.map +2 -2
- package/dist/utils/groupHandlers/taskHandler.js +2 -2
- package/dist/utils/groupHandlers/taskHandler.js.map +2 -2
- package/dist/utils/hookManager.js +64 -6
- package/dist/utils/hookManager.js.map +2 -2
- package/dist/utils/log.js +6 -2
- package/dist/utils/log.js.map +2 -2
- package/dist/utils/markdown.js +237 -19
- package/dist/utils/markdown.js.map +2 -2
- package/dist/utils/messageContextManager.js +18 -5
- package/dist/utils/messageContextManager.js.map +2 -2
- package/dist/utils/messageGroupManager.js +1 -1
- package/dist/utils/messageGroupManager.js.map +2 -2
- package/dist/utils/messages.js +104 -46
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/model.js +2 -2
- package/dist/utils/model.js.map +2 -2
- package/dist/utils/pasteCache.js +8 -4
- package/dist/utils/pasteCache.js.map +2 -2
- package/dist/utils/pluginLoader.js +18 -0
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/secureKeyStorage.js +36 -7
- package/dist/utils/secureKeyStorage.js.map +2 -2
- package/dist/utils/simpleMode.js +7 -0
- package/dist/utils/simpleMode.js.map +7 -0
- package/dist/utils/streamingState.js +11 -1
- package/dist/utils/streamingState.js.map +2 -2
- package/dist/utils/taskDisplayUtils.js +2 -1
- package/dist/utils/taskDisplayUtils.js.map +2 -2
- package/dist/utils/teamConfig.js +2 -2
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/thinking.js +6 -2
- package/dist/utils/thinking.js.map +3 -3
- package/dist/utils/tokenProgress.js +55 -0
- package/dist/utils/tokenProgress.js.map +7 -0
- package/dist/utils/toolRiskClassification.js +26 -17
- package/dist/utils/toolRiskClassification.js.map +2 -2
- package/dist/utils/tooling/toolError.js +12 -0
- package/dist/utils/tooling/toolError.js.map +7 -0
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +10 -8
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/services/agentTeams/messageFormatter.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Agent Teams Message Formatter\n *\n * Shared XML formatting helpers for consistent message injection\n * across REPL, TaskTool, headless agents, and heartbeat.\n *\n * All injection points use the CC-compatible `<team-message>` tag format.\n */\n\nimport type { TeamMessage } from '../../types/agentTeams'\n\n/**\n * Sanitize team message text to prevent injection attacks.\n * Replaces XML tags that could break message envelopes or forge system instructions.\n */\nexport function sanitizeTeamMessageText(text: string): string {\n return (\n text\n // Prevent envelope breakout\n .replace(/<\\/team-message>/gi, '[team-message-close]')\n // Prevent system instruction forgery\n .replace(/<system-reminder>/gi, '[system-reminder-open]')\n .replace(/<\\/system-reminder>/gi, '[system-reminder-close]')\n // Prevent API protocol injection\n .replace(/<tool_use>/gi, '[tool-use-open]')\n .replace(/<\\/tool_use>/gi, '[tool-use-close]')\n .replace(/<tool_result>/gi, '[tool-result-open]')\n .replace(/<\\/tool_result>/gi, '[tool-result-close]')\n // Prevent opening tag injection (with potential attributes)\n .replace(/<team-message\\b/gi, '[team-message-open')\n // Prevent user guidance injection\n .replace(/<user-guidance>/gi, '[user-guidance-open]')\n .replace(/<\\/user-guidance>/gi, '[user-guidance-close]')\n // Prevent task notification injection\n .replace(/<task-notification>/gi, '[task-notification-open]')\n .replace(/<\\/task-notification>/gi, '[task-notification-close]')\n // Prevent skill injection\n .replace(/<preloaded-skill>/gi, '[preloaded-skill-open]')\n .replace(/<\\/preloaded-skill>/gi, '[preloaded-skill-close]')\n )\n}\n\n/**\n * Data extracted from idle notification JSON messages\n */\nexport interface IdleNotificationData {\n agentName: string\n status: 'idle' | 'completed' | 'failed'\n taskId?: string\n message?: string\n summary?: string\n}\n\n/**\n * Format a single team message as CC-compatible XML.\n *\n * Output:\n * ```xml\n * <team-message from=\"researcher\" color=\"cyan\" summary=\"Found 5 files\">\n * {message text}\n * </team-message>\n * ```\n */\nexport function formatTeamMessage(msg: TeamMessage): string {\n const senderName = msg.from.split('@')[0] || msg.from\n const summaryText = msg.summary || msg.text.slice(0, 60).replace(/\"/g, \"'\")\n const colorAttr = msg.color ? ` color=\"${msg.color}\"` : ''\n const sanitizedText = sanitizeTeamMessageText(msg.text)\n return `<team-message from=\"${senderName}\"${colorAttr} summary=\"${summaryText}\">\\n${sanitizedText}\\n</team-message>`\n}\n\n/**\n * Format multiple team messages for injection into a conversation turn.\n * Returns a single string with all messages separated by double newlines.\n */\nexport function formatTeamMessagesForInjection(\n messages: TeamMessage[],\n): string {\n return messages.map(formatTeamMessage).join('\\n\\n')\n}\n\n/**\n * Format user guidance for injection when user types during a running query.\n *\n * Output:\n * ```xml\n * <user-guidance>\n * {user's input text}\n * </user-guidance>\n * ```\n */\nexport function formatUserGuidanceForInjection(input: string): string {\n const sanitizedInput = sanitizeTeamMessageText(input)\n return `<user-guidance>\\n${sanitizedInput}\\n</user-guidance>`\n}\n\n/**\n * Format an idle/task notification for injection.\n *\n * Output:\n * ```xml\n * <task-notification>\n * <task-id>{taskId}</task-id>\n * <status>{status}</status>\n * <message>{message}</message>\n * </task-notification>\n * ```\n */\nexport function formatIdleNotificationForInjection(\n notification: IdleNotificationData,\n): string {\n const parts = ['<task-notification>']\n if (notification.taskId) {\n parts.push(` <task-id>${notification.taskId}</task-id>`)\n }\n parts.push(` <status>${notification.status}</status>`)\n parts.push(\n ` <message>${notification.message || `Teammate \"${notification.agentName}\" is now ${notification.status}.`}</message>`,\n )\n if (notification.summary) {\n parts.push(` <summary>${notification.summary}</summary>`)\n }\n parts.push('</task-notification>')\n return parts.join('\\n')\n}\n\n/**\n * Try to parse a message as an idle notification JSON.\n * Returns parsed data if successful, null otherwise.\n */\n/**\n * Protocol message type \u2192 human-friendly summary mapping.\n */\nconst PROTOCOL_SUMMARIES: Record<string, string> = {\n shutdown_approved: 'Shutdown approved',\n shutdown_rejected: 'Shutdown rejected',\n shutdown_request: 'Shutdown requested',\n plan_approved: 'Plan approved',\n plan_rejected: 'Plan rejected',\n plan_approval_request: 'Plan review requested',\n}\n\n/**\n * Try to convert a protocol JSON message to a human-friendly summary.\n * Returns the friendly string, or null if not a protocol message.\n */\nexport function humanizeProtocolMessage(text: string): string | null {\n try {\n const parsed = JSON.parse(text)\n if (\n parsed &&\n typeof parsed === 'object' &&\n parsed.type in PROTOCOL_SUMMARIES\n ) {\n return PROTOCOL_SUMMARIES[parsed.type] || parsed.type\n }\n } catch {\n /* not JSON */\n }\n return null\n}\n\nexport function parseIdleNotification(\n text: string,\n): IdleNotificationData | null {\n try {\n const parsed = JSON.parse(text)\n if (\n parsed &&\n typeof parsed === 'object' &&\n (parsed.type === 'idle_notification' ||\n parsed.type === 'task_completed' ||\n parsed.type === 'idle')\n ) {\n return {\n agentName: parsed.agentName || parsed.from || 'unknown',\n status: parsed.status || parsed.completedStatus || 'idle',\n taskId: parsed.taskId,\n message: parsed.message,\n summary: parsed.summary,\n }\n }\n } catch {\n // Not JSON \u2014 regular text message\n }\n return null\n}\n"],
|
|
5
|
+
"mappings": "AAeO,SAAS,wBAAwB,MAAsB;AAC5D,SACE,KAEG,QAAQ,sBAAsB,sBAAsB,EAEpD,QAAQ,uBAAuB,wBAAwB,EACvD,QAAQ,yBAAyB,yBAAyB,EAE1D,QAAQ,gBAAgB,iBAAiB,EACzC,QAAQ,kBAAkB,kBAAkB,EAC5C,QAAQ,mBAAmB,oBAAoB,EAC/C,QAAQ,qBAAqB,qBAAqB,EAElD,QAAQ,qBAAqB,oBAAoB,EAEjD,QAAQ,qBAAqB,sBAAsB,EACnD,QAAQ,uBAAuB,uBAAuB,EAEtD,QAAQ,yBAAyB,0BAA0B,EAC3D,QAAQ,2BAA2B,2BAA2B,EAE9D,QAAQ,uBAAuB,wBAAwB,EACvD,QAAQ,yBAAyB,yBAAyB;AAEjE;AAuBO,SAAS,kBAAkB,KAA0B;AAC1D,QAAM,aAAa,IAAI,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI;AACjD,QAAM,cAAc,IAAI,WAAW,IAAI,KAAK,MAAM,GAAG,EAAE,EAAE,QAAQ,MAAM,GAAG;AAC1E,QAAM,YAAY,IAAI,QAAQ,WAAW,IAAI,KAAK,MAAM;AACxD,QAAM,gBAAgB,wBAAwB,IAAI,IAAI;AACtD,SAAO,uBAAuB,UAAU,IAAI,SAAS,aAAa,WAAW;AAAA,EAAO,aAAa;AAAA;AACnG;AAMO,SAAS,+BACd,UACQ;AACR,SAAO,SAAS,IAAI,iBAAiB,EAAE,KAAK,MAAM;AACpD;AAYO,SAAS,+BAA+B,OAAuB;AACpE,QAAM,iBAAiB,wBAAwB,KAAK;AACpD,SAAO;AAAA,EAAoB,cAAc;AAAA;AAC3C;AAcO,SAAS,mCACd,cACQ;AACR,QAAM,QAAQ,CAAC,qBAAqB;AACpC,MAAI,aAAa,QAAQ;AACvB,UAAM,KAAK,cAAc,aAAa,MAAM,YAAY;AAAA,EAC1D;AACA,QAAM,KAAK,aAAa,aAAa,MAAM,WAAW;AACtD,QAAM;AAAA,IACJ,cAAc,aAAa,WAAW,aAAa,aAAa,SAAS,YAAY,aAAa,MAAM,GAAG;AAAA,EAC7G;AACA,MAAI,aAAa,SAAS;AACxB,UAAM,KAAK,cAAc,aAAa,OAAO,YAAY;AAAA,EAC3D;AACA,QAAM,KAAK,sBAAsB;AACjC,SAAO,MAAM,KAAK,IAAI;AACxB;AASA,MAAM,qBAA6C;AAAA,EACjD,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,eAAe;AAAA,EACf,uBAAuB;AACzB;AAMO,SAAS,wBAAwB,MAA6B;AACnE,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QACE,UACA,OAAO,WAAW,YAClB,OAAO,QAAQ,oBACf;AACA,aAAO,mBAAmB,OAAO,IAAI,KAAK,OAAO;AAAA,IACnD;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEO,SAAS,sBACd,MAC6B;AAC7B,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QACE,UACA,OAAO,WAAW,aACjB,OAAO,SAAS,uBACf,OAAO,SAAS,oBAChB,OAAO,SAAS,SAClB;AACA,aAAO;AAAA,QACL,WAAW,OAAO,aAAa,OAAO,QAAQ;AAAA,QAC9C,QAAQ,OAAO,UAAU,OAAO,mBAAmB;AAAA,QACnD,QAAQ,OAAO;AAAA,QACf,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,MAClB;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
async function delegatePermissionToLead(options) {
|
|
2
|
+
const {
|
|
3
|
+
teamName,
|
|
4
|
+
agentId,
|
|
5
|
+
toolName,
|
|
6
|
+
toolUseId,
|
|
7
|
+
input,
|
|
8
|
+
description,
|
|
9
|
+
permissionSuggestions
|
|
10
|
+
} = options;
|
|
11
|
+
let mailbox;
|
|
12
|
+
try {
|
|
13
|
+
const { getTeam } = require("./teamManager");
|
|
14
|
+
const entry = getTeam(teamName);
|
|
15
|
+
if (!entry?.mailbox) {
|
|
16
|
+
return { approved: false, error: "Team not found or mailbox unavailable" };
|
|
17
|
+
}
|
|
18
|
+
mailbox = entry.mailbox;
|
|
19
|
+
} catch {
|
|
20
|
+
return { approved: false, error: "Failed to access team mailbox" };
|
|
21
|
+
}
|
|
22
|
+
const requestId = `perm-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
23
|
+
const leadId = `team-lead@${teamName}`;
|
|
24
|
+
const request = JSON.stringify({
|
|
25
|
+
type: "permission_request",
|
|
26
|
+
request_id: requestId,
|
|
27
|
+
agent_id: agentId,
|
|
28
|
+
tool_name: toolName,
|
|
29
|
+
tool_use_id: toolUseId,
|
|
30
|
+
description,
|
|
31
|
+
input,
|
|
32
|
+
permission_suggestions: permissionSuggestions ?? [],
|
|
33
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
34
|
+
});
|
|
35
|
+
mailbox.send(agentId, leadId, request, {
|
|
36
|
+
summary: `Permission request: ${toolName}`
|
|
37
|
+
});
|
|
38
|
+
const POLL_INTERVAL = 500;
|
|
39
|
+
const TIMEOUT = 12e4;
|
|
40
|
+
const startTime = Date.now();
|
|
41
|
+
while (Date.now() - startTime < TIMEOUT) {
|
|
42
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
|
|
43
|
+
const messages = mailbox.getUnread(agentId);
|
|
44
|
+
for (const msg of messages) {
|
|
45
|
+
try {
|
|
46
|
+
const parsed = JSON.parse(msg.text);
|
|
47
|
+
if (parsed.type === "permission_response" && parsed.request_id === requestId) {
|
|
48
|
+
mailbox.markRead([msg.id]);
|
|
49
|
+
if (parsed.subtype === "success" || parsed.approved) {
|
|
50
|
+
return {
|
|
51
|
+
approved: true,
|
|
52
|
+
updatedInput: parsed.response?.updated_input ?? void 0,
|
|
53
|
+
permissionUpdates: parsed.response?.permission_updates ?? void 0
|
|
54
|
+
};
|
|
55
|
+
} else {
|
|
56
|
+
return {
|
|
57
|
+
approved: false,
|
|
58
|
+
error: parsed.error || "Permission denied by team lead"
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { approved: false, error: "Permission request timed out (120s)" };
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
delegatePermissionToLead
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=permissionDelegation.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/services/agentTeams/permissionDelegation.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Permission Delegation for Agent Teams\n *\n * Allows headless teammates to delegate permission decisions to the team lead\n * via the mailbox, instead of auto-denying tool usage.\n *\n * Flow:\n * 1. Teammate calls a tool that requires user permission\n * 2. Instead of auto-denying, teammate sends `permission_request` to leader's inbox\n * 3. Leader reviews and sends `permission_response` back via SendMessage\n * 4. Teammate blocks (polling) until response arrives, then proceeds or fails\n */\n\nimport type { Mailbox } from './mailbox'\n\nexport interface PermissionDelegationResult {\n approved: boolean\n updatedInput?: Record<string, unknown>\n permissionUpdates?: Record<string, unknown>\n error?: string\n}\n\n/**\n * Delegate a permission decision to the team lead via mailbox.\n * Sends a permission_request and polls for permission_response.\n *\n * @returns Result with approved status and optional updates from the leader\n */\nexport async function delegatePermissionToLead(options: {\n teamName: string\n agentId: string\n toolName: string\n toolUseId: string\n input: Record<string, unknown>\n description: string\n permissionSuggestions?: string[]\n}): Promise<PermissionDelegationResult> {\n const {\n teamName,\n agentId,\n toolName,\n toolUseId,\n input,\n description,\n permissionSuggestions,\n } = options\n\n // Get the team's mailbox\n let mailbox: Mailbox\n try {\n // Lazy require to avoid circular dependencies at module load time\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { getTeam } =\n require('./teamManager') as typeof import('./teamManager')\n const entry = getTeam(teamName)\n if (!entry?.mailbox) {\n return { approved: false, error: 'Team not found or mailbox unavailable' }\n }\n mailbox = entry.mailbox\n } catch {\n return { approved: false, error: 'Failed to access team mailbox' }\n }\n\n const requestId = `perm-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n const leadId = `team-lead@${teamName}`\n\n // Send permission_request to the team leader\n const request = JSON.stringify({\n type: 'permission_request',\n request_id: requestId,\n agent_id: agentId,\n tool_name: toolName,\n tool_use_id: toolUseId,\n description,\n input,\n permission_suggestions: permissionSuggestions ?? [],\n timestamp: new Date().toISOString(),\n })\n\n mailbox.send(agentId, leadId, request, {\n summary: `Permission request: ${toolName}`,\n })\n\n // Poll for response with timeout\n const POLL_INTERVAL = 500 // ms\n const TIMEOUT = 120_000 // 2 minutes\n const startTime = Date.now()\n\n while (Date.now() - startTime < TIMEOUT) {\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL))\n\n const messages = mailbox.getUnread(agentId)\n for (const msg of messages) {\n try {\n const parsed = JSON.parse(msg.text)\n if (\n parsed.type === 'permission_response' &&\n parsed.request_id === requestId\n ) {\n mailbox.markRead([msg.id])\n if (parsed.subtype === 'success' || parsed.approved) {\n return {\n approved: true,\n updatedInput: parsed.response?.updated_input ?? undefined,\n permissionUpdates:\n parsed.response?.permission_updates ?? undefined,\n }\n } else {\n return {\n approved: false,\n error: parsed.error || 'Permission denied by team lead',\n }\n }\n }\n } catch {\n // Not a JSON message or not our response \u2014 skip\n }\n }\n }\n\n return { approved: false, error: 'Permission request timed out (120s)' }\n}\n"],
|
|
5
|
+
"mappings": "AA4BA,eAAsB,yBAAyB,SAQP;AACtC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAGJ,MAAI;AACJ,MAAI;AAGF,UAAM,EAAE,QAAQ,IACd,QAAQ,eAAe;AACzB,UAAM,QAAQ,QAAQ,QAAQ;AAC9B,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO,EAAE,UAAU,OAAO,OAAO,wCAAwC;AAAA,IAC3E;AACA,cAAU,MAAM;AAAA,EAClB,QAAQ;AACN,WAAO,EAAE,UAAU,OAAO,OAAO,gCAAgC;AAAA,EACnE;AAEA,QAAM,YAAY,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAC9E,QAAM,SAAS,aAAa,QAAQ;AAGpC,QAAM,UAAU,KAAK,UAAU;AAAA,IAC7B,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,wBAAwB,yBAAyB,CAAC;AAAA,IAClD,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC,CAAC;AAED,UAAQ,KAAK,SAAS,QAAQ,SAAS;AAAA,IACrC,SAAS,uBAAuB,QAAQ;AAAA,EAC1C,CAAC;AAGD,QAAM,gBAAgB;AACtB,QAAM,UAAU;AAChB,QAAM,YAAY,KAAK,IAAI;AAE3B,SAAO,KAAK,IAAI,IAAI,YAAY,SAAS;AACvC,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,aAAa,CAAC;AAE/D,UAAM,WAAW,QAAQ,UAAU,OAAO;AAC1C,eAAW,OAAO,UAAU;AAC1B,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,IAAI,IAAI;AAClC,YACE,OAAO,SAAS,yBAChB,OAAO,eAAe,WACtB;AACA,kBAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;AACzB,cAAI,OAAO,YAAY,aAAa,OAAO,UAAU;AACnD,mBAAO;AAAA,cACL,UAAU;AAAA,cACV,cAAc,OAAO,UAAU,iBAAiB;AAAA,cAChD,mBACE,OAAO,UAAU,sBAAsB;AAAA,YAC3C;AAAA,UACF,OAAO;AACL,mBAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO,OAAO,SAAS;AAAA,YACzB;AAAA,UACF;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,OAAO,OAAO,sCAAsC;AACzE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
class TeamEventEmitter extends EventEmitter {
|
|
3
|
+
static instance = null;
|
|
4
|
+
constructor() {
|
|
5
|
+
super();
|
|
6
|
+
this.setMaxListeners(20);
|
|
7
|
+
}
|
|
8
|
+
static getInstance() {
|
|
9
|
+
if (!TeamEventEmitter.instance) {
|
|
10
|
+
TeamEventEmitter.instance = new TeamEventEmitter();
|
|
11
|
+
}
|
|
12
|
+
return TeamEventEmitter.instance;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Emit member status change event
|
|
16
|
+
*/
|
|
17
|
+
emitMemberStatusChange(data) {
|
|
18
|
+
this.emit("member:status", data);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Emit team lifecycle change event
|
|
22
|
+
*/
|
|
23
|
+
emitTeamChange(data) {
|
|
24
|
+
this.emit("team:change", data);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Subscribe to member status changes
|
|
28
|
+
*/
|
|
29
|
+
onMemberStatusChange(callback) {
|
|
30
|
+
this.on("member:status", callback);
|
|
31
|
+
return () => this.off("member:status", callback);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Subscribe to team lifecycle changes
|
|
35
|
+
*/
|
|
36
|
+
onTeamChange(callback) {
|
|
37
|
+
this.on("team:change", callback);
|
|
38
|
+
return () => this.off("team:change", callback);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const teamEvents = TeamEventEmitter.getInstance();
|
|
42
|
+
export {
|
|
43
|
+
teamEvents
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=teamEvents.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/services/agentTeams/teamEvents.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Team Events\n *\n * Singleton EventEmitter for team lifecycle and member status changes.\n * Follows the same pattern as BackgroundAgentEventEmitter.\n *\n * Enables event-driven UI updates instead of polling.\n */\n\nimport { EventEmitter } from 'events'\nimport type { TeammateStatus } from '@minto-types/agentTeams'\n\nexport interface MemberStatusChangeData {\n teamName: string\n memberId: string\n memberName: string\n status: TeammateStatus\n previousStatus: TeammateStatus\n currentTaskId?: string\n}\n\nexport interface TeamChangeData {\n teamName: string\n event: 'created' | 'disbanded' | 'member_added'\n}\n\nclass TeamEventEmitter extends EventEmitter {\n private static instance: TeamEventEmitter | null = null\n\n private constructor() {\n super()\n this.setMaxListeners(20)\n }\n\n static getInstance(): TeamEventEmitter {\n if (!TeamEventEmitter.instance) {\n TeamEventEmitter.instance = new TeamEventEmitter()\n }\n return TeamEventEmitter.instance\n }\n\n /**\n * Emit member status change event\n */\n emitMemberStatusChange(data: MemberStatusChangeData): void {\n this.emit('member:status', data)\n }\n\n /**\n * Emit team lifecycle change event\n */\n emitTeamChange(data: TeamChangeData): void {\n this.emit('team:change', data)\n }\n\n /**\n * Subscribe to member status changes\n */\n onMemberStatusChange(\n callback: (data: MemberStatusChangeData) => void,\n ): () => void {\n this.on('member:status', callback)\n return () => this.off('member:status', callback)\n }\n\n /**\n * Subscribe to team lifecycle changes\n */\n onTeamChange(callback: (data: TeamChangeData) => void): () => void {\n this.on('team:change', callback)\n return () => this.off('team:change', callback)\n }\n}\n\nexport const teamEvents = TeamEventEmitter.getInstance()\n"],
|
|
5
|
+
"mappings": "AASA,SAAS,oBAAoB;AAiB7B,MAAM,yBAAyB,aAAa;AAAA,EAC1C,OAAe,WAAoC;AAAA,EAE3C,cAAc;AACpB,UAAM;AACN,SAAK,gBAAgB,EAAE;AAAA,EACzB;AAAA,EAEA,OAAO,cAAgC;AACrC,QAAI,CAAC,iBAAiB,UAAU;AAC9B,uBAAiB,WAAW,IAAI,iBAAiB;AAAA,IACnD;AACA,WAAO,iBAAiB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,MAAoC;AACzD,SAAK,KAAK,iBAAiB,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,MAA4B;AACzC,SAAK,KAAK,eAAe,IAAI;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,qBACE,UACY;AACZ,SAAK,GAAG,iBAAiB,QAAQ;AACjC,WAAO,MAAM,KAAK,IAAI,iBAAiB,QAAQ;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,UAAsD;AACjE,SAAK,GAAG,eAAe,QAAQ;AAC/B,WAAO,MAAM,KAAK,IAAI,eAAe,QAAQ;AAAA,EAC/C;AACF;AAEO,MAAM,aAAa,iBAAiB,YAAY;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,22 +1,139 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
existsSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
writeFileSync,
|
|
5
|
+
readFileSync,
|
|
6
|
+
unlinkSync
|
|
7
|
+
} from "fs";
|
|
8
|
+
import { randomUUID } from "crypto";
|
|
2
9
|
import { join } from "path";
|
|
3
10
|
import { homedir } from "os";
|
|
11
|
+
import { z } from "zod";
|
|
4
12
|
import { Mailbox } from "./mailbox.js";
|
|
5
13
|
import { TeamTaskStore } from "./teamTaskStore.js";
|
|
6
14
|
import { emitReminderEvent } from "../systemReminder.js";
|
|
15
|
+
import { teamEvents } from "./teamEvents.js";
|
|
16
|
+
import { debug } from "../../utils/debugLogger.js";
|
|
17
|
+
const TeamConfigFileSchema = z.object({
|
|
18
|
+
name: z.string(),
|
|
19
|
+
description: z.string().optional().default(""),
|
|
20
|
+
createdAt: z.number(),
|
|
21
|
+
leadAgentId: z.string().optional(),
|
|
22
|
+
leadSessionId: z.string().optional().default(""),
|
|
23
|
+
displayMode: z.string().optional().default("auto"),
|
|
24
|
+
maxTeammates: z.number().optional().default(10),
|
|
25
|
+
members: z.array(
|
|
26
|
+
z.object({
|
|
27
|
+
agentId: z.string(),
|
|
28
|
+
name: z.string(),
|
|
29
|
+
agentType: z.string(),
|
|
30
|
+
color: z.string().nullable().optional(),
|
|
31
|
+
joinedAt: z.number().optional(),
|
|
32
|
+
tmuxPaneId: z.string().optional(),
|
|
33
|
+
cwd: z.string().optional(),
|
|
34
|
+
subscriptions: z.array(z.string()).optional(),
|
|
35
|
+
backendType: z.string().optional(),
|
|
36
|
+
worktreePath: z.string().nullable().optional(),
|
|
37
|
+
planModeRequired: z.boolean().optional(),
|
|
38
|
+
isActive: z.boolean().optional(),
|
|
39
|
+
mode: z.string().nullable().optional(),
|
|
40
|
+
status: z.string().optional(),
|
|
41
|
+
prompt: z.string().optional(),
|
|
42
|
+
currentTaskId: z.string().nullable().optional(),
|
|
43
|
+
lastActivity: z.number().nullable().optional(),
|
|
44
|
+
parentSessionId: z.string().nullable().optional()
|
|
45
|
+
})
|
|
46
|
+
).optional().default([])
|
|
47
|
+
});
|
|
48
|
+
function sanitizeTeamName(name) {
|
|
49
|
+
return name.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
|
|
50
|
+
}
|
|
7
51
|
function isAgentTeamsEnabled() {
|
|
8
|
-
|
|
52
|
+
if (process.env.MINTO_EXPERIMENTAL_AGENT_TEAMS === "0") return false;
|
|
53
|
+
if (process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === "0") return false;
|
|
54
|
+
if (process.env.MINTO_EXPERIMENTAL_AGENT_TEAMS === "1") return true;
|
|
55
|
+
if (process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === "1") return true;
|
|
56
|
+
try {
|
|
57
|
+
const { getGlobalConfig } = require("../../utils/config");
|
|
58
|
+
const config = getGlobalConfig();
|
|
59
|
+
if (config.enableAgentTeams === false) return false;
|
|
60
|
+
if (config.enableAgentTeams === true) return true;
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
9
64
|
}
|
|
10
65
|
const activeTeams = /* @__PURE__ */ new Map();
|
|
66
|
+
const agentAbortControllers = /* @__PURE__ */ new Map();
|
|
67
|
+
function registerAgentAbortController(teamName, agentId, controller) {
|
|
68
|
+
agentAbortControllers.set(`${teamName}:${agentId}`, controller);
|
|
69
|
+
}
|
|
70
|
+
function unregisterAgentAbortController(teamName, agentId) {
|
|
71
|
+
agentAbortControllers.delete(`${teamName}:${agentId}`);
|
|
72
|
+
}
|
|
73
|
+
function abortTeamAgents(teamName) {
|
|
74
|
+
for (const [key, controller] of agentAbortControllers) {
|
|
75
|
+
if (key.startsWith(`${teamName}:`)) {
|
|
76
|
+
try {
|
|
77
|
+
controller.abort();
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
agentAbortControllers.delete(key);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
11
84
|
function getTeamsDir() {
|
|
12
85
|
return join(homedir(), ".minto", "teams");
|
|
13
86
|
}
|
|
87
|
+
function persistTeam(teamDir, team) {
|
|
88
|
+
try {
|
|
89
|
+
const configData = {
|
|
90
|
+
name: team.name,
|
|
91
|
+
description: team.config.description || "",
|
|
92
|
+
createdAt: team.createdAt,
|
|
93
|
+
leadAgentId: `team-lead@${team.name}`,
|
|
94
|
+
leadSessionId: team.leadSessionId || "",
|
|
95
|
+
// Minto extensions
|
|
96
|
+
displayMode: team.config.displayMode || "auto",
|
|
97
|
+
maxTeammates: team.config.maxTeammates || 10,
|
|
98
|
+
members: team.members.map((m) => ({
|
|
99
|
+
// CC-compatible fields
|
|
100
|
+
agentId: m.id,
|
|
101
|
+
name: m.name,
|
|
102
|
+
agentType: m.agentType,
|
|
103
|
+
color: m.color || null,
|
|
104
|
+
joinedAt: m.joinedAt || m.lastActivity,
|
|
105
|
+
tmuxPaneId: m.tmuxPaneId || (m.backendType === "in-process" ? "in-process" : "unknown"),
|
|
106
|
+
cwd: m.cwd || process.cwd(),
|
|
107
|
+
subscriptions: m.subscriptions || [],
|
|
108
|
+
backendType: m.backendType || "in-process",
|
|
109
|
+
worktreePath: m.worktreePath || null,
|
|
110
|
+
planModeRequired: m.planModeRequired || false,
|
|
111
|
+
isActive: m.isActive !== false,
|
|
112
|
+
mode: m.mode || null,
|
|
113
|
+
// Minto extension fields
|
|
114
|
+
status: m.status || "idle",
|
|
115
|
+
prompt: m.prompt || "",
|
|
116
|
+
currentTaskId: m.currentTaskId || null,
|
|
117
|
+
lastActivity: m.lastActivity || null,
|
|
118
|
+
parentSessionId: m.parentSessionId || null
|
|
119
|
+
}))
|
|
120
|
+
};
|
|
121
|
+
writeFileSync(
|
|
122
|
+
join(teamDir, "config.json"),
|
|
123
|
+
JSON.stringify(configData, null, 2),
|
|
124
|
+
"utf-8"
|
|
125
|
+
);
|
|
126
|
+
} catch (error) {
|
|
127
|
+
debug.warn("TEAM_PERSIST_CONFIG_FAILED", { error });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
14
130
|
function createTeam(config) {
|
|
15
131
|
if (!isAgentTeamsEnabled()) {
|
|
16
132
|
throw new Error(
|
|
17
|
-
"Agent Teams is
|
|
133
|
+
"Agent Teams is disabled. Remove enableAgentTeams: false from config or unset MINTO_EXPERIMENTAL_AGENT_TEAMS=0 to re-enable."
|
|
18
134
|
);
|
|
19
135
|
}
|
|
136
|
+
config = { ...config, name: sanitizeTeamName(config.name) };
|
|
20
137
|
if (activeTeams.has(config.name)) {
|
|
21
138
|
throw new Error(`Team "${config.name}" already exists`);
|
|
22
139
|
}
|
|
@@ -24,7 +141,8 @@ function createTeam(config) {
|
|
|
24
141
|
name: config.name,
|
|
25
142
|
config,
|
|
26
143
|
members: [],
|
|
27
|
-
createdAt: Date.now()
|
|
144
|
+
createdAt: Date.now(),
|
|
145
|
+
leadSessionId: randomUUID()
|
|
28
146
|
};
|
|
29
147
|
const mailbox = new Mailbox(config.name);
|
|
30
148
|
const taskStore = new TeamTaskStore(config.name);
|
|
@@ -34,12 +152,9 @@ function createTeam(config) {
|
|
|
34
152
|
if (!existsSync(teamDir)) {
|
|
35
153
|
mkdirSync(teamDir, { recursive: true });
|
|
36
154
|
}
|
|
37
|
-
|
|
38
|
-
join(teamDir, "team.json"),
|
|
39
|
-
JSON.stringify(team, null, 2),
|
|
40
|
-
"utf-8"
|
|
41
|
-
);
|
|
155
|
+
persistTeam(teamDir, team);
|
|
42
156
|
activeTeams.set(config.name, { team, mailbox, taskStore });
|
|
157
|
+
teamEvents.emitTeamChange({ teamName: config.name, event: "created" });
|
|
43
158
|
emitReminderEvent("team:coordination", {
|
|
44
159
|
teamId: config.name,
|
|
45
160
|
message: `Team "${config.name}" created (max ${config.maxTeammates} teammates).`
|
|
@@ -51,6 +166,17 @@ function addTeammate(teamName, teammate) {
|
|
|
51
166
|
if (!entry) {
|
|
52
167
|
throw new Error(`Team "${teamName}" not found`);
|
|
53
168
|
}
|
|
169
|
+
const activeMembers = entry.team.members.filter((m) => m.status !== "stopped");
|
|
170
|
+
if (activeMembers.length >= entry.team.config.maxTeammates) {
|
|
171
|
+
throw new Error(
|
|
172
|
+
`Team "${teamName}" has reached maximum members (${entry.team.config.maxTeammates})`
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
const existing = entry.team.members.find((m) => m.id === teammate.id);
|
|
176
|
+
if (existing) {
|
|
177
|
+
Object.assign(existing, teammate, { lastActivity: Date.now() });
|
|
178
|
+
return existing;
|
|
179
|
+
}
|
|
54
180
|
const fullTeammate = {
|
|
55
181
|
...teammate,
|
|
56
182
|
lastActivity: Date.now()
|
|
@@ -61,11 +187,8 @@ function addTeammate(teamName, teammate) {
|
|
|
61
187
|
message: `Teammate "${teammate.id}" (${teammate.agentType}) joined team "${teamName}".`
|
|
62
188
|
});
|
|
63
189
|
const teamDir = join(getTeamsDir(), teamName);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
JSON.stringify(entry.team, null, 2),
|
|
67
|
-
"utf-8"
|
|
68
|
-
);
|
|
190
|
+
persistTeam(teamDir, entry.team);
|
|
191
|
+
teamEvents.emitTeamChange({ teamName, event: "member_added" });
|
|
69
192
|
return fullTeammate;
|
|
70
193
|
}
|
|
71
194
|
function updateTeammateStatus(teamName, teammateId, status, currentTaskId) {
|
|
@@ -73,11 +196,40 @@ function updateTeammateStatus(teamName, teammateId, status, currentTaskId) {
|
|
|
73
196
|
if (!entry) return;
|
|
74
197
|
const member = entry.team.members.find((m) => m.id === teammateId);
|
|
75
198
|
if (!member) return;
|
|
199
|
+
const previousStatus = member.status;
|
|
76
200
|
member.status = status;
|
|
77
201
|
member.lastActivity = Date.now();
|
|
78
202
|
if (currentTaskId !== void 0) {
|
|
79
203
|
member.currentTaskId = currentTaskId;
|
|
80
204
|
}
|
|
205
|
+
teamEvents.emitMemberStatusChange({
|
|
206
|
+
teamName,
|
|
207
|
+
memberId: teammateId,
|
|
208
|
+
memberName: member.name,
|
|
209
|
+
status,
|
|
210
|
+
previousStatus,
|
|
211
|
+
currentTaskId
|
|
212
|
+
});
|
|
213
|
+
const significantTransitions = /* @__PURE__ */ new Set([
|
|
214
|
+
"idle",
|
|
215
|
+
"working",
|
|
216
|
+
"stopped",
|
|
217
|
+
"completed",
|
|
218
|
+
"failed"
|
|
219
|
+
]);
|
|
220
|
+
if (previousStatus !== status && significantTransitions.has(status)) {
|
|
221
|
+
const teamDir = join(getTeamsDir(), teamName);
|
|
222
|
+
persistTeam(teamDir, entry.team);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function updateTeammateWorktree(teamName, teammateId, worktreePath) {
|
|
226
|
+
const entry = activeTeams.get(teamName);
|
|
227
|
+
if (!entry) return;
|
|
228
|
+
const member = entry.team.members.find((m) => m.id === teammateId);
|
|
229
|
+
if (!member) return;
|
|
230
|
+
member.worktreePath = worktreePath;
|
|
231
|
+
const teamDir = join(getTeamsDir(), teamName);
|
|
232
|
+
persistTeam(teamDir, entry.team);
|
|
81
233
|
}
|
|
82
234
|
function getTeam(teamName) {
|
|
83
235
|
return activeTeams.get(teamName);
|
|
@@ -88,29 +240,84 @@ function getActiveTeams() {
|
|
|
88
240
|
function disbandTeam(teamName) {
|
|
89
241
|
const entry = activeTeams.get(teamName);
|
|
90
242
|
if (!entry) return;
|
|
243
|
+
entry.mailbox.stopAllWatchers();
|
|
244
|
+
abortTeamAgents(teamName);
|
|
91
245
|
for (const member of entry.team.members) {
|
|
92
246
|
member.status = "stopped";
|
|
247
|
+
member.isActive = false;
|
|
93
248
|
}
|
|
94
249
|
const teamDir = join(getTeamsDir(), teamName);
|
|
95
250
|
if (existsSync(teamDir)) {
|
|
96
|
-
|
|
97
|
-
join(teamDir, "team.json"),
|
|
98
|
-
JSON.stringify(entry.team, null, 2),
|
|
99
|
-
"utf-8"
|
|
100
|
-
);
|
|
251
|
+
persistTeam(teamDir, entry.team);
|
|
101
252
|
}
|
|
102
253
|
activeTeams.delete(teamName);
|
|
254
|
+
teamEvents.emitTeamChange({ teamName, event: "disbanded" });
|
|
103
255
|
emitReminderEvent("team:shutdown", {
|
|
104
256
|
teamId: teamName,
|
|
105
257
|
reason: "disbanded"
|
|
106
258
|
});
|
|
107
259
|
}
|
|
108
260
|
function loadTeam(teamName) {
|
|
109
|
-
const
|
|
110
|
-
|
|
261
|
+
const teamDir = join(getTeamsDir(), teamName);
|
|
262
|
+
const configFile = join(teamDir, "config.json");
|
|
263
|
+
const legacyFile = join(teamDir, "team.json");
|
|
264
|
+
if (!existsSync(configFile) && existsSync(legacyFile)) {
|
|
265
|
+
try {
|
|
266
|
+
const legacyContent = readFileSync(legacyFile, "utf-8");
|
|
267
|
+
const legacyTeam = JSON.parse(legacyContent);
|
|
268
|
+
persistTeam(teamDir, legacyTeam);
|
|
269
|
+
try {
|
|
270
|
+
unlinkSync(legacyFile);
|
|
271
|
+
} catch {
|
|
272
|
+
}
|
|
273
|
+
} catch {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (!existsSync(configFile)) return null;
|
|
111
278
|
try {
|
|
112
|
-
const content = readFileSync(
|
|
113
|
-
const
|
|
279
|
+
const content = readFileSync(configFile, "utf-8");
|
|
280
|
+
const rawData = JSON.parse(content);
|
|
281
|
+
const parsed = TeamConfigFileSchema.safeParse(rawData);
|
|
282
|
+
if (!parsed.success) {
|
|
283
|
+
debug.warn("TEAM_CONFIG_VALIDATION_FAILED", {
|
|
284
|
+
teamName,
|
|
285
|
+
error: parsed.error.message
|
|
286
|
+
});
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
const configData = parsed.data;
|
|
290
|
+
const team = {
|
|
291
|
+
name: configData.name,
|
|
292
|
+
config: {
|
|
293
|
+
name: configData.name,
|
|
294
|
+
displayMode: configData.displayMode || "auto",
|
|
295
|
+
maxTeammates: configData.maxTeammates || 10,
|
|
296
|
+
description: configData.description || ""
|
|
297
|
+
},
|
|
298
|
+
members: (configData.members || []).map((m) => ({
|
|
299
|
+
id: m.agentId,
|
|
300
|
+
name: m.name,
|
|
301
|
+
agentType: m.agentType,
|
|
302
|
+
status: m.status || "idle",
|
|
303
|
+
prompt: m.prompt || "",
|
|
304
|
+
currentTaskId: m.currentTaskId || void 0,
|
|
305
|
+
lastActivity: m.lastActivity || m.joinedAt,
|
|
306
|
+
color: m.color || void 0,
|
|
307
|
+
joinedAt: m.joinedAt,
|
|
308
|
+
backendType: m.backendType || "in-process",
|
|
309
|
+
tmuxPaneId: m.tmuxPaneId || void 0,
|
|
310
|
+
cwd: m.cwd || process.cwd(),
|
|
311
|
+
subscriptions: m.subscriptions || [],
|
|
312
|
+
worktreePath: m.worktreePath || void 0,
|
|
313
|
+
planModeRequired: m.planModeRequired || false,
|
|
314
|
+
isActive: m.isActive !== false,
|
|
315
|
+
mode: m.mode || void 0,
|
|
316
|
+
parentSessionId: m.parentSessionId || void 0
|
|
317
|
+
})),
|
|
318
|
+
createdAt: configData.createdAt,
|
|
319
|
+
leadSessionId: configData.leadSessionId || ""
|
|
320
|
+
};
|
|
114
321
|
const mailbox = new Mailbox(teamName);
|
|
115
322
|
const taskStore = new TeamTaskStore(teamName);
|
|
116
323
|
mailbox.load();
|
|
@@ -121,29 +328,39 @@ function loadTeam(teamName) {
|
|
|
121
328
|
return null;
|
|
122
329
|
}
|
|
123
330
|
}
|
|
124
|
-
function resolveDisplayMode(mode) {
|
|
125
|
-
if (mode === "tmux") return "tmux";
|
|
331
|
+
async function resolveDisplayMode(mode) {
|
|
126
332
|
if (mode === "in-process") return "in-process";
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
333
|
+
if (mode === "tmux") return "tmux";
|
|
334
|
+
if (mode === "aiter") return "aiter";
|
|
335
|
+
if (process.env.TMUX || process.env.TERM_PROGRAM === "iTerm.app") {
|
|
336
|
+
return "tmux";
|
|
337
|
+
}
|
|
338
|
+
return "in-process";
|
|
339
|
+
}
|
|
340
|
+
function disbandAllTeams() {
|
|
341
|
+
const teamNames = Array.from(activeTeams.keys());
|
|
342
|
+
for (const name of teamNames) {
|
|
343
|
+
try {
|
|
344
|
+
disbandTeam(name);
|
|
345
|
+
} catch (error) {
|
|
346
|
+
debug.warn("TEAM_DISBAND_CLEANUP_FAILED", { teamName: name, error });
|
|
132
347
|
}
|
|
133
|
-
return "in-process";
|
|
134
|
-
} catch {
|
|
135
|
-
return "in-process";
|
|
136
348
|
}
|
|
137
349
|
}
|
|
138
350
|
export {
|
|
139
351
|
addTeammate,
|
|
140
352
|
createTeam,
|
|
353
|
+
disbandAllTeams,
|
|
141
354
|
disbandTeam,
|
|
142
355
|
getActiveTeams,
|
|
143
356
|
getTeam,
|
|
144
357
|
isAgentTeamsEnabled,
|
|
145
358
|
loadTeam,
|
|
359
|
+
registerAgentAbortController,
|
|
146
360
|
resolveDisplayMode,
|
|
147
|
-
|
|
361
|
+
sanitizeTeamName,
|
|
362
|
+
unregisterAgentAbortController,
|
|
363
|
+
updateTeammateStatus,
|
|
364
|
+
updateTeammateWorktree
|
|
148
365
|
};
|
|
149
366
|
//# sourceMappingURL=teamManager.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/services/agentTeams/teamManager.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Team Manager\n *\n * Central coordinator for agent teams lifecycle.\n * Manages team creation, teammate spawning, and disbanding.\n *\n * Experimental: Enable with MINTO_EXPERIMENTAL_AGENT_TEAMS=1\n */\n\nimport { existsSync, mkdirSync, writeFileSync, readFileSync, rmSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport type {\n Team,\n TeamConfig,\n Teammate,\n TeamDisplayMode,\n} from '../../types/agentTeams'\nimport { Mailbox } from './mailbox'\nimport { TeamTaskStore } from './teamTaskStore'\nimport { emitReminderEvent } from '../systemReminder'\n\n/**\n * Check if Agent Teams feature is enabled\n */\nexport function isAgentTeamsEnabled(): boolean {\n return process.env.MINTO_EXPERIMENTAL_AGENT_TEAMS === '1'\n}\n\n/**\n * Active teams registry\n */\nconst activeTeams = new Map<\n string,\n {\n team: Team\n mailbox: Mailbox\n taskStore: TeamTaskStore\n }\n>()\n\n/**\n * Get the teams storage directory\n */\nfunction getTeamsDir(): string {\n return join(homedir(), '.minto', 'teams')\n}\n\n/**\n * Create a new team\n */\nexport function createTeam(config: TeamConfig): Team {\n if (!isAgentTeamsEnabled()) {\n throw new Error(\n 'Agent Teams is experimental. Set MINTO_EXPERIMENTAL_AGENT_TEAMS=1 to enable.',\n )\n }\n\n if (activeTeams.has(config.name)) {\n throw new Error(`Team \"${config.name}\" already exists`)\n }\n\n const team: Team = {\n name: config.name,\n config,\n members: [],\n createdAt: Date.now(),\n }\n\n const mailbox = new Mailbox(config.name)\n const taskStore = new TeamTaskStore(config.name)\n taskStore.load()\n mailbox.load()\n\n // Persist team config\n const teamDir = join(getTeamsDir(), config.name)\n if (!existsSync(teamDir)) {\n mkdirSync(teamDir, { recursive: true })\n }\n writeFileSync(\n join(teamDir, 'team.json'),\n JSON.stringify(team, null, 2),\n 'utf-8',\n )\n\n activeTeams.set(config.name, { team, mailbox, taskStore })\n\n emitReminderEvent('team:coordination', {\n teamId: config.name,\n message: `Team \"${config.name}\" created (max ${config.maxTeammates} teammates).`,\n })\n\n return team\n}\n\n/**\n * Add a teammate to a team\n */\nexport function addTeammate(\n teamName: string,\n teammate: Omit<Teammate, 'lastActivity'>,\n): Teammate {\n const entry = activeTeams.get(teamName)\n if (!entry) {\n throw new Error(`Team \"${teamName}\" not found`)\n }\n\n const fullTeammate: Teammate = {\n ...teammate,\n lastActivity: Date.now(),\n }\n\n entry.team.members.push(fullTeammate)\n\n emitReminderEvent('team:coordination', {\n teamId: teamName,\n message: `Teammate \"${teammate.id}\" (${teammate.agentType}) joined team \"${teamName}\".`,\n })\n\n // Persist\n const teamDir = join(getTeamsDir(), teamName)\n writeFileSync(\n join(teamDir, 'team.json'),\n JSON.stringify(entry.team, null, 2),\n 'utf-8',\n )\n\n return fullTeammate\n}\n\n/**\n * Update teammate status\n */\nexport function updateTeammateStatus(\n teamName: string,\n teammateId: string,\n status: Teammate['status'],\n currentTaskId?: string,\n): void {\n const entry = activeTeams.get(teamName)\n if (!entry) return\n\n const member = entry.team.members.find(m => m.id === teammateId)\n if (!member) return\n\n member.status = status\n member.lastActivity = Date.now()\n if (currentTaskId !== undefined) {\n member.currentTaskId = currentTaskId\n }\n}\n\n/**\n * Get a team by name\n */\nexport function getTeam(\n teamName: string,\n): { team: Team; mailbox: Mailbox; taskStore: TeamTaskStore } | undefined {\n return activeTeams.get(teamName)\n}\n\n/**\n * Get all active teams\n */\nexport function getActiveTeams(): Team[] {\n return Array.from(activeTeams.values()).map(e => e.team)\n}\n\n/**\n * Disband a team\n */\nexport function disbandTeam(teamName: string): void {\n const entry = activeTeams.get(teamName)\n if (!entry) return\n\n // Mark all members as stopped\n for (const member of entry.team.members) {\n member.status = 'stopped'\n }\n\n // Persist final state\n const teamDir = join(getTeamsDir(), teamName)\n if (existsSync(teamDir)) {\n writeFileSync(\n join(teamDir, 'team.json'),\n JSON.stringify(entry.team, null, 2),\n 'utf-8',\n )\n }\n\n activeTeams.delete(teamName)\n\n emitReminderEvent('team:shutdown', {\n teamId: teamName,\n reason: 'disbanded',\n })\n}\n\n/**\n * Load a persisted team from disk\n */\nexport function loadTeam(teamName: string): Team | null {\n const teamFile = join(getTeamsDir(), teamName, 'team.json')\n if (!existsSync(teamFile)) return null\n\n try {\n const content = readFileSync(teamFile, 'utf-8')\n const team = JSON.parse(content) as Team\n\n const mailbox = new Mailbox(teamName)\n const taskStore = new TeamTaskStore(teamName)\n mailbox.load()\n taskStore.load()\n\n activeTeams.set(teamName, { team, mailbox, taskStore })\n return team\n } catch {\n return null\n }\n}\n\n/**\n * Resolve display mode based on config and environment\n */\nexport function resolveDisplayMode(\n mode: TeamDisplayMode,\n): 'in-process' | 'tmux' {\n if (mode === 'tmux') return 'tmux'\n if (mode === 'in-process') return 'in-process'\n\n // Auto: check if tmux is available\n try {\n const { execSync } = require('child_process')\n execSync('which tmux', { stdio: 'pipe' })\n // tmux available, check if we're already in a tmux session\n if (process.env.TMUX) {\n return 'tmux'\n }\n return 'in-process' // Default to in-process even if tmux available\n } catch {\n return 'in-process'\n }\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * Team Manager\n *\n * Central coordinator for agent teams lifecycle.\n * Manages team creation, teammate spawning, and disbanding.\n *\n * Enabled by default. Disable with MINTO_EXPERIMENTAL_AGENT_TEAMS=0\n * or set enableAgentTeams: false in global config.\n */\n\nimport {\n existsSync,\n mkdirSync,\n writeFileSync,\n readFileSync,\n rmSync,\n unlinkSync,\n} from 'fs'\nimport { randomUUID } from 'crypto'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { z } from 'zod'\nimport type {\n Team,\n TeamConfig,\n Teammate,\n TeamDisplayMode,\n} from '../../types/agentTeams'\nimport { Mailbox } from './mailbox'\nimport { TeamTaskStore } from './teamTaskStore'\nimport { emitReminderEvent } from '../systemReminder'\nimport { teamEvents } from './teamEvents'\nimport { debug } from '../../utils/debugLogger'\n\n/** Zod schema for team config.json \u2014 used to validate JSON parsed from disk */\nconst TeamConfigFileSchema = z.object({\n name: z.string(),\n description: z.string().optional().default(''),\n createdAt: z.number(),\n leadAgentId: z.string().optional(),\n leadSessionId: z.string().optional().default(''),\n displayMode: z.string().optional().default('auto'),\n maxTeammates: z.number().optional().default(10),\n members: z\n .array(\n z.object({\n agentId: z.string(),\n name: z.string(),\n agentType: z.string(),\n color: z.string().nullable().optional(),\n joinedAt: z.number().optional(),\n tmuxPaneId: z.string().optional(),\n cwd: z.string().optional(),\n subscriptions: z.array(z.string()).optional(),\n backendType: z.string().optional(),\n worktreePath: z.string().nullable().optional(),\n planModeRequired: z.boolean().optional(),\n isActive: z.boolean().optional(),\n mode: z.string().nullable().optional(),\n status: z.string().optional(),\n prompt: z.string().optional(),\n currentTaskId: z.string().nullable().optional(),\n lastActivity: z.number().nullable().optional(),\n parentSessionId: z.string().nullable().optional(),\n }),\n )\n .optional()\n .default([]),\n})\n\nexport function sanitizeTeamName(name: string): string {\n return name.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase()\n}\n\n/**\n * Check if Agent Teams feature is enabled\n *\n * Enabled by default. Can be explicitly disabled via:\n * 1. GlobalConfig.enableAgentTeams === false\n * 2. MINTO_EXPERIMENTAL_AGENT_TEAMS=0 env var\n */\nexport function isAgentTeamsEnabled(): boolean {\n // Explicit disable takes highest priority (Minto > CC fallback)\n if (process.env.MINTO_EXPERIMENTAL_AGENT_TEAMS === '0') return false\n if (process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === '0') return false\n\n // Explicit enable (CC compat: CC uses =1 opt-in, Minto defaults to enabled)\n if (process.env.MINTO_EXPERIMENTAL_AGENT_TEAMS === '1') return true\n if (process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === '1') return true\n\n // Check config flag (lazy require to avoid circular deps at module load time)\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const { getGlobalConfig } =\n require('../../utils/config') as typeof import('../../utils/config')\n const config = getGlobalConfig()\n if (config.enableAgentTeams === false) return false\n if (config.enableAgentTeams === true) return true\n } catch {\n // Config not available yet \u2014 default to enabled\n }\n\n // Default: enabled (Minto behavior, differs from CC which defaults to disabled)\n return true\n}\n\n/**\n * Active teams registry\n */\nconst activeTeams = new Map<\n string,\n {\n team: Team\n mailbox: Mailbox\n taskStore: TeamTaskStore\n }\n>()\n\n/**\n * Track AbortControllers for running agent tasks.\n * Key: `${teamName}:${agentId}`, Value: AbortController\n * Used to abort agent query loops when team is disbanded or interrupted.\n */\nconst agentAbortControllers = new Map<string, AbortController>()\n\n/**\n * Register an AbortController for a running agent task.\n * Called by TaskTool when starting an in-process agent query loop.\n */\nexport function registerAgentAbortController(\n teamName: string,\n agentId: string,\n controller: AbortController,\n): void {\n agentAbortControllers.set(`${teamName}:${agentId}`, controller)\n}\n\n/**\n * Unregister an agent's AbortController (e.g., when the agent completes).\n */\nexport function unregisterAgentAbortController(\n teamName: string,\n agentId: string,\n): void {\n agentAbortControllers.delete(`${teamName}:${agentId}`)\n}\n\n/**\n * Abort all running agents for a given team.\n */\nfunction abortTeamAgents(teamName: string): void {\n for (const [key, controller] of agentAbortControllers) {\n if (key.startsWith(`${teamName}:`)) {\n try {\n controller.abort()\n } catch {\n // Ignore abort errors\n }\n agentAbortControllers.delete(key)\n }\n }\n}\n\n/**\n * Get the teams storage directory\n */\nfunction getTeamsDir(): string {\n return join(homedir(), '.minto', 'teams')\n}\n\n/**\n * Persist team state to config.json (single source of truth).\n *\n * CC-compatible flat format with Minto extensions for full team state.\n * Replaces the previous dual-file (team.json + config.json) approach.\n */\nfunction persistTeam(teamDir: string, team: Team): void {\n try {\n const configData = {\n name: team.name,\n description: team.config.description || '',\n createdAt: team.createdAt,\n leadAgentId: `team-lead@${team.name}`,\n leadSessionId: team.leadSessionId || '',\n // Minto extensions\n displayMode: team.config.displayMode || 'auto',\n maxTeammates: team.config.maxTeammates || 10,\n members: team.members.map(m => ({\n // CC-compatible fields\n agentId: m.id,\n name: m.name,\n agentType: m.agentType,\n color: m.color || null,\n joinedAt: m.joinedAt || m.lastActivity,\n tmuxPaneId:\n m.tmuxPaneId ||\n (m.backendType === 'in-process' ? 'in-process' : 'unknown'),\n cwd: m.cwd || process.cwd(),\n subscriptions: m.subscriptions || [],\n backendType: m.backendType || 'in-process',\n worktreePath: m.worktreePath || null,\n planModeRequired: m.planModeRequired || false,\n isActive: m.isActive !== false,\n mode: m.mode || null,\n // Minto extension fields\n status: m.status || 'idle',\n prompt: m.prompt || '',\n currentTaskId: m.currentTaskId || null,\n lastActivity: m.lastActivity || null,\n parentSessionId: m.parentSessionId || null,\n })),\n }\n writeFileSync(\n join(teamDir, 'config.json'),\n JSON.stringify(configData, null, 2),\n 'utf-8',\n )\n } catch (error) {\n debug.warn('TEAM_PERSIST_CONFIG_FAILED', { error })\n }\n}\n\n/**\n * Create a new team\n */\nexport function createTeam(config: TeamConfig): Team {\n if (!isAgentTeamsEnabled()) {\n throw new Error(\n 'Agent Teams is disabled. Remove enableAgentTeams: false from config or unset MINTO_EXPERIMENTAL_AGENT_TEAMS=0 to re-enable.',\n )\n }\n\n config = { ...config, name: sanitizeTeamName(config.name) }\n\n if (activeTeams.has(config.name)) {\n throw new Error(`Team \"${config.name}\" already exists`)\n }\n\n const team: Team = {\n name: config.name,\n config,\n members: [],\n createdAt: Date.now(),\n leadSessionId: randomUUID(),\n }\n\n const mailbox = new Mailbox(config.name)\n const taskStore = new TeamTaskStore(config.name)\n taskStore.load()\n mailbox.load()\n\n // Persist team state to config.json\n const teamDir = join(getTeamsDir(), config.name)\n if (!existsSync(teamDir)) {\n mkdirSync(teamDir, { recursive: true })\n }\n persistTeam(teamDir, team)\n\n activeTeams.set(config.name, { team, mailbox, taskStore })\n\n teamEvents.emitTeamChange({ teamName: config.name, event: 'created' })\n\n emitReminderEvent('team:coordination', {\n teamId: config.name,\n message: `Team \"${config.name}\" created (max ${config.maxTeammates} teammates).`,\n })\n\n return team\n}\n\n/**\n * Add a teammate to a team\n */\nexport function addTeammate(\n teamName: string,\n teammate: Omit<Teammate, 'lastActivity'>,\n): Teammate {\n const entry = activeTeams.get(teamName)\n if (!entry) {\n throw new Error(`Team \"${teamName}\" not found`)\n }\n\n // Enforce maxTeammates limit (count only non-stopped members)\n const activeMembers = entry.team.members.filter(m => m.status !== 'stopped')\n if (activeMembers.length >= entry.team.config.maxTeammates) {\n throw new Error(\n `Team \"${teamName}\" has reached maximum members (${entry.team.config.maxTeammates})`,\n )\n }\n\n // Guard against duplicate member IDs (e.g., retry or re-spawn)\n const existing = entry.team.members.find(m => m.id === teammate.id)\n if (existing) {\n Object.assign(existing, teammate, { lastActivity: Date.now() })\n return existing\n }\n\n const fullTeammate: Teammate = {\n ...teammate,\n lastActivity: Date.now(),\n }\n\n entry.team.members.push(fullTeammate)\n\n emitReminderEvent('team:coordination', {\n teamId: teamName,\n message: `Teammate \"${teammate.id}\" (${teammate.agentType}) joined team \"${teamName}\".`,\n })\n\n // Persist\n const teamDir = join(getTeamsDir(), teamName)\n persistTeam(teamDir, entry.team)\n\n teamEvents.emitTeamChange({ teamName, event: 'member_added' })\n\n return fullTeammate\n}\n\n/**\n * Update teammate status\n */\nexport function updateTeammateStatus(\n teamName: string,\n teammateId: string,\n status: Teammate['status'],\n currentTaskId?: string,\n): void {\n const entry = activeTeams.get(teamName)\n if (!entry) return\n\n const member = entry.team.members.find(m => m.id === teammateId)\n if (!member) return\n\n const previousStatus = member.status\n member.status = status\n member.lastActivity = Date.now()\n if (currentTaskId !== undefined) {\n member.currentTaskId = currentTaskId\n }\n\n teamEvents.emitMemberStatusChange({\n teamName,\n memberId: teammateId,\n memberName: member.name,\n status,\n previousStatus,\n currentTaskId,\n })\n\n // Persist to disk for significant state transitions\n const significantTransitions = new Set([\n 'idle',\n 'working',\n 'stopped',\n 'completed',\n 'failed',\n ])\n if (previousStatus !== status && significantTransitions.has(status)) {\n const teamDir = join(getTeamsDir(), teamName)\n persistTeam(teamDir, entry.team)\n }\n}\n\n/**\n * Update a teammate's worktree path and persist to disk.\n * Called after creating a git worktree for a teammate agent.\n */\nexport function updateTeammateWorktree(\n teamName: string,\n teammateId: string,\n worktreePath: string,\n): void {\n const entry = activeTeams.get(teamName)\n if (!entry) return\n const member = entry.team.members.find(m => m.id === teammateId)\n if (!member) return\n member.worktreePath = worktreePath\n // Persist\n const teamDir = join(getTeamsDir(), teamName)\n persistTeam(teamDir, entry.team)\n}\n\n/**\n * Get a team by name\n */\nexport function getTeam(\n teamName: string,\n): { team: Team; mailbox: Mailbox; taskStore: TeamTaskStore } | undefined {\n return activeTeams.get(teamName)\n}\n\n/**\n * Get all active teams\n */\nexport function getActiveTeams(): Team[] {\n return Array.from(activeTeams.values()).map(e => e.team)\n}\n\n/**\n * Disband a team \u2014 aborts all running agents, marks members stopped, cleans up.\n */\nexport function disbandTeam(teamName: string): void {\n const entry = activeTeams.get(teamName)\n if (!entry) return\n\n // Clean up mailbox file watchers before aborting agents\n entry.mailbox.stopAllWatchers()\n\n // Abort all running agent query loops for this team\n abortTeamAgents(teamName)\n\n // Mark all members as stopped\n for (const member of entry.team.members) {\n member.status = 'stopped'\n member.isActive = false\n }\n\n // Persist final state\n const teamDir = join(getTeamsDir(), teamName)\n if (existsSync(teamDir)) {\n persistTeam(teamDir, entry.team)\n }\n\n // Delete from active teams BEFORE emitting the event.\n // Listeners (e.g. useTeamMembers) call getActiveTeams() in their handler,\n // so the team must already be removed to avoid stale data.\n activeTeams.delete(teamName)\n\n teamEvents.emitTeamChange({ teamName, event: 'disbanded' })\n\n emitReminderEvent('team:shutdown', {\n teamId: teamName,\n reason: 'disbanded',\n })\n}\n\n/**\n * Load a persisted team from disk.\n *\n * Reads from config.json (single source of truth).\n * One-time migration: if only team.json exists, migrates to config.json.\n */\nexport function loadTeam(teamName: string): Team | null {\n const teamDir = join(getTeamsDir(), teamName)\n const configFile = join(teamDir, 'config.json')\n const legacyFile = join(teamDir, 'team.json')\n\n // Backward-compat migration: team.json \u2192 config.json\n if (!existsSync(configFile) && existsSync(legacyFile)) {\n try {\n const legacyContent = readFileSync(legacyFile, 'utf-8')\n // Legacy format: best-effort parse, no strict validation\n const legacyTeam = JSON.parse(legacyContent) as Team\n persistTeam(teamDir, legacyTeam)\n // Remove legacy file after successful migration\n try {\n unlinkSync(legacyFile)\n } catch {\n /* best-effort */\n }\n } catch {\n return null\n }\n }\n\n if (!existsSync(configFile)) return null\n\n try {\n const content = readFileSync(configFile, 'utf-8')\n const rawData = JSON.parse(content)\n const parsed = TeamConfigFileSchema.safeParse(rawData)\n if (!parsed.success) {\n debug.warn('TEAM_CONFIG_VALIDATION_FAILED', {\n teamName,\n error: parsed.error.message,\n })\n return null\n }\n const configData = parsed.data\n\n // Map config.json back to Team object\n const team: Team = {\n name: configData.name,\n config: {\n name: configData.name,\n displayMode: (configData.displayMode as TeamDisplayMode) || 'auto',\n maxTeammates: configData.maxTeammates || 10,\n description: configData.description || '',\n },\n members: (configData.members || []).map(m => ({\n id: m.agentId,\n name: m.name,\n agentType: m.agentType,\n status: (m.status as Teammate['status']) || 'idle',\n prompt: m.prompt || '',\n currentTaskId: m.currentTaskId || undefined,\n lastActivity: m.lastActivity || m.joinedAt,\n color: m.color || undefined,\n joinedAt: m.joinedAt,\n backendType: (m.backendType as Teammate['backendType']) || 'in-process',\n tmuxPaneId: m.tmuxPaneId || undefined,\n cwd: m.cwd || process.cwd(),\n subscriptions: m.subscriptions || [],\n worktreePath: m.worktreePath || undefined,\n planModeRequired: m.planModeRequired || false,\n isActive: m.isActive !== false,\n mode: m.mode || undefined,\n parentSessionId: m.parentSessionId || undefined,\n })),\n createdAt: configData.createdAt,\n leadSessionId: configData.leadSessionId || '',\n }\n\n const mailbox = new Mailbox(teamName)\n const taskStore = new TeamTaskStore(teamName)\n mailbox.load()\n taskStore.load()\n\n activeTeams.set(teamName, { team, mailbox, taskStore })\n return team\n } catch {\n return null\n }\n}\n\n/**\n * Resolve display mode based on config and environment.\n *\n * Priority for 'auto':\n * 1. tmux/iTerm2 session detected? \u2192 'tmux'\n * 2. 'in-process' (default \u2014 maximum compatibility)\n */\nexport async function resolveDisplayMode(\n mode: TeamDisplayMode,\n): Promise<'in-process' | 'tmux' | 'aiter'> {\n if (mode === 'in-process') return 'in-process'\n if (mode === 'tmux') return 'tmux'\n if (mode === 'aiter') return 'aiter'\n\n // Auto detection:\n // 1. tmux session detected? \u2192 'tmux'\n // 2. Default: in-process for maximum compatibility\n if (process.env.TMUX || process.env.TERM_PROGRAM === 'iTerm.app') {\n return 'tmux'\n }\n\n return 'in-process'\n}\n\n/**\n * Disband ALL active teams. Called during graceful shutdown to ensure\n * all agent query loops are aborted and resources are cleaned up.\n */\nexport function disbandAllTeams(): void {\n const teamNames = Array.from(activeTeams.keys())\n for (const name of teamNames) {\n try {\n disbandTeam(name)\n } catch (error) {\n debug.warn('TEAM_DISBAND_CLEANUP_FAILED', { teamName: name, error })\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|