mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
git mv the 12 packages from session-persistence/, session-projection/, session-title/, and telemetry/ into one session/ group per the regrouping RFC; merge the four group READMEs into one bilingual triplet; rewrite the group segment in tsconfig references (intra-group references shorten to ../<pkg>), tsconfig.base.json paths/globs, knip.json keys, vitest include, gate scripts, and authored doc/note citations; regenerate module graph, doc graphs, catalogs, and the lockfile importer keys. No npm names change. Full unit suite: 8779 passed; the 18 reported failures reproduce as env flakes (ambient-proxy IPv6 tunneling, watched-dir inotify timeouts under parallel load) — each passes in isolation with NO_PROXY set, matching their known pre-existing behavior on master.
120 lines
4.3 KiB
TypeScript
120 lines
4.3 KiB
TypeScript
import { afterEach, describe, expect, it } from 'vitest'
|
|
import { Context } from 'cordis'
|
|
import Loader from '@cordisjs/plugin-loader'
|
|
import Include from '@cordisjs/plugin-include'
|
|
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { pathToFileURL } from 'node:url'
|
|
import LlmService, { createUserMessage, LlmAdapter } from '@deepseek-ai/dsh-llm'
|
|
import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm'
|
|
import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
|
|
import SessionTitleService from '@deepseek-ai/dsh-session-title'
|
|
import * as providerPlugin from '@deepseek-ai/dsh-session-title-first-message-llm'
|
|
|
|
let root: string | undefined
|
|
let context: Context | undefined
|
|
|
|
class LoaderAdapter extends LlmAdapter {
|
|
readonly requests: GenerateOptions[] = []
|
|
|
|
override async * stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
|
|
this.requests.push(options)
|
|
yield { type: 'text-delta', index: 0, text: 'Loader composed title' }
|
|
yield { type: 'finish', reason: { kind: 'stop' } }
|
|
}
|
|
}
|
|
|
|
afterEach(async () => {
|
|
await context?.fiber.dispose()
|
|
context = undefined
|
|
if (root !== undefined) await rm(root, { recursive: true, force: true })
|
|
root = undefined
|
|
})
|
|
|
|
async function loadComposition(): Promise<Context> {
|
|
root = await mkdtemp(join(tmpdir(), 'dsh-title-loader-'))
|
|
const configPath = join(root, 'cordis.yml')
|
|
await writeFile(configPath, [
|
|
"- name: '@deepseek-ai/dsh-llm'",
|
|
"- name: '@deepseek-ai/dsh-session'",
|
|
"- name: '@deepseek-ai/dsh-session-title'",
|
|
' config:',
|
|
' fallbackMaxWords: 5',
|
|
' fallbackMaxBytes: 40',
|
|
' maxTitleBytes: 80',
|
|
"- name: '@deepseek-ai/dsh-session-title-first-message-llm'",
|
|
' config:',
|
|
' targetWords: 5',
|
|
' targetCjkCharacters: 10',
|
|
' maxInputBytes: 1000',
|
|
' maxOutputTokens: 32',
|
|
' timeoutMs: 1000',
|
|
" provider: 'title-route'",
|
|
" model: 'title-model'",
|
|
'',
|
|
].join('\n'))
|
|
|
|
context = new Context()
|
|
context.baseUrl = pathToFileURL(root).href + '/'
|
|
await context.plugin(Loader)
|
|
context.loader.builtins.include = Include
|
|
const modules = new Map<string, unknown>([
|
|
['@deepseek-ai/dsh-llm', LlmService],
|
|
['@deepseek-ai/dsh-session', SessionStore],
|
|
['@deepseek-ai/dsh-session-title', SessionTitleService],
|
|
['@deepseek-ai/dsh-session-title-first-message-llm', providerPlugin],
|
|
])
|
|
context.loader.internal = {
|
|
version: 'v2',
|
|
async import(specifier: string) {
|
|
if (!modules.has(specifier)) throw new Error(`unexpected Loader import: ${specifier}`)
|
|
return modules.get(specifier)
|
|
},
|
|
} as unknown as NonNullable<typeof context.loader.internal>
|
|
await context.loader.create({
|
|
name: 'cordis:include',
|
|
config: { path: pathToFileURL(configPath).href },
|
|
})
|
|
await context.loader.await()
|
|
return context
|
|
}
|
|
|
|
describe('session-title Loader composition', () => {
|
|
it('loads the service and one model provider with required deployment policy', async () => {
|
|
const ctx = await loadComposition()
|
|
const unloaded = [...ctx.loader.entries()]
|
|
.filter(entry => entry.fiber === undefined && !entry.disabled)
|
|
.map(entry => entry.options.name)
|
|
expect(unloaded).toEqual([])
|
|
|
|
const adapter = new LoaderAdapter()
|
|
ctx.llm.registerAdapter(['title-route'], adapter)
|
|
const session = ctx.sessions.create(SessionId('loader-title'))
|
|
session.append('turn/start', {
|
|
turn: 1,
|
|
})
|
|
const message = session.append('user/message', createUserMessage({
|
|
content: [{ type: 'text', text: 'Compose a title through Loader' }],
|
|
source: { kind: 'user' },
|
|
}), { surfaceOp: 'append' })
|
|
await new Promise(resolve => setTimeout(resolve, 0))
|
|
session.append('request/header', {
|
|
header: { config: { provider: 'main-route', model: 'main-model' } },
|
|
reason: 'initial',
|
|
})
|
|
await new Promise(resolve => setTimeout(resolve, 0))
|
|
|
|
expect(adapter.requests[0]).toMatchObject({ provider: 'title-route', model: 'title-model' })
|
|
expect(ctx.sessionTitle.get(session)).toMatchObject({
|
|
title: 'Loader composed title',
|
|
messageSeqs: [message.seq],
|
|
source: {
|
|
kind: 'provider',
|
|
provider: 'session-title-first-message-llm',
|
|
model: { provider: 'title-route', model: 'title-model' },
|
|
},
|
|
})
|
|
})
|
|
})
|