teamDiscovery.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /**
  2. * Team Discovery - Utilities for discovering teams and teammate status
  3. *
  4. * Scans ~/.claude/teams/ to find teams where the current session is the leader.
  5. * Used by the Teams UI in the footer to show team status.
  6. */
  7. import { isPaneBackend, type PaneBackendType } from './swarm/backends/types.js'
  8. import { readTeamFile } from './swarm/teamHelpers.js'
  9. export type TeamSummary = {
  10. name: string
  11. memberCount: number
  12. runningCount: number
  13. idleCount: number
  14. }
  15. export type TeammateStatus = {
  16. name: string
  17. agentId: string
  18. agentType?: string
  19. model?: string
  20. prompt?: string
  21. status: 'running' | 'idle' | 'unknown'
  22. color?: string
  23. idleSince?: string // ISO timestamp from idle notification
  24. tmuxPaneId: string
  25. cwd: string
  26. worktreePath?: string
  27. isHidden?: boolean // Whether the pane is currently hidden from the swarm view
  28. backendType?: PaneBackendType // The backend type used for this teammate
  29. mode?: string // Current permission mode for this teammate
  30. }
  31. /**
  32. * Get detailed teammate statuses for a team
  33. * Reads isActive from config to determine status
  34. */
  35. export function getTeammateStatuses(teamName: string): TeammateStatus[] {
  36. const teamFile = readTeamFile(teamName)
  37. if (!teamFile) {
  38. return []
  39. }
  40. const hiddenPaneIds = new Set(teamFile.hiddenPaneIds ?? [])
  41. const statuses: TeammateStatus[] = []
  42. for (const member of teamFile.members) {
  43. // Exclude team-lead from the list
  44. if (member.name === 'team-lead') {
  45. continue
  46. }
  47. // Read isActive from config, defaulting to true (active) if undefined
  48. const isActive = member.isActive !== false
  49. const status: 'running' | 'idle' = isActive ? 'running' : 'idle'
  50. statuses.push({
  51. name: member.name,
  52. agentId: member.agentId,
  53. agentType: member.agentType,
  54. model: member.model,
  55. prompt: member.prompt,
  56. status,
  57. color: member.color,
  58. tmuxPaneId: member.tmuxPaneId,
  59. cwd: member.cwd,
  60. worktreePath: member.worktreePath,
  61. isHidden: hiddenPaneIds.has(member.tmuxPaneId),
  62. backendType:
  63. member.backendType && isPaneBackend(member.backendType)
  64. ? member.backendType
  65. : undefined,
  66. mode: member.mode,
  67. })
  68. }
  69. return statuses
  70. }
  71. // Note: For time formatting, use formatRelativeTimeAgo from '../utils/format.js'