mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
test(api): complete migrated Remote coverage
This commit is contained in:
@@ -305,9 +305,9 @@ describe('Web session model selection', () => {
|
||||
model: 'private-preview',
|
||||
reasoningEffort: ReasoningEffortId('max'),
|
||||
})
|
||||
createSessionTestRemote(ctx, { defaultModelSelection: () => ({ provider: 'deepseek-official', model: 'deepseek-chat' }), cwd: '/tmp' })
|
||||
const remote = createSessionTestRemote(ctx, { defaultModelSelection: () => ({ provider: 'deepseek-official', model: 'deepseek-chat' }), cwd: '/tmp' })
|
||||
|
||||
const catalog = await buildModelCatalog(ctx)
|
||||
const catalog = expectValue(await remote.modelCatalog())
|
||||
expect(currentSelection(ctx, sessionId)).toEqual({
|
||||
provider: 'deepseek-official',
|
||||
model: 'private-preview',
|
||||
|
||||
@@ -2,7 +2,11 @@ import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { createSessionTestRemote, testSessionPersistence } from './test-remote.ts'
|
||||
import {
|
||||
createSessionTestController,
|
||||
createSessionTestRemote,
|
||||
testSessionPersistence,
|
||||
} from './test-remote.ts'
|
||||
|
||||
async function context(): Promise<Context> {
|
||||
const ctx = new Context()
|
||||
@@ -92,4 +96,54 @@ describe('session/openWorkspacePath', () => {
|
||||
await expect(remote.openWorkspacePath({ sessionId, path: 'result.html' }, aborted.signal))
|
||||
.resolves.toMatchObject({ ok: false, error: { code: 'cancelled' } })
|
||||
})
|
||||
|
||||
it('classifies inspection cancellation and non-session failures', async () => {
|
||||
const ctx = await context()
|
||||
const controller = createSessionTestController(ctx, {
|
||||
defaultModelSelection: () => ({ provider: 'p', model: 'm' }),
|
||||
cwd: '/default',
|
||||
})
|
||||
const inspect = vi.spyOn(controller, 'inspect')
|
||||
const aborted = new AbortController()
|
||||
inspect.mockImplementationOnce(async () => {
|
||||
aborted.abort(new Error('cancelled'))
|
||||
throw new Error('inspection stopped')
|
||||
})
|
||||
await expect(controller.openWorkspacePath({
|
||||
sessionId: SessionId('inspection-cancelled'), path: 'result.html',
|
||||
}, aborted.signal)).rejects.toMatchObject({ failure: { code: 'cancelled' } })
|
||||
|
||||
inspect.mockRejectedValueOnce('storage offline')
|
||||
await expect(controller.openWorkspacePath({
|
||||
sessionId: SessionId('inspection-failed'), path: 'result.html',
|
||||
}, new AbortController().signal)).rejects.toMatchObject({
|
||||
failure: { code: 'internal', message: expect.stringContaining('storage offline') },
|
||||
})
|
||||
})
|
||||
|
||||
it('classifies opener cancellation and non-Error failures', async () => {
|
||||
const ctx = await context()
|
||||
const sessionId = SessionId('open-error-kinds')
|
||||
ctx.sessions.create(sessionId, { meta: { cwd: '/workspace/project' } })
|
||||
const aborted = new AbortController()
|
||||
const openPath = vi.fn()
|
||||
.mockImplementationOnce(async () => {
|
||||
aborted.abort(new Error('cancelled'))
|
||||
throw new Error('opening stopped')
|
||||
})
|
||||
.mockRejectedValueOnce('desktop unavailable')
|
||||
const controller = createSessionTestController(ctx, {
|
||||
defaultModelSelection: () => ({ provider: 'p', model: 'm' }),
|
||||
cwd: '/default',
|
||||
openPath,
|
||||
})
|
||||
|
||||
await expect(controller.openWorkspacePath({ sessionId, path: 'first.html' }, aborted.signal))
|
||||
.rejects.toMatchObject({ failure: { code: 'cancelled' } })
|
||||
await expect(controller.openWorkspacePath({
|
||||
sessionId, path: 'second.html',
|
||||
}, new AbortController().signal)).rejects.toMatchObject({
|
||||
failure: { code: 'internal', message: 'path open failed: desktop unavailable' },
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -188,4 +188,41 @@ describe('SessionSkillCatalog', () => {
|
||||
failure: { code: 'internal', message: expect.stringContaining('skill registry is absent') },
|
||||
})
|
||||
})
|
||||
|
||||
it('rejects observations without projections or a project cwd', async () => {
|
||||
const ctx = await context()
|
||||
const sessionId = SessionId('incomplete-skills')
|
||||
const withoutProjections = { ...observation(sessionId, { cwd: '/project' }), projections: undefined }
|
||||
const observeSession = vi.fn()
|
||||
.mockResolvedValueOnce(withoutProjections)
|
||||
.mockResolvedValueOnce(observation(sessionId))
|
||||
ctx.provide('sessionQuery', { observeSession } as never)
|
||||
const catalog = new SessionSkillCatalog(ctx)
|
||||
|
||||
await expect(catalog.list({ sessionId }, new AbortController().signal))
|
||||
.rejects.toMatchObject({
|
||||
failure: { code: 'internal', message: expect.stringContaining('projected Session observation') },
|
||||
})
|
||||
await expect(catalog.list({ sessionId }, new AbortController().signal))
|
||||
.rejects.toMatchObject({
|
||||
failure: { code: 'internal', message: expect.stringContaining('has no project cwd') },
|
||||
})
|
||||
})
|
||||
|
||||
it('classifies a provider listing failure', async () => {
|
||||
const ctx = await context()
|
||||
const sessionId = SessionId('failed-skills')
|
||||
ctx.provide('sessionQuery', {
|
||||
observeSession: () => Promise.resolve(observation(sessionId, { cwd: '/project' })),
|
||||
} as never)
|
||||
ctx.provide('skills', {
|
||||
list: () => Promise.reject(new Error('catalog offline')),
|
||||
} as never)
|
||||
const catalog = new SessionSkillCatalog(ctx)
|
||||
|
||||
await expect(catalog.list({ sessionId }, new AbortController().signal))
|
||||
.rejects.toMatchObject({
|
||||
failure: { code: 'internal', message: 'skill listing failed: Error: catalog offline' },
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from '@deepseek-ai/dsh-typert-protocol'
|
||||
import SessionController from '../src/index.ts'
|
||||
import type {
|
||||
ModelCatalog,
|
||||
SessionAttachmentRequest,
|
||||
SessionAttachmentValue,
|
||||
SessionCancelRequest,
|
||||
@@ -54,6 +55,7 @@ export interface TestSessionRemote {
|
||||
search(request: SessionSearchRequest, signal?: AbortSignal): Promise<RemoteResult<SessionSearchValue>>
|
||||
create(request: SessionCreateRequest): Promise<RemoteResult<SessionCreateValue>>
|
||||
selectModel(request: SessionSelectModelRequest): Promise<RemoteResult<SessionSelectModelValue>>
|
||||
modelCatalog(): Promise<RemoteResult<ModelCatalog>>
|
||||
rename(request: SessionRenameRequest): Promise<RemoteResult<SessionRenameValue>>
|
||||
fork(request: SessionForkRequest): Promise<RemoteResult<SessionForkValue>>
|
||||
prompt(request: SessionPromptRequest, signal?: AbortSignal): Promise<RemoteResult<SessionPromptValue>>
|
||||
@@ -241,6 +243,7 @@ export function createSessionTestRemote(
|
||||
),
|
||||
create: request => remoteResult(() => direct.create(request)),
|
||||
selectModel: request => remoteResult(() => direct.selectModel(request)),
|
||||
modelCatalog: () => remoteResult(() => direct.modelCatalog()),
|
||||
rename: request => remoteResult(() => direct.rename(request)),
|
||||
fork: request => remoteResult(() => direct.fork(request)),
|
||||
prompt: (request, signal = new AbortController().signal) => remoteResult(
|
||||
|
||||
Reference in New Issue
Block a user