refactor agent pre-step inbox lifecycle
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import type { Context } from 'cordis'
|
||||
import z from 'schemastery'
|
||||
import type { Agent, PromptDecision } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, PreStepDecision } from '@deepseek-ai/dsh-agent'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import type { ContentBlock, MessageSource } from '@deepseek-ai/dsh-llm'
|
||||
import type { UserMessage } from '@deepseek-ai/dsh-session'
|
||||
@@ -182,11 +182,6 @@ export function apply(ctx: Context, config: Config): void {
|
||||
return [ours, ...theirs ?? []]
|
||||
}
|
||||
|
||||
/** Append hook context to an admitted inbox batch. */
|
||||
function appendPromptContext(theirs: UserMessage[], ours: UserMessage): UserMessage[] {
|
||||
return [...theirs, ours]
|
||||
}
|
||||
|
||||
// SessionStart injects plain stdout when its detached hook resolves; a slow
|
||||
// hook may miss the first request.
|
||||
// TODO(session-start-gating): add a startup gate before promising first-turn delivery.
|
||||
@@ -200,30 +195,27 @@ export function apply(ctx: Context, config: Config): void {
|
||||
/* jscpd:ignore-end */
|
||||
})
|
||||
|
||||
// UserPromptSubmit → PromptDecision. Codex supports block, not allow or ask.
|
||||
ctx.on('agent/prompt-submit', async (agent, messages, signal, next): Promise<PromptDecision> => {
|
||||
// UserPromptSubmit → PreStepDecision. Codex supports reject, not rewrite or ask.
|
||||
ctx.on('agent/pre-step', async (agent, messages, { turn, signal }, next): Promise<PreStepDecision> => {
|
||||
if (messages.length === 0) return next()
|
||||
const payload = {
|
||||
...base(ctx, agent, 'UserPromptSubmit', model),
|
||||
turn_id: String(lastTurn(agent) + 1),
|
||||
turn_id: String(turn),
|
||||
prompt: blocksToText(messages.flatMap(message => message.content)),
|
||||
}
|
||||
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',
|
||||
discardClaimed: true,
|
||||
}
|
||||
return { kind: 'reject' }
|
||||
}
|
||||
// Context alone is not a veto: DELEGATE so a later prompt-submit listener can
|
||||
// still block/rewrite, then fold our context onto its decision.
|
||||
// Context alone is not a veto: DELEGATE so a later pre-step listener can
|
||||
// still reject/rewrite, then fold our context onto its decision.
|
||||
const downstream = await next()
|
||||
const ours = contextFrom(merged)
|
||||
if (!ours || downstream.kind !== 'allow') return downstream
|
||||
if (!ours || downstream.kind !== 'enter') return downstream
|
||||
return {
|
||||
kind: 'allow',
|
||||
messages: appendPromptContext(downstream.messages, ours),
|
||||
kind: 'enter',
|
||||
messages: [...downstream.messages, ours],
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user