fix(agent-loop): scope blocked admission cleanup
This commit is contained in:
@@ -209,7 +209,13 @@ export function apply(ctx: Context, config: Config): void {
|
||||
}
|
||||
const merged = await runPoint('UserPromptSubmit', '', payload, { agent, plainStdoutAsContext: true, signal })
|
||||
/* jscpd:ignore-start */
|
||||
if (merged.decision === 'deny') return { kind: 'block', reason: merged.reason ?? 'blocked by UserPromptSubmit hook' }
|
||||
if (merged.decision === 'deny') {
|
||||
return {
|
||||
kind: 'block',
|
||||
reason: merged.reason ?? 'blocked by UserPromptSubmit hook',
|
||||
discardClaimed: true,
|
||||
}
|
||||
}
|
||||
// Context alone is not a veto: DELEGATE so a later prompt-submit listener can
|
||||
// still block/rewrite, then fold our context onto its decision.
|
||||
const downstream = await next()
|
||||
|
||||
@@ -109,7 +109,11 @@ export function defineCoverageCases(groups: CoverageGroup | readonly CoverageGro
|
||||
hooks(d, { UserPromptSubmit: [{ hooks: [{ type: 'command', command: sh(d, 'c.sh', '#!/usr/bin/env bash\necho \'{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"bridge ctx"}}\'\n') }] }] })
|
||||
const adapter = new MockAdapter([textResponse('should not run')])
|
||||
const ctx = await harness(join(d, 'hooks.json'), adapter)
|
||||
ctx.on('agent/prompt-submit', async () => ({ kind: 'block' as const, reason: 'policy veto' }))
|
||||
ctx.on('agent/prompt-submit', async () => ({
|
||||
kind: 'block' as const,
|
||||
reason: 'policy veto',
|
||||
discardClaimed: true,
|
||||
}))
|
||||
const agent = ctx.agentLoop.create(SessionId('a1'), { provider: 'mock', model: 'mock' })
|
||||
agent.followup(createUserMessage({ content: [{ type: 'text', text: 'go' }], source: { kind: 'user' } })); await waitForIdle(ctx, agent)
|
||||
expect(adapter.requests).toHaveLength(0)
|
||||
|
||||
Reference in New Issue
Block a user