TeamDeleteTool.ts
tools/TeamDeleteTool/TeamDeleteTool.ts
140
Lines
4221
Bytes
3
Exports
15
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is part of the tool layer, which means it describes actions the system can perform for the user or model.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with tool-system. It contains 140 lines, 15 detected imports, and 3 detected exports.
Important relationships
Detected exports
OutputInputTeamDeleteTool
Keywords
teamnameinputschemateamutilsswarmnamememberstoolteam_namedata
Detected imports
zod/v4../../services/analytics/index.js../../services/analytics/metadata.js../../Tool.js../../Tool.js../../utils/agentSwarmsEnabled.js../../utils/lazySchema.js../../utils/slowOperations.js../../utils/swarm/constants.js../../utils/swarm/teamHelpers.js../../utils/swarm/teammateLayoutManager.js../../utils/tasks.js./constants.js./prompt.js./UI.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
import { z } from 'zod/v4'
import { logEvent } from '../../services/analytics/index.js'
import type { AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS } from '../../services/analytics/metadata.js'
import type { Tool } from '../../Tool.js'
import { buildTool, type ToolDef } from '../../Tool.js'
import { isAgentSwarmsEnabled } from '../../utils/agentSwarmsEnabled.js'
import { lazySchema } from '../../utils/lazySchema.js'
import { jsonStringify } from '../../utils/slowOperations.js'
import { TEAM_LEAD_NAME } from '../../utils/swarm/constants.js'
import {
cleanupTeamDirectories,
readTeamFile,
unregisterTeamForSessionCleanup,
} from '../../utils/swarm/teamHelpers.js'
import { clearTeammateColors } from '../../utils/swarm/teammateLayoutManager.js'
import { clearLeaderTeamName } from '../../utils/tasks.js'
import { TEAM_DELETE_TOOL_NAME } from './constants.js'
import { getPrompt } from './prompt.js'
import { renderToolResultMessage, renderToolUseMessage } from './UI.js'
const inputSchema = lazySchema(() => z.strictObject({}))
type InputSchema = ReturnType<typeof inputSchema>
export type Output = {
success: boolean
message: string
team_name?: string
}
export type Input = z.infer<InputSchema>
export const TeamDeleteTool: Tool<InputSchema, Output> = buildTool({
name: TEAM_DELETE_TOOL_NAME,
searchHint: 'disband a swarm team and clean up',
maxResultSizeChars: 100_000,
shouldDefer: true,
userFacingName() {
return ''
},
get inputSchema(): InputSchema {
return inputSchema()
},
isEnabled() {
return isAgentSwarmsEnabled()
},
async description() {
return 'Clean up team and task directories when the swarm is complete'
},
async prompt() {
return getPrompt()
},
mapToolResultToToolResultBlockParam(data, toolUseID) {
return {
tool_use_id: toolUseID,
type: 'tool_result' as const,
content: [
{
type: 'text' as const,
text: jsonStringify(data),
},
],
}
},
async call(_input, context) {
const { setAppState, getAppState } = context
const appState = getAppState()
const teamName = appState.teamContext?.teamName
if (teamName) {
// Read team config to check for active members
const teamFile = readTeamFile(teamName)
if (teamFile) {
// Filter out the team lead - only count non-lead members
const nonLeadMembers = teamFile.members.filter(
m => m.name !== TEAM_LEAD_NAME,
)
// Separate truly active members from idle/dead ones
// Members with isActive === false are idle (finished their turn or crashed)
const activeMembers = nonLeadMembers.filter(m => m.isActive !== false)
if (activeMembers.length > 0) {
const memberNames = activeMembers.map(m => m.name).join(', ')
return {
data: {
success: false,
message: `Cannot cleanup team with ${activeMembers.length} active member(s): ${memberNames}. Use requestShutdown to gracefully terminate teammates first.`,
team_name: teamName,
},
}
}
}
await cleanupTeamDirectories(teamName)
// Already cleaned — don't try again on gracefulShutdown.
unregisterTeamForSessionCleanup(teamName)
// Clear color assignments so new teams start fresh
clearTeammateColors()
// Clear leader team name so getTaskListId() falls back to session ID
clearLeaderTeamName()
logEvent('tengu_team_deleted', {
team_name:
teamName as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
})
}
// Clear team context and inbox from app state
setAppState(prev => ({
...prev,
teamContext: undefined,
inbox: {
messages: [], // Clear any queued messages
},
}))
return {
data: {
success: true,
message: teamName
? `Cleaned up directories and worktrees for team "${teamName}"`
: 'No team name found, nothing to clean up',
team_name: teamName,
},
}
},
renderToolUseMessage,
renderToolResultMessage,
} satisfies ToolDef<InputSchema, Output>)