refactor(agent-loop): separate injected context from turns

This commit is contained in:
_Kerman
2026-07-24 16:05:52 +08:00
parent 712448a2d2
commit 45fc7fda3d
45 changed files with 470 additions and 873 deletions

View File

@@ -102,7 +102,7 @@ describe('session-log invariants', () => {
} as never) }).toThrow(/seq must strictly increase/)
})
it('enforces turn numbering and enclosure', async () => {
it('enforces turn numbering and encloses events other than idle context', async () => {
const first = await setup()
const open = first.ctx.sessions.create()
open.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
@@ -119,9 +119,9 @@ describe('session-log invariants', () => {
const outside = (await setup()).ctx.sessions.create()
expect(() => outside.append('user/message', {
content: [{ type: 'text', text: 'hi' }],
source: { kind: 'user' },
}, { surfaceOp: 'append' })).toThrow(/outside any open turn/)
content: [{ type: 'text', text: 'idle context' }],
source: { kind: 'plugin', plugin: 'test' },
}, { surfaceOp: 'append' })).not.toThrow()
expect(() => outside.append('steering/message', {
turn: 1,
content: [{ type: 'text', text: 'go' }],

View File

@@ -2,7 +2,6 @@ import { describe, expect, expectTypeOf, it, vi } from 'vitest'
import { Context } from 'cordis'
import { CallId } from '@deepseek-ai/dsh-llm'
import SessionStore, {
displayPromptContent,
findLastMessageTurnEnd,
SESSION_FORMAT_VERSION,
Session,
@@ -136,35 +135,6 @@ describe('Session', () => {
expect(steeringMessage!.content).toEqual([{ type: 'text', text: 'focus on tests' }])
})
it('derives baked prompt context while exposing only the direct prompt for display', () => {
const session = new Session(SessionId('prompt-envelope'))
const event = session.append('user/message', {
content: [
{ type: 'text', text: 'background' },
{ type: 'text', text: '\n\n## My request:\n' },
{ type: 'text', text: 'question' },
],
source: { kind: 'user' },
envelope: {
displayContent: [{ type: 'text', text: 'question' }],
prefixContexts: [{ source: { kind: 'plugin', plugin: 'reference' } }],
},
}, { surfaceOp: 'append' })
expect(session.deriveMessages()).toEqual([{
role: 'user',
content: [
{ type: 'text', text: 'background' },
{ type: 'text', text: '\n\n## My request:\n' },
{ type: 'text', text: 'question' },
],
}])
expect(displayPromptContent(event.data)).toEqual([{ type: 'text', text: 'question' }])
expect(Object.isFrozen(event.data.envelope?.displayContent)).toBe(true)
expect(new Session(SessionId('prompt-envelope-replay'), session.events).deriveMessages())
.toEqual(session.deriveMessages())
})
it('keeps context source durable in the event while hiding it from the projection', () => {
const session = new Session(SessionId('s2-raw'))
session.append('user/message', {