156 lines
4.1 KiB
TypeScript
156 lines
4.1 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
import { rmSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { createPaneBackendExecutor } from '../PaneBackendExecutor'
|
|
import type { PaneBackend } from '../types'
|
|
|
|
let tempHome: string
|
|
let previousConfigDir: string | undefined
|
|
|
|
beforeEach(() => {
|
|
previousConfigDir = process.env.CLAUDE_CONFIG_DIR
|
|
tempHome = join(
|
|
tmpdir(),
|
|
`pane-backend-executor-${Date.now()}-${Math.random().toString(16).slice(2)}`,
|
|
)
|
|
process.env.CLAUDE_CONFIG_DIR = tempHome
|
|
})
|
|
|
|
afterEach(() => {
|
|
if (previousConfigDir === undefined) {
|
|
delete process.env.CLAUDE_CONFIG_DIR
|
|
} else {
|
|
process.env.CLAUDE_CONFIG_DIR = previousConfigDir
|
|
}
|
|
rmSync(tempHome, { recursive: true, force: true })
|
|
})
|
|
|
|
describe('PaneBackendExecutor', () => {
|
|
test('spawns process teammates with agent type and inherited auto permission mode', async () => {
|
|
let sentCommand = ''
|
|
const backend: PaneBackend = {
|
|
type: 'tmux',
|
|
displayName: 'tmux',
|
|
supportsHideShow: true,
|
|
async isAvailable() {
|
|
return true
|
|
},
|
|
async isRunningInside() {
|
|
return false
|
|
},
|
|
async createTeammatePaneInSwarmView() {
|
|
return { paneId: '%1', isFirstTeammate: false }
|
|
},
|
|
async sendCommandToPane(_paneId, command) {
|
|
sentCommand = command
|
|
},
|
|
async setPaneBorderColor() {},
|
|
async setPaneTitle() {},
|
|
async enablePaneBorderStatus() {},
|
|
async rebalancePanes() {},
|
|
async killPane() {
|
|
return true
|
|
},
|
|
async hidePane() {
|
|
return true
|
|
},
|
|
async showPane() {
|
|
return true
|
|
},
|
|
}
|
|
|
|
const executor = createPaneBackendExecutor(backend)
|
|
executor.setContext({
|
|
getAppState: () => ({
|
|
toolPermissionContext: {
|
|
mode: 'auto',
|
|
},
|
|
}),
|
|
} as any)
|
|
|
|
const result = await executor.spawn({
|
|
name: 'reviewer',
|
|
teamName: 'alpha',
|
|
prompt: 'review the change',
|
|
cwd: tempHome,
|
|
parentSessionId: 'parent-session',
|
|
agentType: 'code-reviewer',
|
|
planModeRequired: false,
|
|
})
|
|
|
|
expect(result.success).toBe(true)
|
|
expect(result.backendType).toBe('tmux')
|
|
expect(result.paneId).toBe('%1')
|
|
expect(sentCommand).toContain('--agent-type code-reviewer')
|
|
expect(sentCommand).toContain('--permission-mode auto')
|
|
})
|
|
|
|
test('preserves legacy separate-window spawning when useSplitPane is false', async () => {
|
|
let paneSpawned = false
|
|
let windowSpawned = false
|
|
const backend: PaneBackend = {
|
|
type: 'tmux',
|
|
displayName: 'tmux',
|
|
supportsHideShow: true,
|
|
async isAvailable() {
|
|
return true
|
|
},
|
|
async isRunningInside() {
|
|
return false
|
|
},
|
|
async createTeammatePaneInSwarmView() {
|
|
paneSpawned = true
|
|
return { paneId: '%pane', isFirstTeammate: false }
|
|
},
|
|
async createTeammateWindowInSwarmView() {
|
|
windowSpawned = true
|
|
return {
|
|
paneId: '%window',
|
|
windowName: 'teammate-worker',
|
|
isFirstTeammate: false,
|
|
}
|
|
},
|
|
async sendCommandToPane() {},
|
|
async setPaneBorderColor() {},
|
|
async setPaneTitle() {},
|
|
async enablePaneBorderStatus() {},
|
|
async rebalancePanes() {},
|
|
async killPane() {
|
|
return true
|
|
},
|
|
async hidePane() {
|
|
return true
|
|
},
|
|
async showPane() {
|
|
return true
|
|
},
|
|
}
|
|
|
|
const executor = createPaneBackendExecutor(backend)
|
|
executor.setContext({
|
|
getAppState: () => ({
|
|
toolPermissionContext: {
|
|
mode: 'default',
|
|
},
|
|
}),
|
|
} as any)
|
|
|
|
const result = await executor.spawn({
|
|
name: 'worker',
|
|
teamName: 'alpha',
|
|
prompt: 'do work',
|
|
cwd: tempHome,
|
|
parentSessionId: 'parent-session',
|
|
useSplitPane: false,
|
|
})
|
|
|
|
expect(result.success).toBe(true)
|
|
expect(paneSpawned).toBe(false)
|
|
expect(windowSpawned).toBe(true)
|
|
expect(result.paneId).toBe('%window')
|
|
expect(result.windowName).toBe('teammate-worker')
|
|
expect(result.isSplitPane).toBe(false)
|
|
})
|
|
})
|