mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 08:03:39 +00:00
test(runtime): cover the Windows agent-prompt submit delay on Linux lanes
AGENT_PROMPT_SUBMIT_DELAY_MS is frozen from process.platform at import, so no PR lane ever exercised the 1_500 ConPTY path. Add a suite that mocks the constant to the Windows value and replays both the delay boundary and the cancellation-during-verification scenario. Also pin the phase boundary in the existing cancellation test so timing drift fails at the Enter write rather than as an ambiguous empty post-abort array. Refs #15498
This commit is contained in:
@@ -676,8 +676,10 @@ describe('agent prompt submission runtime', () => {
|
||||
})
|
||||
const rejected = expect(submission).rejects.toThrow('request_aborted')
|
||||
|
||||
// Why: the settle delay is platform-dependent (1_500 on Windows); a hardcoded 500 aborts before the Enter there.
|
||||
// Why: the submit delay is 1_500 on Windows (ConPTY); a hardcoded 500 aborts before the Enter there.
|
||||
await vi.advanceTimersByTimeAsync(AGENT_PROMPT_SUBMIT_DELAY_MS)
|
||||
// Why: pin the phase boundary so drift fails here instead of as an empty post-abort array.
|
||||
expect(writes.filter((data) => data === '\r')).toHaveLength(1)
|
||||
controller.abort()
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import type * as AgentPromptInjection from '../../shared/agent-prompt-injection'
|
||||
import { OrcaRuntimeService } from './orca-runtime'
|
||||
import { makeStore } from './runtime-rpc-worktree-store-fixtures'
|
||||
|
||||
// Why: vi.mock factories are hoisted above module-scope consts, so the delay must be hoisted too.
|
||||
const { WINDOWS_SUBMIT_DELAY_MS } = vi.hoisted(() => ({ WINDOWS_SUBMIT_DELAY_MS: 1_500 }))
|
||||
const WORKTREE_PATH = '/tmp/worktree-a'
|
||||
|
||||
// Why: AGENT_PROMPT_SUBMIT_DELAY_MS is frozen from process.platform at import, so the 1_500 ConPTY
|
||||
// path is otherwise unreachable on the Linux/macOS lanes that run this suite.
|
||||
vi.mock('../../shared/agent-prompt-injection', async (importOriginal) => ({
|
||||
...(await importOriginal<typeof AgentPromptInjection>()),
|
||||
AGENT_PROMPT_SUBMIT_DELAY_MS: WINDOWS_SUBMIT_DELAY_MS
|
||||
}))
|
||||
|
||||
vi.mock('../git/worktree', () => ({
|
||||
listWorktrees: vi.fn().mockResolvedValue([
|
||||
{
|
||||
path: '/tmp/worktree-a',
|
||||
head: 'abc',
|
||||
branch: 'feature/prompt-verification',
|
||||
isBare: false,
|
||||
isMainWorktree: false
|
||||
}
|
||||
]),
|
||||
listWorktreesStrict: vi.fn().mockResolvedValue([
|
||||
{
|
||||
path: '/tmp/worktree-a',
|
||||
head: 'abc',
|
||||
branch: 'feature/prompt-verification',
|
||||
isBare: false,
|
||||
isMainWorktree: false
|
||||
}
|
||||
])
|
||||
}))
|
||||
|
||||
// Why: 'aider' is not a settlement agent, so submission takes the fixed-delay branch under test.
|
||||
async function createPromptRuntime(): Promise<{
|
||||
runtime: OrcaRuntimeService
|
||||
handle: string
|
||||
writes: string[]
|
||||
}> {
|
||||
const runtime = new OrcaRuntimeService(makeStore() as never)
|
||||
const writes: string[] = []
|
||||
runtime.setPtyController({
|
||||
spawn: vi.fn().mockResolvedValue({ id: 'pty-prompt' }),
|
||||
write: (_ptyId, data) => {
|
||||
writes.push(data)
|
||||
return true
|
||||
},
|
||||
kill: () => true,
|
||||
getForegroundProcess: async () => null
|
||||
})
|
||||
const terminal = await runtime.createTerminal(`path:${WORKTREE_PATH}`, {
|
||||
launchAgent: 'aider'
|
||||
})
|
||||
return { runtime, handle: terminal.handle, writes }
|
||||
}
|
||||
|
||||
function countSubmits(writes: readonly string[]): number {
|
||||
return writes.filter((data) => data === '\r').length
|
||||
}
|
||||
|
||||
describe('agent prompt submission at the Windows submit delay', () => {
|
||||
afterEach(() => vi.useRealTimers())
|
||||
|
||||
it('holds Enter until the full platform delay elapses', async () => {
|
||||
vi.useFakeTimers()
|
||||
const { runtime, handle, writes } = await createPromptRuntime()
|
||||
const submission = runtime.sendTerminalAgentPrompt(handle, 'review this')
|
||||
const stalled = expect(submission).rejects.toThrow('agent_prompt_stalled')
|
||||
|
||||
await vi.advanceTimersByTimeAsync(WINDOWS_SUBMIT_DELAY_MS - 1)
|
||||
expect(countSubmits(writes)).toBe(0)
|
||||
await vi.advanceTimersByTimeAsync(1)
|
||||
expect(countSubmits(writes)).toBe(1)
|
||||
|
||||
await vi.runAllTimersAsync()
|
||||
await stalled
|
||||
})
|
||||
|
||||
it('does not send another Enter after cancellation during verification', async () => {
|
||||
vi.useFakeTimers()
|
||||
const controller = new AbortController()
|
||||
const { runtime, handle, writes } = await createPromptRuntime()
|
||||
const submission = runtime.sendTerminalAgentPrompt(handle, 'review this', {
|
||||
signal: controller.signal
|
||||
})
|
||||
const rejected = expect(submission).rejects.toThrow('request_aborted')
|
||||
|
||||
await vi.advanceTimersByTimeAsync(WINDOWS_SUBMIT_DELAY_MS)
|
||||
expect(countSubmits(writes)).toBe(1)
|
||||
controller.abort()
|
||||
await vi.runAllTimersAsync()
|
||||
|
||||
await rejected
|
||||
expect(countSubmits(writes)).toBe(1)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user