mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Machine-produced by `pnpm run rescope-vendor --apply` plus the regeneration it prints: `pnpm install` for the lockfile, `pnpm run gen-third-party-notices`, `verify-translation-pairing --write` for the touched bilingual pairs, `gen-doc-graphs`, and one typert snapshot whose ids embed character offsets. `pnpm run rescope-vendor --check` verifies the result. Renames nine vendored packages (cordis, cosmokit, schemastery and the six @cordisjs plugins) and every reference that resolves them: manifest names and dependency keys, module specifiers including declare-module merges, cordis.yml plugin names, tsconfig paths, every Markdown fence, and `docs/` prose. Directory names, upstream versions, and dependency ranges are unchanged, so vendor/README.md still reads as an upstream snapshot; its manifest table gains an upstream-name column so THIRD_PARTY_NOTICES keeps MIT attribution pointed at each fork's origin. The tutorial tier follows the rename end to end: its yaml fences named plugins the Loader can no longer resolve, its `ts ignore-check` fences disagreed with the compiled fences beside them, and its prose quoted both. The contracts that told readers to keep upstream names — the root convention and the vendoring cookbook's tree comment and manifest invariant — now say to rescope instead. Two rules read `@deepseek-ai/` as "another workspace plugin": the client bundle purity gate now names the vendored libraries a browser bundle inlines, and the files where a bare `cordis` is an agent-preset id keep that product data.
99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
/** Default Agent model settings layered over a real settings provider. */
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
import { Context } from '@deepseek-ai/cordis'
|
|
import AgentDefaultModelService, { AGENT_DEFAULT_MODEL_SETTINGS_NAMESPACE } from '../src/index.ts'
|
|
import { Settings } from '@deepseek-ai/dsh-settings'
|
|
import type { SettingsNamespace } from '@deepseek-ai/dsh-settings'
|
|
import { ReasoningEffortId } from '@deepseek-ai/dsh-llm'
|
|
|
|
/** The smallest real provider: one in-memory document, always writable. */
|
|
class MemorySettings extends Settings {
|
|
doc: Record<string, unknown> = {}
|
|
|
|
get writable(): boolean {
|
|
return true
|
|
}
|
|
|
|
protected load(): Promise<Record<string, unknown>> {
|
|
return Promise.resolve(structuredClone(this.doc))
|
|
}
|
|
|
|
protected persist(ns: SettingsNamespace, section: Record<string, unknown>): Promise<void> {
|
|
this.doc = { ...this.doc, [ns]: structuredClone(section) }
|
|
return Promise.resolve()
|
|
}
|
|
}
|
|
|
|
async function boot(): Promise<{
|
|
ctx: Context
|
|
settingsFiber: Context['fiber']
|
|
defaultModel: AgentDefaultModelService
|
|
}> {
|
|
const ctx = new Context()
|
|
const settingsFiber = ctx.plugin(MemorySettings)
|
|
await settingsFiber.await()
|
|
await ctx.plugin(AgentDefaultModelService, {
|
|
provider: 'deepseek-official',
|
|
model: 'deepseek-v4-flash',
|
|
})
|
|
return { ctx, settingsFiber, defaultModel: ctx.agentDefaultModel }
|
|
}
|
|
|
|
describe('AgentDefaultModelService', () => {
|
|
it('resolves the user layer over the composition entry', async () => {
|
|
const bench = await boot()
|
|
expect(bench.defaultModel.currentSelection()).toEqual({
|
|
provider: 'deepseek-official', model: 'deepseek-v4-flash',
|
|
})
|
|
|
|
await bench.defaultModel.saveSelection({
|
|
provider: 'acme-gateway', model: 'acme-large', reasoningEffort: ReasoningEffortId('high'),
|
|
})
|
|
expect(bench.defaultModel.currentSelection()).toEqual({
|
|
provider: 'acme-gateway', model: 'acme-large', reasoningEffort: 'high',
|
|
})
|
|
await bench.ctx.fiber.dispose()
|
|
})
|
|
|
|
it('clears a stored effort when the saved selection has none', async () => {
|
|
const bench = await boot()
|
|
await bench.defaultModel.saveSelection({
|
|
provider: 'acme-gateway', model: 'acme-large', reasoningEffort: ReasoningEffortId('high'),
|
|
})
|
|
await bench.defaultModel.saveSelection({ provider: 'acme-gateway', model: 'acme-plain' })
|
|
expect(bench.defaultModel.currentSelection()).toEqual({ provider: 'acme-gateway', model: 'acme-plain' })
|
|
await bench.ctx.fiber.dispose()
|
|
})
|
|
|
|
it('layers a hand-written partial section over the entry', async () => {
|
|
const bench = await boot()
|
|
await bench.settingsFiber.ctx.settings.replace(AGENT_DEFAULT_MODEL_SETTINGS_NAMESPACE, {
|
|
model: 'deepseek-reasoner',
|
|
})
|
|
expect(bench.defaultModel.currentSelection()).toEqual({
|
|
provider: 'deepseek-official', model: 'deepseek-reasoner',
|
|
})
|
|
await bench.ctx.fiber.dispose()
|
|
})
|
|
|
|
it('falls back to the composition entry when the settings provider detaches', async () => {
|
|
const bench = await boot()
|
|
await bench.defaultModel.saveSelection({ provider: 'acme-gateway', model: 'acme-large' })
|
|
expect(bench.defaultModel.currentSelection().provider).toBe('acme-gateway')
|
|
await bench.settingsFiber.dispose()
|
|
expect(bench.defaultModel.currentSelection()).toEqual({
|
|
provider: 'deepseek-official', model: 'deepseek-v4-flash',
|
|
})
|
|
await bench.ctx.fiber.dispose()
|
|
})
|
|
|
|
it('keeps the composition entry when no settings provider is mounted', async () => {
|
|
const ctx = new Context()
|
|
await ctx.plugin(AgentDefaultModelService, { provider: 'p', model: 'm' })
|
|
await ctx.agentDefaultModel.saveSelection({ provider: 'other', model: 'other' })
|
|
expect(ctx.agentDefaultModel.currentSelection()).toEqual({ provider: 'p', model: 'm' })
|
|
await ctx.fiber.dispose()
|
|
})
|
|
})
|