Merge remote-tracking branch 'origin/master' into codex/ask-user-question
# Conflicts: # docs/config-catalog.md # examples/acp-agent/tests/snapshots/text-turn/session.jsonl # pnpm-lock.yaml
This commit is contained in:
@@ -40,12 +40,14 @@ async function readUntil(
|
||||
): Promise<BashTaskRead> {
|
||||
const deadline = Date.now() + timeoutMs
|
||||
let last: BashTaskRead | undefined
|
||||
let delta = ''
|
||||
while (Date.now() < deadline) {
|
||||
last = bash.readOutput(id)
|
||||
if (last.delta.includes(expected)) return last
|
||||
delta += last.delta
|
||||
if (delta.includes(expected)) return { ...last, delta }
|
||||
await new Promise(resolve => setTimeout(resolve, 20))
|
||||
}
|
||||
throw new Error(`task ${id} output did not include ${JSON.stringify(expected)}; last delta was ${JSON.stringify(last?.delta ?? '')}`)
|
||||
throw new Error(`task ${id} output did not include ${JSON.stringify(expected)}; output was ${JSON.stringify(delta)}, last delta was ${JSON.stringify(last?.delta ?? '')}`)
|
||||
}
|
||||
|
||||
describe('LocalBashExecutor.run', () => {
|
||||
@@ -90,8 +92,8 @@ describe('LocalBashExecutor.run', () => {
|
||||
|
||||
it('kill escalation uses the configured graceMs (a TERM-trapping task dies by SIGKILL)', async () => {
|
||||
const { bash } = await setup() // setup pins graceMs: 200 via config
|
||||
const task = bash.start(bash.resolve({ command: 'trap \'\' TERM; sleep 60' }))
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
const task = bash.start(bash.resolve({ command: 'trap \'\' TERM; echo trap-ready; sleep 60' }))
|
||||
await readUntil(bash, task.id, 'trap-ready')
|
||||
bash.kill(task.id)
|
||||
await task.done
|
||||
expect(task.signal).toBe('SIGKILL')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { mkdtempSync, readFileSync, statSync } from 'node:fs'
|
||||
import { existsSync, mkdtempSync, readFileSync, statSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
@@ -56,6 +56,15 @@ async function waitForStdout(running: RunningBash, expected: string, timeoutMs =
|
||||
throw new Error(`stdout did not include ${JSON.stringify(expected)} after ${timeoutMs}ms`)
|
||||
}
|
||||
|
||||
async function waitForFile(file: string, timeoutMs = 5_000): Promise<void> {
|
||||
const deadline = Date.now() + timeoutMs
|
||||
while (Date.now() < deadline) {
|
||||
if (existsSync(file)) return
|
||||
await new Promise(resolve => setTimeout(resolve, 20))
|
||||
}
|
||||
throw new Error(`${file} did not exist after ${timeoutMs}ms`)
|
||||
}
|
||||
|
||||
describe('runBash', () => {
|
||||
it('captures stdout on success', async () => {
|
||||
const result = await runBash(spec('echo hello')).done
|
||||
@@ -119,7 +128,7 @@ describe('runBash', () => {
|
||||
// group must take the sleep down with bash.
|
||||
const pidFile = join(spillDir, `grandchild-${Date.now()}.pid`)
|
||||
const running = runBash(spec(`sleep 60 & echo $! > ${pidFile}; wait`))
|
||||
await new Promise(resolve => setTimeout(resolve, 300))
|
||||
await waitForFile(pidFile)
|
||||
const grandchild = Number(readFileSync(pidFile, 'utf8').trim())
|
||||
expect(grandchild).toBeGreaterThan(0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user