feat: add canonical typed tool outputs
This commit is contained in:
@@ -119,7 +119,13 @@ class RecordingSandboxExecutor extends BashExecutor {
|
||||
timeoutMs: spec.timeoutMs,
|
||||
stdout: { text: 'ok', truncated: false },
|
||||
stderr: { text: '', truncated: false },
|
||||
sandbox: { mode: spec.sandboxMode ?? 'read-only', denied: false },
|
||||
sandbox: {
|
||||
mode: spec.sandboxMode ?? 'read-only',
|
||||
denied: false,
|
||||
...spec.command === 'without optional sandbox facts'
|
||||
? {}
|
||||
: { enforcement: 'full' as const, runnerFailed: false },
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -204,6 +210,16 @@ describe('bash tool', () => {
|
||||
const ctx = await setup()
|
||||
const result = await call(ctx, 'bash', { command: 'echo hello', description: 'test command' })
|
||||
expect(result.isError).toBe(false)
|
||||
if (result.isError) throw new Error('expected bash success')
|
||||
expect(result.value).toMatchObject({
|
||||
kind: 'foreground',
|
||||
exitCode: 0,
|
||||
signal: null,
|
||||
timedOut: false,
|
||||
aborted: false,
|
||||
stdout: { text: 'hello\n', truncated: false },
|
||||
stderr: { text: '', truncated: false },
|
||||
})
|
||||
expect(text(result)).toBe('hello\n')
|
||||
})
|
||||
|
||||
@@ -399,6 +415,8 @@ describe('background execution through the task runtime', () => {
|
||||
const ctx = await setupWithTasks()
|
||||
const started = await call(ctx, 'bash', { command: 'echo bg-ok', description: 'test command', run_in_background: true })
|
||||
expect(started.isError).toBe(false)
|
||||
if (started.isError) throw new Error('expected background bash success')
|
||||
expect(started.value).toEqual({ kind: 'background', taskId: 'bash-1' })
|
||||
expect(text(started)).toBe('started background task bash-1')
|
||||
|
||||
const read = await callUntilText(ctx, 'task_output', { task_id: 'bash-1' }, 'bg-ok')
|
||||
@@ -606,6 +624,22 @@ describe('sandbox escalation through the generic task producer', () => {
|
||||
expect(bash.modes).toEqual(['workspace-write', 'danger-full-access'])
|
||||
})
|
||||
|
||||
it('omits sandbox facts the executor did not acquire from the canonical result', async () => {
|
||||
const { ctx } = await setupSandboxed()
|
||||
const result = await call(ctx, 'bash', {
|
||||
command: 'without optional sandbox facts',
|
||||
description: 'exercise optional sandbox facts',
|
||||
})
|
||||
|
||||
if (result.isError) throw new Error('expected foreground bash success')
|
||||
expect(result.value).toMatchObject({
|
||||
kind: 'foreground',
|
||||
sandbox: { mode: 'read-only', denied: false },
|
||||
})
|
||||
expect((result.value as { sandbox: object }).sandbox).not.toHaveProperty('enforcement')
|
||||
expect((result.value as { sandbox: object }).sandbox).not.toHaveProperty('runnerFailed')
|
||||
})
|
||||
|
||||
it('keeps the exhaustiveness backstop for a rogue approval implementation', async () => {
|
||||
const { ctx } = await setupSandboxed(true)
|
||||
ctx.approval.request = () => Promise.resolve('rogue' as ApprovalOutcome)
|
||||
|
||||
Reference in New Issue
Block a user