mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
fix(user-questions): bridge scoped request events
This commit is contained in:
@@ -34,6 +34,7 @@ const scopedSubjectResolvers: Readonly<Record<string, ScopedSubjectResolver | nu
|
||||
'tools/post-execute': args => (args[0] as Record<string, unknown>)['agent'],
|
||||
'tools/pre-execute': args => (args[0] as Record<string, unknown>)['agent'],
|
||||
'tools/result': args => (args[0] as Record<string, unknown>)['agent'],
|
||||
'user-questions/request': args => (args[0] as Record<string, unknown>)['agent'],
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import { Context, Service } from '@deepseek-ai/cordis'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { HarnessError } from '@deepseek-ai/dsh-llm'
|
||||
import { scopeTarget } from '@deepseek-ai/dsh-scope'
|
||||
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context {
|
||||
@@ -144,11 +145,18 @@ export class UserQuestionService extends Service {
|
||||
'BAD_INTENT')
|
||||
}
|
||||
}
|
||||
if (this.provider === undefined) {
|
||||
throw new UserQuestionError('no user-questions provider is registered', 'NO_PROVIDER')
|
||||
}
|
||||
const askProvider = () => this.provider === undefined
|
||||
? Promise.reject(new UserQuestionError('no user-questions provider is registered', 'NO_PROVIDER'))
|
||||
: this.provider.ask(request)
|
||||
try {
|
||||
return await this.provider.ask(request)
|
||||
return await (agent === undefined
|
||||
? askProvider()
|
||||
: this.ctx.waterfall(
|
||||
scopeTarget(agent, agent),
|
||||
'user-questions/request',
|
||||
{ ...request, agent },
|
||||
askProvider,
|
||||
))
|
||||
} catch (error) {
|
||||
if (request.signal?.aborted && !(error instanceof UserQuestionError)) {
|
||||
throw abortedQuestion(error)
|
||||
|
||||
@@ -171,6 +171,25 @@ describe('UserQuestionService', () => {
|
||||
expect(result).toEqual({ answers: [{ id: 'confirm', selected: ['yes'] }] })
|
||||
})
|
||||
|
||||
it('offers an Agent-scoped waterfall before the provider fallback', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(UserQuestionService)
|
||||
const p = provider('fallback')
|
||||
ctx.userQuestions.registerProvider(p)
|
||||
const agent = stubAgent('root')
|
||||
ctx.agents.enter(agent, undefined)
|
||||
ctx.on('user-questions/request', request => Promise.resolve({
|
||||
answers: request.questions.map(question => ({ id: question.id, selected: ['remote'] })),
|
||||
}))
|
||||
|
||||
await expect(ctx.userQuestions.ask({
|
||||
questions: [{ id: 'confirm', question: 'Proceed?' }],
|
||||
agent,
|
||||
})).resolves.toEqual({ answers: [{ id: 'confirm', selected: ['remote'] }] })
|
||||
expect(p.seen).toEqual([])
|
||||
})
|
||||
|
||||
it('rejects a supplied agent when no live registry can attest it', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(UserQuestionService)
|
||||
|
||||
Reference in New Issue
Block a user