source dump of claude code
at main 139 lines 4.2 kB view raw
1import { z } from 'zod/v4' 2import { logEvent } from '../../services/analytics/index.js' 3import type { AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS } from '../../services/analytics/metadata.js' 4import type { Tool } from '../../Tool.js' 5import { buildTool, type ToolDef } from '../../Tool.js' 6import { isAgentSwarmsEnabled } from '../../utils/agentSwarmsEnabled.js' 7import { lazySchema } from '../../utils/lazySchema.js' 8import { jsonStringify } from '../../utils/slowOperations.js' 9import { TEAM_LEAD_NAME } from '../../utils/swarm/constants.js' 10import { 11 cleanupTeamDirectories, 12 readTeamFile, 13 unregisterTeamForSessionCleanup, 14} from '../../utils/swarm/teamHelpers.js' 15import { clearTeammateColors } from '../../utils/swarm/teammateLayoutManager.js' 16import { clearLeaderTeamName } from '../../utils/tasks.js' 17import { TEAM_DELETE_TOOL_NAME } from './constants.js' 18import { getPrompt } from './prompt.js' 19import { renderToolResultMessage, renderToolUseMessage } from './UI.js' 20 21const inputSchema = lazySchema(() => z.strictObject({})) 22type InputSchema = ReturnType<typeof inputSchema> 23 24export type Output = { 25 success: boolean 26 message: string 27 team_name?: string 28} 29 30export type Input = z.infer<InputSchema> 31 32export const TeamDeleteTool: Tool<InputSchema, Output> = buildTool({ 33 name: TEAM_DELETE_TOOL_NAME, 34 searchHint: 'disband a swarm team and clean up', 35 maxResultSizeChars: 100_000, 36 shouldDefer: true, 37 38 userFacingName() { 39 return '' 40 }, 41 42 get inputSchema(): InputSchema { 43 return inputSchema() 44 }, 45 46 isEnabled() { 47 return isAgentSwarmsEnabled() 48 }, 49 50 async description() { 51 return 'Clean up team and task directories when the swarm is complete' 52 }, 53 54 async prompt() { 55 return getPrompt() 56 }, 57 58 mapToolResultToToolResultBlockParam(data, toolUseID) { 59 return { 60 tool_use_id: toolUseID, 61 type: 'tool_result' as const, 62 content: [ 63 { 64 type: 'text' as const, 65 text: jsonStringify(data), 66 }, 67 ], 68 } 69 }, 70 71 async call(_input, context) { 72 const { setAppState, getAppState } = context 73 const appState = getAppState() 74 const teamName = appState.teamContext?.teamName 75 76 if (teamName) { 77 // Read team config to check for active members 78 const teamFile = readTeamFile(teamName) 79 if (teamFile) { 80 // Filter out the team lead - only count non-lead members 81 const nonLeadMembers = teamFile.members.filter( 82 m => m.name !== TEAM_LEAD_NAME, 83 ) 84 85 // Separate truly active members from idle/dead ones 86 // Members with isActive === false are idle (finished their turn or crashed) 87 const activeMembers = nonLeadMembers.filter(m => m.isActive !== false) 88 89 if (activeMembers.length > 0) { 90 const memberNames = activeMembers.map(m => m.name).join(', ') 91 return { 92 data: { 93 success: false, 94 message: `Cannot cleanup team with ${activeMembers.length} active member(s): ${memberNames}. Use requestShutdown to gracefully terminate teammates first.`, 95 team_name: teamName, 96 }, 97 } 98 } 99 } 100 101 await cleanupTeamDirectories(teamName) 102 // Already cleaned — don't try again on gracefulShutdown. 103 unregisterTeamForSessionCleanup(teamName) 104 105 // Clear color assignments so new teams start fresh 106 clearTeammateColors() 107 108 // Clear leader team name so getTaskListId() falls back to session ID 109 clearLeaderTeamName() 110 111 logEvent('tengu_team_deleted', { 112 team_name: 113 teamName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 114 }) 115 } 116 117 // Clear team context and inbox from app state 118 setAppState(prev => ({ 119 ...prev, 120 teamContext: undefined, 121 inbox: { 122 messages: [], // Clear any queued messages 123 }, 124 })) 125 126 return { 127 data: { 128 success: true, 129 message: teamName 130 ? `Cleaned up directories and worktrees for team "${teamName}"` 131 : 'No team name found, nothing to clean up', 132 team_name: teamName, 133 }, 134 } 135 }, 136 137 renderToolUseMessage, 138 renderToolResultMessage, 139} satisfies ToolDef<InputSchema, Output>)