mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 17:37:40 +00:00
144 lines
5.9 KiB
TypeScript
144 lines
5.9 KiB
TypeScript
import { WorktreeCreate } from '../../src/shared/rpc-contract/worktree-create-params'
|
|
import { buildManagedWorktreeCreateArgs } from '../../src/main/runtime/rpc/methods/workspaces/worktree-create-args'
|
|
import { resolveManagedWorktreeCreateStartup } from '../../src/main/runtime/workspaces/startup/managed-worktree-create-startup'
|
|
import { buildWorktreeStartupForAgent } from '../../src/main/runtime/workspaces/startup/runtime-worktree-agent-startup'
|
|
import { getDefaultSettings } from '../../src/shared/constants'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import {
|
|
createCompatibleRuntimeStatusResponse,
|
|
type RuntimeEnvironmentCallRequest
|
|
} from '../../src/renderer/src/runtime/rpc/testing/runtime-compatibility-test-fixture'
|
|
import { TEST_REPO } from '../../src/renderer/src/store/repos/repo.test-fixture'
|
|
import { makeWorktree } from '../../src/renderer/src/store/slices/worktrees/worktree.test-fixture'
|
|
import {
|
|
createTestStore,
|
|
resetRemoteRuntimeMocks,
|
|
resetWorktreeSliceModuleMemory,
|
|
runtimeEnvironmentCall,
|
|
runtimeEnvironmentTransportCall
|
|
} from '../../src/renderer/src/store/slices/worktrees/worktrees-slice-test-harness'
|
|
|
|
vi.mock('sonner', () => ({
|
|
toast: { warning: vi.fn(), info: vi.fn(), success: vi.fn(), error: vi.fn(), dismiss: vi.fn() }
|
|
}))
|
|
|
|
beforeEach(() => {
|
|
resetWorktreeSliceModuleMemory()
|
|
vi.clearAllMocks()
|
|
resetRemoteRuntimeMocks()
|
|
})
|
|
|
|
describe('paired workspace agent startup ownership', () => {
|
|
it.each(['modern', 'prompt', 'older', 'probe-failure', 'predates-agent', 'custom'] as const)(
|
|
'preserves launch command ownership for %s paired creation',
|
|
async (scenario) => {
|
|
const supported = scenario === 'modern' || scenario === 'prompt'
|
|
const status = createCompatibleRuntimeStatusResponse('runtime-remote')
|
|
if (status.ok && scenario === 'older') {
|
|
status.result.capabilities = status.result.capabilities?.filter(
|
|
(capability) => capability !== 'agent.launch.v2'
|
|
)
|
|
}
|
|
let failedProbe = false
|
|
runtimeEnvironmentTransportCall.mockImplementation((args: RuntimeEnvironmentCallRequest) => {
|
|
if (args.method !== 'status.get') {
|
|
return runtimeEnvironmentCall(args)
|
|
}
|
|
if (scenario === 'probe-failure' && !failedProbe) {
|
|
failedProbe = true
|
|
throw new Error('temporary status read failure')
|
|
}
|
|
return status
|
|
})
|
|
const hostSettings = {
|
|
...getDefaultSettings('/host'),
|
|
agentCmdOverrides: { claude: '/host/claude-wrapper' },
|
|
agentDefaultArgs: { claude: '--host-only' },
|
|
agentDefaultEnv: { claude: { LAUNCH_OWNER: 'host' } }
|
|
}
|
|
const store = createTestStore()
|
|
store.setState({ repos: [{ ...TEST_REPO, executionHostId: 'runtime:env-1' }] })
|
|
let launchedCommand = ''
|
|
let launchedEnv: Record<string, string> | undefined
|
|
let delivered = ''
|
|
runtimeEnvironmentCall.mockImplementation(async (call) => {
|
|
expect(call.method).toBe('worktree.create')
|
|
if (scenario === 'predates-agent' && call.params && 'startupAgent' in call.params) {
|
|
// What a host older than the agent answers while validating its name.
|
|
return {
|
|
id: 'host-create',
|
|
ok: false,
|
|
error: { code: 'invalid_argument', message: 'Unknown TUI agent' },
|
|
_meta: { runtimeId: 'runtime-remote' }
|
|
}
|
|
}
|
|
const params = WorktreeCreate.parse(call.params)
|
|
const args = buildManagedWorktreeCreateArgs(params, {})
|
|
const resolved = await resolveManagedWorktreeCreateStartup(args, [], {
|
|
agent: (agent, prompt) =>
|
|
buildWorktreeStartupForAgent({
|
|
agent,
|
|
prompt,
|
|
repo: TEST_REPO,
|
|
settings: hostSettings,
|
|
getLaunchRuntime: () => ({
|
|
platform: 'linux',
|
|
shell: 'posix',
|
|
launchRuntime: {
|
|
platform: 'linux',
|
|
pty: { shellOverride: undefined, terminalWindowsWslDistro: null }
|
|
}
|
|
}),
|
|
toSessionOptions: () => undefined
|
|
}),
|
|
draft: async () => null
|
|
})
|
|
delivered = [resolved.effectiveStartup?.command, resolved.effectiveStartupFollowup?.prompt]
|
|
.filter(Boolean)
|
|
.join('\n')
|
|
launchedCommand = resolved.effectiveStartup?.command ?? ''
|
|
launchedEnv = resolved.effectiveStartup?.env
|
|
return {
|
|
id: 'host-create',
|
|
ok: true,
|
|
result: {
|
|
worktree: makeWorktree({ id: 'repo1::/path/host-agent', repoId: 'repo1' }),
|
|
startupTerminal: { spawned: true, tabId: 'host-tab' }
|
|
},
|
|
_meta: { runtimeId: 'runtime-remote' }
|
|
}
|
|
})
|
|
const createWorktree = store.getState().createWorktree
|
|
const args: Parameters<typeof createWorktree> = ['repo1', 'host-agent']
|
|
args[10] = 'claude'
|
|
args[16] = {
|
|
command: '/client/claude --client-only',
|
|
env: { LAUNCH_OWNER: 'client' },
|
|
launchAgent: 'claude'
|
|
}
|
|
args[25] = {
|
|
...(scenario === 'custom'
|
|
? {}
|
|
: {
|
|
hostAgentLaunch: {
|
|
agent: 'claude' as const,
|
|
...(scenario === 'prompt' ? { prompt: 'prompt-text' } : {})
|
|
}
|
|
}),
|
|
executionHostId: 'runtime:env-1'
|
|
}
|
|
|
|
await createWorktree(...args)
|
|
|
|
expect(launchedCommand).toContain(supported ? '/host/claude-wrapper' : '/client/claude')
|
|
expect(launchedCommand).toContain(supported ? '--host-only' : '--client-only')
|
|
expect(launchedEnv?.LAUNCH_OWNER).toBe(supported ? 'host' : 'client')
|
|
if (scenario === 'prompt') {
|
|
// Exactly once, through whichever channel the host's planner picked.
|
|
expect(delivered.split('prompt-text')).toHaveLength(2)
|
|
}
|
|
expect(runtimeEnvironmentCall).toHaveBeenCalledTimes(scenario === 'predates-agent' ? 2 : 1)
|
|
}
|
|
)
|
|
})
|