From baed704fc26e392aee67fe1645a130ecdd6d82ef Mon Sep 17 00:00:00 2001 From: Chinesezjc Date: Thu, 6 Aug 2026 11:46:22 +0800 Subject: [PATCH] test(todo): follow master's Agent shape and load-time config failure --- .../ui-conversation/tests/todo-panel.spec.tsx | 2 +- .../tests/loader-composition.spec.ts | 33 +++++++------------ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/packages/client/ui-conversation/tests/todo-panel.spec.tsx b/packages/client/ui-conversation/tests/todo-panel.spec.tsx index 7bcc8c4071..82f71517f1 100644 --- a/packages/client/ui-conversation/tests/todo-panel.spec.tsx +++ b/packages/client/ui-conversation/tests/todo-panel.spec.tsx @@ -132,7 +132,7 @@ describe('TodoPanel', () => { expect(statuses.filter(s => s === 'in_progress')).toHaveLength(3) expect(screen.getByText('跑后台构建')).toBeTruthy() expect(screen.getByText('读源码')).toBeTruthy() - expect(screen.getByText('1 已完成 · 3 进行中 · 1 待处理')).toBeTruthy() + expect(screen.getByText('1 已完成 · 3 进行中 · 1 待处理')).toBeTruthy() }) it('an all-completed list collapses the summary to the done count alone', () => { diff --git a/packages/todo/tool-todo/tests/loader-composition.spec.ts b/packages/todo/tool-todo/tests/loader-composition.spec.ts index 58e5434acf..572254e348 100644 --- a/packages/todo/tool-todo/tests/loader-composition.spec.ts +++ b/packages/todo/tool-todo/tests/loader-composition.spec.ts @@ -6,12 +6,12 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { pathToFileURL } from 'node:url' import { afterEach, describe, expect, it } from 'vitest' -import { Context, FiberState } from 'cordis' +import { Context } from 'cordis' import Loader from '@cordisjs/plugin-loader' import Include from '@cordisjs/plugin-include' import { CallId } from '@deepseek-ai/dsh-llm' import { Session, SessionId } from '@deepseek-ai/dsh-session' -import AgentRegistry from '@deepseek-ai/dsh-agent' +import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent' import type { Agent } from '@deepseek-ai/dsh-agent' import SystemPrompt from '@deepseek-ai/dsh-system-prompt' import ToolRegistry from '@deepseek-ai/dsh-tools' @@ -30,9 +30,13 @@ afterEach(async () => { function agent(ctx: Context): Agent { const scope = ctx.plugin(() => {}) const id = SessionId('todo-loader-agent') + const session = Session.create(id) const value: Agent = { - id, options: {}, session: new Session(id), status: 'idle', acceptsNextStep: false, ctx: scope.ctx, - followup: () => {}, steer: () => {}, inject: () => {}, send: () => {}, cancel() {}, whenIdle: () => Promise.resolve(), + id, options: {}, session, inbox: new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} }), + status: 'idle', ctx: scope.ctx, + followup: () => {}, steer: () => {}, inject: () => {}, send: () => {}, cancel() {}, + runMaintenance: task => task(new AbortController().signal), + whenIdle: () => Promise.resolve(), } ctx.agents.register(value) return value @@ -126,23 +130,10 @@ describe('tool-todo real Loader composition through cordis.yml', () => { it.each([ { label: 'is omitted', configLines: [], failure: '$.allowParallelInProgress missing required value' }, - { label: 'is not boolean', configLines: [' allowParallelInProgress: "no"'], failure: '$.allowParallelInProgress' }, + { label: 'is not boolean', configLines: [' allowParallelInProgress: "no"'], failure: '$.allowParallelInProgress expected boolean' }, ])('fails loading when allowParallelInProgress $label', async ({ configLines, failure }) => { - // loader.await() is all-settled; configuration failure leaves a FAILED - // entry and escapes as a late rejection for the host boot to report. - const rejections: unknown[] = [] - const onUnhandled = (err: unknown): void => { rejections.push(err) } - process.on('unhandledRejection', onUnhandled) - try { - const ctx = await boot(configLines) - const entry = [...ctx.loader.entries()].find(e => e.options.name === '@deepseek-ai/dsh-tool-todo') - expect(entry?.fiber?.state).toBe(FiberState.FAILED) - for (let i = 0; i < 100 && rejections.length === 0; i++) { - await new Promise(resolve => setTimeout(resolve, 10)) - } - expect(rejections.map(String).join('\n')).toContain(failure) - } finally { - process.off('unhandledRejection', onUnhandled) - } + // The policy is self-contained, so misconfiguration fails at load: the + // entry's apply rejects and boot never reaches a running tool. + await expect(boot(configLines)).rejects.toThrow(failure) }, 30_000) })