refactor(agent): own model selection on each agent
This commit is contained in:
1 parent
639602e63a
commit
a9c006f9c3
237 files changed
+1051
-1734
No files matched your search
@@ -2,7 +2,7 @@ import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { unsupportedInbox } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import { unsupportedModel, unsupportedInbox } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import type { Session } from '@deepseek-ai/dsh-session'
|
||||
import type {} from '@deepseek-ai/dsh-workspace'
|
||||
@@ -31,6 +31,7 @@ async function liveAgent(ctx: Context, session: Session): Promise<Agent> {
|
||||
id: session.id,
|
||||
options: {},
|
||||
session,
|
||||
model: unsupportedModel(),
|
||||
inbox: unsupportedInbox(),
|
||||
status: 'idle',
|
||||
ctx,
|
||||
|
||||
@@ -17,7 +17,7 @@ import { subagentIdentityProjectionDefinition } from '@deepseek-ai/dsh-subagent/
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { ApiSessionAgentController } from '../src/agent.ts'
|
||||
import { SessionCommandController } from '../src/commands.ts'
|
||||
import { createInboxStub } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import { unsupportedModel, createInboxStub } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import { installSessionReadTestServices, testSessionPersistence } from './test-remote.ts'
|
||||
|
||||
declare module '@deepseek-ai/dsh-llm' {
|
||||
@@ -92,6 +92,7 @@ async function commandHarness(
|
||||
send: vi.fn(),
|
||||
inject: vi.fn(),
|
||||
session,
|
||||
model: unsupportedModel(),
|
||||
inbox,
|
||||
status: 'running',
|
||||
ctx,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { AgentModel, modelSelectionProjectionDefinition } from '@deepseek-ai/dsh-agent'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { Context, FiberState } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import { createInboxStub } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import * as AgentModelPlugin from '@deepseek-ai/dsh-agent-model'
|
||||
import AttachmentStore, { AttachmentId } from '@deepseek-ai/dsh-attachment'
|
||||
import type {
|
||||
FileAttachmentRef, ImageAttachmentRef, SaveFileAttachment, SaveFileStreamAttachment,
|
||||
@@ -38,7 +38,6 @@ async function uploadHarness(origin?: 'subagent'): Promise<{
|
||||
onTestFinished(() => ctx.fiber.dispose())
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(CommandRuntime)
|
||||
const session = ctx.sessions.create(SESSION, {
|
||||
@@ -46,14 +45,17 @@ async function uploadHarness(origin?: 'subagent'): Promise<{
|
||||
})
|
||||
const inbox = createInboxStub()
|
||||
const followup = vi.fn()
|
||||
const options = { provider: 'fixture', model: 'fixture-model' }
|
||||
const projection = await ctx.sessionProjections.register(modelSelectionProjectionDefinition)
|
||||
const agent = {
|
||||
id: session.id,
|
||||
options: { provider: 'fixture', model: 'fixture-model' },
|
||||
options,
|
||||
whenIdle: vi.fn(() => Promise.resolve()),
|
||||
runMaintenance: async () => { throw new Error('unexpected maintenance') },
|
||||
send: vi.fn(),
|
||||
inject: vi.fn(),
|
||||
session,
|
||||
model: new AgentModel(() => projection.stateOf(session), session, options),
|
||||
inbox,
|
||||
status: 'idle',
|
||||
ctx,
|
||||
|
||||
@@ -2,7 +2,6 @@ import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import * as AgentModelPlugin from '@deepseek-ai/dsh-agent-model'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import SessionStore, { SESSION_FORMAT_VERSION, SessionId, SessionLogOffset } from '@deepseek-ai/dsh-session'
|
||||
import type { SessionEvent, SessionHeader } from '@deepseek-ai/dsh-session'
|
||||
@@ -26,7 +25,6 @@ describe('SessionController facade', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const sessionId = SessionId('controller-session')
|
||||
const header: SessionHeader = {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* metadata-only listing, Agent-free history reads, subagent ownership
|
||||
* isolation, and prompt failure mapping.
|
||||
*/
|
||||
import { AgentModel, modelSelectionProjectionDefinition } from '@deepseek-ai/dsh-agent'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
|
||||
import { SESSION_FORMAT_VERSION, SessionLogOffset, SessionSeq } from '@deepseek-ai/dsh-session'
|
||||
@@ -17,8 +18,7 @@ import { createUserMessage, MessageId } from '@deepseek-ai/dsh-llm'
|
||||
import { snapshotSubagentDescriptor } from '@deepseek-ai/dsh-subagent'
|
||||
import { createInboxStub, mountAgentLoopTestDependencies, mountAgentLoopTestHarness } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import type { Agent, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import * as AgentModelPlugin from '@deepseek-ai/dsh-agent-model'
|
||||
import type { SessionEvent, SessionHeader, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import type { Session, SessionEvent, SessionHeader, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AttachmentStore from '@deepseek-ai/dsh-attachment'
|
||||
import type { SessionPromptRequest, SessionRequestId } from '../src/types.ts'
|
||||
import {
|
||||
@@ -84,7 +84,6 @@ describe('sessions.list cold merge', () => {
|
||||
try {
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const historical = header('format-historical', 100)
|
||||
const current = header('format-current', 200)
|
||||
@@ -251,7 +250,6 @@ describe('attached updatedAt tracks human prompts', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const remote = await createSessionTestRemote(ctx, { defaultModelSelection: () => ({ provider: 'p', model: 'm' }), cwd: '/tmp' })
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
@@ -397,7 +395,6 @@ describe('Remote Agent and Session lookup policy', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const remote = await createSessionTestRemote(ctx, {
|
||||
defaultModelSelection: () => ({ provider: 'p', model: 'm' }),
|
||||
@@ -419,7 +416,6 @@ describe('Remote Agent and Session lookup policy', () => {
|
||||
await ctx.plugin(TypertRegistry)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const sessionId = sid('session-remote-cold')
|
||||
const meta = header(sessionId, 1000)
|
||||
@@ -461,7 +457,6 @@ describe('Remote Agent and Session lookup policy', () => {
|
||||
await ctx.plugin(TypertRegistry)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const coldId = sid('session-remote-cold-child')
|
||||
const coldMeta = header(coldId, 1000, {
|
||||
@@ -507,7 +502,6 @@ describe('Remote Agent and Session lookup policy', () => {
|
||||
await ctx.plugin(TypertRegistry)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const sessionId = sid('session-remote-resumed-child')
|
||||
const meta = header(sessionId, 1000)
|
||||
@@ -544,7 +538,6 @@ describe('subagent ownership fence', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const sessionId = sid('session-child')
|
||||
const meta = header('session-child', 1000, {
|
||||
@@ -624,7 +617,6 @@ describe('subagent ownership fence', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const sessionId = sid('session-legacy-child')
|
||||
const meta = header('session-legacy-child', 1000, {
|
||||
@@ -663,7 +655,6 @@ describe('subagent ownership fence', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const parentSession = ctx.sessions.create(sid('session-parent'), { meta: { cwd: '/proj' } })
|
||||
const parent = { id: parentSession.id, session: parentSession, status: 'idle', ctx } as Agent
|
||||
@@ -724,7 +715,6 @@ describe('subagent ownership fence', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const session = ctx.sessions.create(sid('session-ordinary-fork'), {
|
||||
seed: [{
|
||||
@@ -737,9 +727,14 @@ describe('subagent ownership fence', () => {
|
||||
inheritedEventCount: SessionLogOffset(1),
|
||||
})
|
||||
const followup = vi.fn()
|
||||
const agent = {
|
||||
id: session.id, session, inbox: inboxFor(), status: 'idle', ctx, followup,
|
||||
} as unknown as Agent
|
||||
const agent: Agent = {
|
||||
id: session.id, session, model: await modelFor(ctx, session),
|
||||
options: { provider: 'p', model: 'm' },
|
||||
inbox: inboxFor(), status: 'idle', ctx, followup,
|
||||
cancel: vi.fn(), whenIdle: () => Promise.resolve(),
|
||||
runMaintenance: async () => { throw new Error('unexpected maintenance') },
|
||||
send: vi.fn(), inject: vi.fn(), steer: vi.fn(),
|
||||
}
|
||||
await ctx.agents.register(agent)
|
||||
const remote = await createSessionTestRemote(ctx, { defaultModelSelection: () => ({ provider: 'p', model: 'm' }), cwd: '/tmp' })
|
||||
|
||||
@@ -756,13 +751,17 @@ describe('subagent ownership fence', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const session = ctx.sessions.create(sid('session-browser-zone'), { meta: { cwd: '/proj' } })
|
||||
const followup = vi.fn()
|
||||
const agent = {
|
||||
id: session.id, session, inbox: inboxFor(), status: 'idle', ctx, followup,
|
||||
} as unknown as Agent
|
||||
const agent: Agent = {
|
||||
id: session.id, session, model: await modelFor(ctx, session),
|
||||
options: { provider: 'p', model: 'm' },
|
||||
inbox: inboxFor(), status: 'idle', ctx, followup,
|
||||
cancel: vi.fn(), whenIdle: () => Promise.resolve(),
|
||||
runMaintenance: async () => { throw new Error('unexpected maintenance') },
|
||||
send: vi.fn(), inject: vi.fn(), steer: vi.fn(),
|
||||
}
|
||||
await ctx.agents.register(agent)
|
||||
const remote = await createSessionTestRemote(ctx, {
|
||||
defaultModelSelection: () => ({ provider: 'p', model: 'm' }),
|
||||
@@ -829,7 +828,6 @@ describe('degenerate composition (no persistence, no factory)', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const remote = await createSessionTestRemote(ctx, { defaultModelSelection: () => ({ provider: 'p', model: 'm' }), cwd: '/tmp' })
|
||||
|
||||
@@ -852,7 +850,6 @@ describe('degenerate composition (no persistence, no factory)', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const inspect = vi.fn()
|
||||
const stat = vi.fn(() => Promise.resolve(undefined))
|
||||
@@ -875,25 +872,31 @@ describe('degenerate composition (no persistence, no factory)', () => {
|
||||
})
|
||||
})
|
||||
|
||||
async function modelFor(ctx: Context, session: Session): Promise<AgentModel> {
|
||||
const projection = await ctx.sessionProjections.register(modelSelectionProjectionDefinition)
|
||||
return new AgentModel(() => projection.stateOf(session), session, { provider: 'p', model: 'm' })
|
||||
}
|
||||
|
||||
describe('sessions.prompt synchronous rejection', () => {
|
||||
it('rejects content without non-whitespace text or an attachment before delivery or Session events', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const session = ctx.sessions.create(sid('session-empty-prompt'))
|
||||
const options = { provider: 'p', model: 'm' }
|
||||
const followup = vi.fn()
|
||||
const steer = vi.fn()
|
||||
await ctx.agents.register({
|
||||
id: session.id,
|
||||
options: { provider: 'p', model: 'm' },
|
||||
options,
|
||||
whenIdle: vi.fn(() => Promise.resolve()),
|
||||
runMaintenance: async () => { throw new Error('unexpected maintenance') },
|
||||
send: vi.fn(),
|
||||
inject: vi.fn(),
|
||||
cancel: vi.fn(),
|
||||
session,
|
||||
model: await modelFor(ctx, session),
|
||||
inbox: inboxFor(),
|
||||
status: 'idle',
|
||||
ctx,
|
||||
@@ -984,7 +987,6 @@ describe('sessions.prompt synchronous rejection', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const session = ctx.sessions.create(sid('session-throwing'))
|
||||
// A live structural stub whose delivery verbs throw synchronously, the
|
||||
@@ -992,12 +994,17 @@ describe('sessions.prompt synchronous rejection', () => {
|
||||
await ctx.agents.register({
|
||||
id: session.id,
|
||||
session,
|
||||
model: await modelFor(ctx, session),
|
||||
inbox: inboxFor(),
|
||||
status: 'idle',
|
||||
ctx,
|
||||
options: { provider: 'p', model: 'm' },
|
||||
cancel: vi.fn(), whenIdle: () => Promise.resolve(),
|
||||
runMaintenance: async () => { throw new Error('unexpected maintenance') },
|
||||
send: vi.fn(), inject: vi.fn(),
|
||||
followup: () => { throw new Error('agent "session-throwing" lifecycle disposed') },
|
||||
steer: () => { throw new Error('agent "session-throwing" lifecycle disposed') },
|
||||
} as unknown as Agent)
|
||||
})
|
||||
const remote = await createSessionTestRemote(ctx, { defaultModelSelection: () => ({ provider: 'p', model: 'm' }), cwd: '/tmp' })
|
||||
|
||||
for (const mode of ['queue', 'steer'] as const) {
|
||||
@@ -1019,7 +1026,6 @@ describe('sessions.prompt synchronous rejection', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const sessionId = sid('race-resume')
|
||||
const meta: SessionHeader = header('race-resume', 1000)
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentHandle, CreateAgentOptions } from '@deepseek-ai/dsh-agent'
|
||||
import { mountAgentLoopTestDependencies, mountAgentLoopTestHarness } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import * as AgentModelPlugin from '@deepseek-ai/dsh-agent-model'
|
||||
import { BasicCompactionEngine } from '@deepseek-ai/dsh-compaction-basic'
|
||||
import { MockAdapter, textResponse } from '../../../core/agent-loop/tests/mock-adapter.ts'
|
||||
import { ToolCallId, createMessage, createUserMessage, ReasoningEffortId } from '@deepseek-ai/dsh-llm'
|
||||
@@ -34,7 +33,6 @@ async function composed(workspaces: readonly Workspace[] = []): Promise<Context>
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SystemPrompt, { personaPrefix: '' })
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
installSessionReadTestServices(ctx)
|
||||
ctx.provide('workspaceRegistry', { list: () => workspaces, archivedSessionIds: [] } as never)
|
||||
@@ -665,7 +663,7 @@ describe('sessions.fork', () => {
|
||||
const child = ctx.agents.get(response.value.sessionId)
|
||||
if (child === undefined) throw new Error('fork did not publish the child agent')
|
||||
expect(child.session.snapshotEvents().slice(0, child.session.inheritedEventCount)).toEqual(inherited)
|
||||
expect(ctx.agentModel.resolveForNextStep(child)).toEqual({
|
||||
expect(child.model.current()).toEqual({
|
||||
provider: 'inherited-provider', model: 'inherited-model', reasoningEffort: 'high',
|
||||
})
|
||||
await ctx.fiber.dispose()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* catalog injection, unavailable-model refusals, and the prompt-assembly
|
||||
* boundary for a running selection change.
|
||||
*/
|
||||
import { AgentModel, modelSelectionProjectionDefinition } from '@deepseek-ai/dsh-agent'
|
||||
import { createInboxStub } from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
|
||||
@@ -11,7 +12,6 @@ import { describe, expect, it, vi, onTestFinished } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import * as AgentModelPlugin from '@deepseek-ai/dsh-agent-model'
|
||||
import AttachmentStore from '@deepseek-ai/dsh-attachment'
|
||||
import LlmRuntime, { LlmAdapter, ReasoningEffortId } from '@deepseek-ai/dsh-llm'
|
||||
import type {
|
||||
@@ -99,7 +99,6 @@ async function harness(logged?: {
|
||||
await ctx.plugin(SystemPrompt, { personaPrefix: '' })
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
ctx.llm.registerAdapter(['deepseek-official'], new CatalogAdapter('DeepSeek', [
|
||||
{ provider: 'deepseek-official', id: 'deepseek-chat', name: 'DeepSeek Chat' },
|
||||
@@ -128,13 +127,16 @@ async function harness(logged?: {
|
||||
reason: 'initial',
|
||||
})
|
||||
}
|
||||
const projection = await ctx.sessionProjections.register(modelSelectionProjectionDefinition)
|
||||
const options = {
|
||||
get provider() { return ctx.agentDefaultModel.currentSelection().provider },
|
||||
get model() { return ctx.agentDefaultModel.currentSelection().model },
|
||||
get reasoningEffort() { return ctx.agentDefaultModel.currentSelection().reasoningEffort },
|
||||
}
|
||||
const agent = {
|
||||
id: session.id,
|
||||
options: {
|
||||
get provider() { return ctx.agentDefaultModel.currentSelection().provider },
|
||||
get model() { return ctx.agentDefaultModel.currentSelection().model },
|
||||
get reasoningEffort() { return ctx.agentDefaultModel.currentSelection().reasoningEffort },
|
||||
},
|
||||
options,
|
||||
model: new AgentModel(() => projection.stateOf(session), session, options),
|
||||
session,
|
||||
status: 'running',
|
||||
ctx,
|
||||
@@ -520,7 +522,7 @@ describe('Web session model selection', () => {
|
||||
model: 'deepseek-reasoner',
|
||||
reasoningEffort: 'max',
|
||||
})
|
||||
expect(ctx.agentModel.resolveForNextStep(agent)).toEqual(selected.selected)
|
||||
expect(agent.model.current()).toEqual(selected.selected)
|
||||
expect(agent.session.snapshotEvents().at(-1)).toMatchObject({
|
||||
type: 'model/selection', data: selected.selected,
|
||||
})
|
||||
@@ -581,7 +583,10 @@ describe('Web session model selection', () => {
|
||||
ctx.agents.setFactory({
|
||||
async createAgent(ownerCtx, options) {
|
||||
const session = ctx.sessions.create(options.sessionId)
|
||||
const agent: Agent = { ...template, id: session.id, session, ctx: ownerCtx, options: options.agentOptions ?? {} }
|
||||
const agentOptions = options.agentOptions ?? {}
|
||||
const projection = await ownerCtx.sessionProjections.register(modelSelectionProjectionDefinition)
|
||||
const model = new AgentModel(() => projection.stateOf(session), session, agentOptions)
|
||||
const agent: Agent = { ...template, id: session.id, session, ctx: ownerCtx, options: agentOptions, model }
|
||||
await options.setup?.(ownerCtx, agent)
|
||||
await ctx.agents.register(agent)
|
||||
return { agent, dispose: () => Promise.resolve() }
|
||||
@@ -591,9 +596,9 @@ describe('Web session model selection', () => {
|
||||
const first = expectValue(await remote.create({ cwd: '/tmp' }))
|
||||
const second = expectValue(await remote.create({ cwd: '/tmp' }))
|
||||
const agent = ctx.agents.get(first.sessionId)!
|
||||
expect(ctx.agentModel.resolveForNextStep(agent)).toEqual(stored)
|
||||
expect(agent.model.current()).toEqual(stored)
|
||||
stored = { provider: 'deepseek-official', model: 'deepseek-reasoner' }
|
||||
expect(ctx.agentModel.resolveForNextStep(agent)).toEqual(stored)
|
||||
expect(agent.model.current()).toEqual(stored)
|
||||
const selection = { ...stored, reasoningEffort: ReasoningEffortId('high') }
|
||||
// The explicit selection is identical to the live fallback, including effort.
|
||||
stored = selection
|
||||
@@ -601,7 +606,7 @@ describe('Web session model selection', () => {
|
||||
expect(agent.session.snapshotEvents().filter(event => event.type === 'model/selection'))
|
||||
.toMatchObject([{ data: selection }])
|
||||
expectValue(await remote.selectModel({ sessionId: second.sessionId, provider: 'deepseek-official', model: 'deepseek-chat' }))
|
||||
expect(ctx.agentModel.resolveForNextStep(agent)).toEqual(selection)
|
||||
expect(agent.model.current()).toEqual(selection)
|
||||
expect(currentSelection(ctx, first.sessionId)).toEqual(selection)
|
||||
})
|
||||
|
||||
@@ -634,7 +639,7 @@ describe('Web session model selection', () => {
|
||||
cwd: '/tmp',
|
||||
})
|
||||
|
||||
expect(ctx.agentModel.resolveForNextStep(agent))
|
||||
expect(agent.model.current())
|
||||
.toEqual({ provider: 'deepseek-official', model: 'deepseek-chat' })
|
||||
await ctx.fiber.dispose()
|
||||
})
|
||||
|
||||
@@ -31,7 +31,6 @@ import {
|
||||
mountAgentLoopTestDependencies,
|
||||
mountAgentLoopTestHarness,
|
||||
} from '@deepseek-ai/dsh-agent-loop-testkit'
|
||||
import * as AgentModelPlugin from '@deepseek-ai/dsh-agent-model'
|
||||
import { createSessionTestRemote, testSessionPersistence, type TestSessionRemote } from './test-remote.ts'
|
||||
|
||||
const ownedContexts = new Set<Context>()
|
||||
@@ -163,7 +162,6 @@ describe('session.history projections block', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const parent = ctx.sessions.create(SessionId('wire-seed-parent'), { meta: { cwd: '/workspace' } })
|
||||
parent.append('turn/start', { turn: 1 })
|
||||
@@ -581,7 +579,6 @@ describe('session.list projections column', () => {
|
||||
await ctx.plugin(StorageDomain, { backend: 'json' })
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.sessionProjections.register(privatePromptUnit())
|
||||
await ctx.plugin(SessionProjectionCache, { writeEveryEvents: 100, writeIntervalMs: 60_000 })
|
||||
@@ -637,7 +634,6 @@ describe('session.list projections column', () => {
|
||||
await ctx.plugin(StorageDomain, { backend: 'json' })
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(AgentModelPlugin)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.sessionProjections.register(titleProjectionDefinition)
|
||||
await ctx.plugin(SessionProjectionCache, { writeEveryEvents: 100, writeIntervalMs: 60_000 })
|
||||
|
||||
Reference in new issue
Block a user