mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
The native adapter's route was named deepseek, colliding with pi-ai's catalog provider of the same name, so the two DeepSeek paths could never be mounted side by side. The web settings page needs both configurable at once. Compositions, fixtures, goldens, scaffolding defaults, and docs all move together (pre-release, no shim); TUI/session-query-spill/ missing-credential goldens re-recorded through their keyless refresh modes because provider-name length shifts box padding and spill truncation points.
56 lines
2.3 KiB
TypeScript
56 lines
2.3 KiB
TypeScript
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
|
import { mkdtemp, rm } from 'node:fs/promises'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
import type { Context } from 'cordis'
|
|
import { codingHarness, TODO_SYSTEM_PROMPT, waitForIdle } from './harness.ts'
|
|
import { SessionId } from '@deepseek-ai/dsh-session'
|
|
|
|
/**
|
|
* A REAL model drives the REAL todo_write tool: verify the WORLD (the session
|
|
* log gains a todo/write event whose snapshot the model actually produced), not
|
|
* the agent's self-report. Key-gated (see vitest.e2e.config.ts).
|
|
*/
|
|
|
|
let ctx: Context | undefined
|
|
let workdir: string | undefined
|
|
|
|
afterEach(async () => {
|
|
await ctx?.fiber.dispose()
|
|
ctx = undefined
|
|
if (workdir !== undefined) await rm(workdir, { recursive: true, force: true })
|
|
workdir = undefined
|
|
})
|
|
|
|
describe.skipIf(!process.env.DEEPSEEK_API_KEY)('todo_write: real model records a plan', () => {
|
|
it('appends a todo/write event with the model-produced task list', async () => {
|
|
workdir = await mkdtemp(join(tmpdir(), 'dsh-todo-write-e2e-'))
|
|
ctx = await codingHarness(workdir, { persona: TODO_SYSTEM_PROMPT })
|
|
const agent = ctx.agentLoop.create(SessionId('e2e-todo'), { provider: 'deepseek-official', model: 'deepseek-v4-flash' })
|
|
|
|
agent.followup(createUserMessage({
|
|
content: [{ type: 'text', text:
|
|
'Use the todo_write tool to record a plan of exactly two steps: first '
|
|
+ '"inspect the failing test" (in_progress), then "apply the fix" (pending). '
|
|
+ 'Send both in one todo_write call, then reply with the single word DONE.' }], source: { kind: 'user' } }))
|
|
await waitForIdle(ctx, agent)
|
|
|
|
const events = [...agent.session.events]
|
|
|
|
// The model actually called the tool.
|
|
const calls = events.filter(event => event.type === 'tool/call')
|
|
expect(calls.some(event => event.data.name === 'todo_write')).toBe(true)
|
|
|
|
// And the tool wrote a todo/write event to the log — verify the WORLD.
|
|
const todoEvents = events.filter(event => event.type === 'todo/write')
|
|
expect(todoEvents.length).toBeGreaterThan(0)
|
|
|
|
const todos = (todoEvents.at(-1)!).data.todos
|
|
expect(todos).toEqual([
|
|
{ content: 'inspect the failing test', status: 'in_progress' },
|
|
{ content: 'apply the fix', status: 'pending' },
|
|
])
|
|
}, 120_000)
|
|
})
|