Roles: re-point reused Sessions when a role model drifts
A role model only seeded brand-new Sessions, so Workers created before a settings change kept their old route forever — the operator's complaint that the default model 'did not take effect'. On dispatch, ensure() now compares the durable selection or header of an existing Session against the configured role model and appends a model/selection event when they drift, leaving the deployment default alone. Seven unit cases cover drift, idempotence, effort, and precedence.
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { afterEach, expect, it, vi } from 'vitest'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import { agentEvents, installModelSelection, type Agent, type ModelSelection, type ModelSelectionRef } from '@deepseek-ai/dsh-agent'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import { ReasoningEffortId } from '@deepseek-ai/dsh-llm'
|
||||
import { initializeRoleModel } from '../src/app/role-models.ts'
|
||||
import { alignRoleModel, initializeRoleModel } from '../src/app/role-models.ts'
|
||||
const contexts: Context[] = []
|
||||
afterEach(async () => { await Promise.all(contexts.splice(0).map(ctx => ctx.fiber.dispose())); vi.restoreAllMocks() })
|
||||
async function fixture() {
|
||||
@@ -63,3 +63,64 @@ it('inherits the host when unset and fails unavailable routes before recording a
|
||||
await expect(initializeRoleModel(ctx, agent, { provider: 'unknown', model: 'x' })).rejects.toThrow('unknown provider')
|
||||
expect(agent.session.snapshotEvents().some(event => event.type === 'model/selection')).toBe(false)
|
||||
})
|
||||
describe('alignRoleModel', () => {
|
||||
const selections = (agent: Agent) => agent.session.snapshotEvents().filter(event => event.type === 'model/selection')
|
||||
it('re-points a reused Session whose durable header drifted from the configured model', async () => {
|
||||
const { ctx, agent, flush, record } = await fixture()
|
||||
record({ provider: 'deepseek-official', model: 'deepseek-flash', reasoningEffort: ReasoningEffortId('low') })
|
||||
await alignRoleModel(ctx, agent, { provider: 'wp', model: 'wm' })
|
||||
const events = selections(agent)
|
||||
expect(events).toHaveLength(1)
|
||||
expect(events[0]?.data).toEqual({ provider: 'wp', model: 'wm' })
|
||||
expect(flush).toHaveBeenCalledOnce()
|
||||
})
|
||||
it('is an idempotent no-op when the durable selection already matches the configured model', async () => {
|
||||
const { ctx, agent, resolve, flush } = await fixture()
|
||||
agent.session.append('model/selection', { provider: 'wp', model: 'wm' })
|
||||
flush.mockClear()
|
||||
await alignRoleModel(ctx, agent, { provider: 'wp', model: 'wm' })
|
||||
expect(resolve).toHaveBeenCalledOnce()
|
||||
expect(selections(agent)).toHaveLength(1)
|
||||
expect(flush).not.toHaveBeenCalled()
|
||||
})
|
||||
it('returns without resolving or recording anything when no model is configured', async () => {
|
||||
const { ctx, agent, resolve, flush } = await fixture()
|
||||
await alignRoleModel(ctx, agent, null)
|
||||
expect(resolve).not.toHaveBeenCalled()
|
||||
expect(selections(agent)).toHaveLength(0)
|
||||
expect(flush).not.toHaveBeenCalled()
|
||||
})
|
||||
it('treats an equal configured reasoning effort as the same route', async () => {
|
||||
const { ctx, agent, flush } = await fixture()
|
||||
agent.session.append('model/selection', { provider: 'wp', model: 'wm', reasoningEffort: ReasoningEffortId('low') })
|
||||
await alignRoleModel(ctx, agent, { provider: 'wp', model: 'wm', reasoningEffort: 'low' })
|
||||
expect(selections(agent)).toHaveLength(1)
|
||||
expect(flush).not.toHaveBeenCalled()
|
||||
})
|
||||
it('re-points when only the reasoning effort differs and records the configured effort', async () => {
|
||||
const { ctx, agent, flush } = await fixture()
|
||||
agent.session.append('model/selection', { provider: 'wp', model: 'wm', reasoningEffort: ReasoningEffortId('low') })
|
||||
await alignRoleModel(ctx, agent, { provider: 'wp', model: 'wm', reasoningEffort: 'high' })
|
||||
const events = selections(agent)
|
||||
expect(events).toHaveLength(2)
|
||||
expect(events[1]?.data).toEqual({ provider: 'wp', model: 'wm', reasoningEffort: ReasoningEffortId('high') })
|
||||
expect(flush).toHaveBeenCalledOnce()
|
||||
})
|
||||
it('follows a selection that supersedes an older header instead of the header', async () => {
|
||||
const { ctx, agent, flush, record } = await fixture()
|
||||
record({ provider: 'old', model: 'header' })
|
||||
agent.session.append('model/selection', { provider: 'wp', model: 'wm' })
|
||||
flush.mockClear()
|
||||
await alignRoleModel(ctx, agent, { provider: 'wp', model: 'wm' })
|
||||
expect(selections(agent)).toHaveLength(1)
|
||||
expect(flush).not.toHaveBeenCalled()
|
||||
})
|
||||
it('treats a Session with no durable route as drift and seeds the configured model', async () => {
|
||||
const { ctx, agent, flush } = await fixture()
|
||||
await alignRoleModel(ctx, agent, { provider: 'wp', model: 'wm' })
|
||||
const events = selections(agent)
|
||||
expect(events).toHaveLength(1)
|
||||
expect(events[0]?.data).toEqual({ provider: 'wp', model: 'wm' })
|
||||
expect(flush).toHaveBeenCalledOnce()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user