test: migrate consumers to inbox and owned-run APIs
This commit is contained in:
@@ -9,7 +9,7 @@ import type { GoalView } from '@deepseek-ai/dsh-goal'
|
||||
import { createUserMessage, LlmAdapter, LlmError } from '@deepseek-ai/dsh-llm'
|
||||
import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm'
|
||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import type { TurnEndReason, UserMessage } from '@deepseek-ai/dsh-session'
|
||||
import type { UserMessage } from '@deepseek-ai/dsh-session'
|
||||
import * as goalSession from '../src/index.ts'
|
||||
|
||||
type ScriptEntry = StreamChunk[] | Error | 'hang' | ((options: GenerateOptions) => StreamChunk[])
|
||||
@@ -133,28 +133,6 @@ async function waitForRequests(adapter: ScriptedAdapter, count: number): Promise
|
||||
}
|
||||
|
||||
describe('goal-round outcome policy', () => {
|
||||
it.each([
|
||||
[{ kind: 'completed' }, true, { kind: 'continue' }],
|
||||
[{ kind: 'aborted' }, true, { kind: 'pause', reason: 'cancelled' }],
|
||||
[{ kind: 'error', step: 1, message: 'slow down', code: 'RATE_LIMIT' }, true,
|
||||
{ kind: 'blocked', code: 'usage-limited', message: 'slow down' }],
|
||||
[{ kind: 'error', step: 1, failure: { message: 'credits exhausted', code: 'QUOTA' } }, true,
|
||||
{ kind: 'blocked', code: 'usage-limited', message: 'credits exhausted' }],
|
||||
[{ kind: 'error', step: 1, failure: { message: 'provider failed', code: 'SERVER' } }, true,
|
||||
{ kind: 'blocked', code: 'turn-error', message: 'provider failed' }],
|
||||
[{ kind: 'error', step: 1, message: 'broken' }, true,
|
||||
{ kind: 'blocked', code: 'turn-error', message: 'broken' }],
|
||||
[{ kind: 'max-tokens' }, true,
|
||||
{ kind: 'blocked', code: 'max-tokens', message: 'model output reached max tokens' }],
|
||||
[{ kind: 'disposed' }, true, { kind: 'disarm', reason: 'disposed' }],
|
||||
[{ kind: 'interrupted' }, true, { kind: 'disarm', reason: 'interrupted' }],
|
||||
[{ kind: 'completed' }, false, { kind: 'disarm', reason: 'durability-failed' }],
|
||||
[{ kind: 'future-outcome' } as unknown as TurnEndReason, true,
|
||||
{ kind: 'blocked', code: 'unknown-turn-outcome', message: 'unknown turn outcome: future-outcome' }],
|
||||
] as const)('maps %j without abnormal automatic retry', (reason, durable, expected) => {
|
||||
expect(goalSession.classifyGoalRound(reason, durable)).toEqual(expected)
|
||||
})
|
||||
|
||||
it('renders the objective, round budget, authority boundary, and completion protocol', () => {
|
||||
const goal: GoalView = {
|
||||
id: GoalId('goal-prompt'),
|
||||
@@ -259,7 +237,7 @@ describe('same-session goal driving', () => {
|
||||
|
||||
it('maps a downstream prompt veto to blocked without admitting the round', async () => {
|
||||
const test = await harness([])
|
||||
test.ctx.on('agent/prompt-submit', (_agent, message, _signal, next) => message.source.kind === 'goal'
|
||||
test.ctx.on('agent/prompt-submit', (_agent, messages, _signal, next) => messages[0]?.source.kind === 'goal'
|
||||
? Promise.resolve({ kind: 'block', reason: 'deployment policy' })
|
||||
: next())
|
||||
test.ctx.goals.create(test.agent, { objective: 'respect policy' })
|
||||
@@ -274,7 +252,7 @@ describe('same-session goal driving', () => {
|
||||
|
||||
it('does not reserve again when a stopped-goal observer queues ordinary work', async () => {
|
||||
const test = await harness([textResponse('human follow-up')])
|
||||
test.ctx.on('agent/prompt-submit', (_agent, message, _signal, next) => message.source.kind === 'goal'
|
||||
test.ctx.on('agent/prompt-submit', (_agent, messages, _signal, next) => messages[0]?.source.kind === 'goal'
|
||||
? Promise.resolve({ kind: 'block', reason: 'stop this round' })
|
||||
: next())
|
||||
test.ctx.on('goal/changed', (agent, change) => {
|
||||
@@ -382,8 +360,8 @@ describe('same-session goal driving', () => {
|
||||
it('rechecks revision after downstream prompt hooks before admitting', async () => {
|
||||
const test = await harness([textResponse('new revision')])
|
||||
let edited = false
|
||||
test.ctx.on('agent/prompt-submit', (agent, message, _signal, next) => {
|
||||
if (message.source.kind === 'goal' && !edited) {
|
||||
test.ctx.on('agent/prompt-submit', (agent, messages, _signal, next) => {
|
||||
if (messages[0]?.source.kind === 'goal' && !edited) {
|
||||
edited = true
|
||||
const current = test.ctx.goals.get(agent)
|
||||
if (current === undefined) throw new Error('missing goal during prompt edit')
|
||||
@@ -489,8 +467,8 @@ describe('same-session goal driving', () => {
|
||||
// attempt through cancel-requested) and THEN throws: the catch finds no
|
||||
// matching reservation and must not reschedule a paused goal.
|
||||
let fired = false
|
||||
test.ctx.on('agent/prompt-submit', async (agent, message, _signal, next) => {
|
||||
if (message.source.kind === 'goal' && !fired) {
|
||||
test.ctx.on('agent/prompt-submit', async (agent, messages, _signal, next) => {
|
||||
if (messages[0]?.source.kind === 'goal' && !fired) {
|
||||
fired = true
|
||||
agent.cancel({ kind: 'user' })
|
||||
throw new Error('hook cancelled then exploded')
|
||||
@@ -513,8 +491,8 @@ describe('same-session goal driving', () => {
|
||||
// Registered after goal-session's own listener: the throw propagates back
|
||||
// through goal-session's next() await, dropping the whole admission.
|
||||
let threw = false
|
||||
test.ctx.on('agent/prompt-submit', async (_agent, message, _signal, next) => {
|
||||
if (message.source.kind === 'goal' && !threw) {
|
||||
test.ctx.on('agent/prompt-submit', async (_agent, messages, _signal, next) => {
|
||||
if (messages[0]?.source.kind === 'goal' && !threw) {
|
||||
threw = true
|
||||
throw new Error('downstream admission hook exploded')
|
||||
}
|
||||
@@ -660,8 +638,8 @@ describe('same-session goal driving', () => {
|
||||
it('fails a post-hook read closed before the prompt can enter history', async () => {
|
||||
const test = await harness([])
|
||||
let armed = true
|
||||
test.ctx.on('agent/prompt-submit', (_agent, message, _signal, next) => {
|
||||
if (message.source.kind === 'goal' && armed) {
|
||||
test.ctx.on('agent/prompt-submit', (_agent, messages, _signal, next) => {
|
||||
if (messages[0]?.source.kind === 'goal' && armed) {
|
||||
armed = false
|
||||
vi.spyOn(test.ctx.goals, 'get').mockImplementationOnce(() => {
|
||||
throw new Error('post-hook projection failed')
|
||||
@@ -735,8 +713,8 @@ describe('same-session goal driving', () => {
|
||||
it('blocks admission when downstream cancellation clears the reservation', async () => {
|
||||
const test = await harness([])
|
||||
let cancelled = false
|
||||
test.ctx.on('agent/prompt-submit', (agent, message, _signal, next) => {
|
||||
if (message.source.kind === 'goal' && !cancelled) {
|
||||
test.ctx.on('agent/prompt-submit', (agent, messages, _signal, next) => {
|
||||
if (messages[0]?.source.kind === 'goal' && !cancelled) {
|
||||
cancelled = true
|
||||
agent.cancel({ kind: 'user' })
|
||||
}
|
||||
@@ -804,8 +782,8 @@ describe('same-session goal driving', () => {
|
||||
it('leaves a queued reservation pending when the driver runs before its turn settles', async () => {
|
||||
const test = await harness([textResponse('settled later')])
|
||||
let woken = false
|
||||
test.ctx.on('agent/prompt-submit', async (_agent, message, _signal, next) => {
|
||||
if (message.source.kind === 'goal' && !woken) {
|
||||
test.ctx.on('agent/prompt-submit', async (_agent, messages, _signal, next) => {
|
||||
if (messages[0]?.source.kind === 'goal' && !woken) {
|
||||
woken = true
|
||||
// A concurrent driver pass must observe the still-unsettled attempt
|
||||
// and yield rather than double-book or clear the reservation.
|
||||
@@ -929,8 +907,8 @@ describe('same-session goal driving', () => {
|
||||
it('does not re-block a goal the downstream veto already saw cancelled', async () => {
|
||||
const test = await harness([])
|
||||
let vetoed = false
|
||||
test.ctx.on('agent/prompt-submit', (agent, message, _signal, next) => {
|
||||
if (message.source.kind === 'goal' && !vetoed) {
|
||||
test.ctx.on('agent/prompt-submit', (agent, messages, _signal, next) => {
|
||||
if (messages[0]?.source.kind === 'goal' && !vetoed) {
|
||||
vetoed = true
|
||||
agent.cancel({ kind: 'user' })
|
||||
return Promise.resolve<PromptDecision>({ kind: 'block', reason: 'cancelled by policy' })
|
||||
@@ -952,8 +930,8 @@ describe('same-session goal driving', () => {
|
||||
it('awaits an unadmitted reservation stuck in admission during teardown without cancelling', async () => {
|
||||
const test = await harness([])
|
||||
let release: (() => void) | undefined
|
||||
test.ctx.on('agent/prompt-submit', async (_agent, message, _signal, next) => {
|
||||
if (message.source.kind === 'goal' && release === undefined) {
|
||||
test.ctx.on('agent/prompt-submit', async (_agent, messages, _signal, next) => {
|
||||
if (messages[0]?.source.kind === 'goal' && release === undefined) {
|
||||
await new Promise<void>((resolve) => { release = resolve })
|
||||
}
|
||||
return next()
|
||||
|
||||
Reference in New Issue
Block a user