mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
152 lines
5.2 KiB
TypeScript
152 lines
5.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { join } from 'node:path'
|
|
import type { Context } from 'cordis'
|
|
import Loader from '@cordisjs/plugin-loader'
|
|
import { TOOL_ORDER_REST } from '@deepseek-ai/dsh-system-prompt'
|
|
import * as tuiAgent from '../src/index.ts'
|
|
|
|
interface PluginCall {
|
|
readonly name: string
|
|
readonly config: unknown
|
|
}
|
|
|
|
function recordingContext(): { readonly ctx: Context; readonly calls: PluginCall[] } {
|
|
const calls: PluginCall[] = []
|
|
const ctx = {
|
|
plugin(plugin: { name?: string }, config?: unknown) {
|
|
calls.push({ name: plugin.name ?? '', config })
|
|
},
|
|
} as unknown as Context
|
|
return { ctx, calls }
|
|
}
|
|
|
|
describe('dsh-tui-demo app', () => {
|
|
it('composes the TUI cluster around one fresh exact session identity', () => {
|
|
const { ctx, calls } = recordingContext()
|
|
tuiAgent.composeTuiApp(ctx, {
|
|
provider: 'mock',
|
|
model: 'mock-model',
|
|
maxParallelToolCalls: 3,
|
|
persona: 'test persona',
|
|
toolOrder: ['zulu', TOOL_ORDER_REST],
|
|
tools: { mode: 'code' },
|
|
dshHome: '/tmp/dsh-home',
|
|
persistenceRoot: '/tmp/tui-sessions',
|
|
persistenceCompression: 'none',
|
|
sessionReferences: {
|
|
maxReferences: 2,
|
|
candidateLimit: 7,
|
|
maxReferenceBytes: 1234,
|
|
},
|
|
welcome: 'TUI ready',
|
|
resumeCommand: 'dsh --resume {session}',
|
|
ui: { color: false, maxToolOutputLines: 3 },
|
|
skills: { tool: { catalogDescriptionMaxLength: 8 } },
|
|
toolBash: { enableRunInBackground: false },
|
|
toolTasks: { waitTimeoutMs: 7, maxWaitTimeoutMs: 11 },
|
|
workspaceContext: false,
|
|
})
|
|
|
|
expect(calls.map(call => call.name)).toEqual([
|
|
'CommandService',
|
|
'command-goal',
|
|
'SessionPersistenceJsonl',
|
|
'session-checkpoint-policy',
|
|
'SessionQuerySqlite',
|
|
'SessionReferenceService',
|
|
'UserInteractionService',
|
|
'ui-tui',
|
|
'agent-spine-demo',
|
|
'tool-ask-user',
|
|
])
|
|
expect(calls[0]?.config).toBeUndefined()
|
|
expect(calls[2]?.config).toEqual({ root: '/tmp/tui-sessions', compression: 'none' })
|
|
expect(calls[4]?.config).toEqual({ path: join('/tmp/tui-sessions', 'session-query.db') })
|
|
expect(calls[5]?.config).toEqual({
|
|
maxReferences: 2,
|
|
candidateLimit: 7,
|
|
maxReferenceBytes: 1234,
|
|
})
|
|
const tuiConfig = calls[7]?.config as { sessionId: string }
|
|
expect(tuiConfig).toMatchObject({
|
|
welcome: 'TUI ready',
|
|
resumeCommand: 'dsh --resume {session}',
|
|
color: false,
|
|
maxToolOutputLines: 3,
|
|
})
|
|
expect(tuiConfig.sessionId).toMatch(/^main-session-[0-9a-f-]{36}$/)
|
|
const spineConfig = calls[8]?.config as {
|
|
readonly agents: Array<Record<string, unknown>>
|
|
readonly goals: Record<string, never>
|
|
readonly maxParallelToolCalls: number
|
|
readonly persona: string
|
|
readonly toolOrder: string[]
|
|
readonly tools: { mode: string }
|
|
}
|
|
expect(spineConfig).toMatchObject({
|
|
maxParallelToolCalls: 3,
|
|
persona: 'test persona',
|
|
toolOrder: ['zulu', TOOL_ORDER_REST],
|
|
tools: { mode: 'code' },
|
|
goals: {},
|
|
})
|
|
expect(spineConfig.agents[0]).toMatchObject({
|
|
id: 'main',
|
|
provider: 'mock',
|
|
model: 'mock-model',
|
|
cwd: process.cwd(),
|
|
sessionId: tuiConfig.sessionId,
|
|
})
|
|
})
|
|
|
|
it('resumes the configured session and applies runtime defaults', () => {
|
|
const { ctx, calls } = recordingContext()
|
|
tuiAgent.composeTuiApp(ctx, {
|
|
provider: 'mock',
|
|
model: 'mock-model',
|
|
resumeSessionId: 'persisted-session',
|
|
workspaceContext: false,
|
|
})
|
|
|
|
expect(calls[2]?.config).toEqual({ root: './.sessions' })
|
|
expect(calls[5]?.config).toEqual({})
|
|
// No configured welcome forwards none: the TUI banner sweeps in without a subtitle.
|
|
expect(calls[7]?.config).toEqual({ sessionId: 'persisted-session' })
|
|
expect((calls[8]?.config as { agents: Array<Record<string, unknown>> }).agents[0]).toMatchObject({
|
|
id: 'main',
|
|
resumeSessionId: 'persisted-session',
|
|
})
|
|
})
|
|
|
|
it('normalizes an empty resume id and routes apply through the same composition', () => {
|
|
const { ctx, calls } = recordingContext()
|
|
tuiAgent.apply(ctx, {
|
|
provider: 'mock',
|
|
model: 'mock-model',
|
|
resumeSessionId: '',
|
|
goals: false,
|
|
workspaceContext: false,
|
|
})
|
|
|
|
const tuiConfig = calls[6]?.config as { sessionId: string }
|
|
expect(tuiConfig.sessionId).toMatch(/^main-session-[0-9a-f-]{36}$/)
|
|
expect((calls[7]?.config as { agents: Array<Record<string, unknown>> }).agents[0])
|
|
.toMatchObject({ sessionId: tuiConfig.sessionId })
|
|
expect(calls.map(call => call.name)).not.toContain('command-goal')
|
|
expect(calls[7]?.config).toMatchObject({ goals: false })
|
|
})
|
|
|
|
it('has the namespace-plugin export shape so the Loader keeps its schema', () => {
|
|
expect(tuiAgent.name).toBe('tui-demo')
|
|
expect(tuiAgent.Config).toBeDefined()
|
|
expect('default' in tuiAgent).toBe(false)
|
|
expect(typeof tuiAgent.apply).toBe('function')
|
|
|
|
const loader = Object.create(Loader.prototype) as Loader
|
|
const unwrapped = loader.unwrapExports(tuiAgent) as Record<string, unknown>
|
|
expect(unwrapped).toBe(tuiAgent)
|
|
expect(unwrapped.name).toBe('tui-demo')
|
|
expect(unwrapped.Config).toBeDefined()
|
|
})
|
|
})
|