* Handle spawn operation using separate windows (legacy behavior). * Creates each teammate in its own tmux window.
( input: SpawnInput, context: ToolUseContext, )
| 543 | * Creates each teammate in its own tmux window. |
| 544 | */ |
| 545 | async function handleSpawnSeparateWindow( |
| 546 | input: SpawnInput, |
| 547 | context: ToolUseContext, |
| 548 | ): Promise<{ data: SpawnOutput }> { |
| 549 | const { setAppState, getAppState } = context |
| 550 | const { name, prompt, agent_type, cwd, plan_mode_required } = input |
| 551 | |
| 552 | // Resolve model: 'inherit' → leader's model; undefined → default Opus |
| 553 | const model = resolveTeammateModel(input.model, getAppState().mainLoopModel) |
| 554 | |
| 555 | if (!name || !prompt) { |
| 556 | throw new Error('name and prompt are required for spawn operation') |
| 557 | } |
| 558 | |
| 559 | // Get team name from input or inherit from leader's team context |
| 560 | const appState = getAppState() |
| 561 | const teamName = input.team_name || appState.teamContext?.teamName |
| 562 | |
| 563 | if (!teamName) { |
| 564 | throw new Error( |
| 565 | 'team_name is required for spawn operation. Either provide team_name in input or call spawnTeam first to establish team context.', |
| 566 | ) |
| 567 | } |
| 568 | |
| 569 | // Generate unique name if duplicate exists in team |
| 570 | const uniqueName = await generateUniqueTeammateName(name, teamName) |
| 571 | |
| 572 | // Sanitize the name to prevent @ in agent IDs (would break agentName@teamName format) |
| 573 | const sanitizedName = sanitizeAgentName(uniqueName) |
| 574 | |
| 575 | // Generate deterministic agent ID from name and team |
| 576 | const teammateId = formatAgentId(sanitizedName, teamName) |
| 577 | const windowName = `teammate-${sanitizeName(sanitizedName)}` |
| 578 | const workingDir = cwd || getCwd() |
| 579 | |
| 580 | // Ensure the swarm session exists |
| 581 | await ensureSession(SWARM_SESSION_NAME) |
| 582 | |
| 583 | // Assign a unique color to this teammate |
| 584 | const teammateColor = assignTeammateColor(teammateId) |
| 585 | |
| 586 | // Create a new window for this teammate |
| 587 | const createWindowResult = await execFileNoThrow(TMUX_COMMAND, [ |
| 588 | 'new-window', |
| 589 | '-t', |
| 590 | SWARM_SESSION_NAME, |
| 591 | '-n', |
| 592 | windowName, |
| 593 | '-P', |
| 594 | '-F', |
| 595 | '#{pane_id}', |
| 596 | ]) |
| 597 | |
| 598 | if (createWindowResult.code !== 0) { |
| 599 | throw new Error( |
| 600 | `Failed to create tmux window: ${createWindowResult.stderr}`, |
| 601 | ) |
| 602 | } |
no test coverage detected