feat(session): add cross-session references

This commit is contained in:
Yichen Jiang
2026-07-21 16:46:48 +08:00
parent 9a5c81f9e5
commit 32d786c439
81 changed files with 2837 additions and 160 deletions
@@ -121,6 +121,64 @@ describe('session-query exact reads', () => {
.toEqual(['shadowed', 'log-only', 'current'])
})
it('reads a detached current surface with its raw-log capture boundary', async () => {
const ctx = await liveContext()
const session = ctx.sessions.create(SessionId('surface-snapshot'), { meta: { cwd: '/work' } })
const first = session.append(
'user/message',
{ content: [{ type: 'text', text: 'old' }], source: { kind: 'user' } },
{ surfaceOp: 'append' },
)
session.append('assistant/chunk', {
turn: 1,
step: 1,
chunk: { type: 'text-delta', index: 0, text: 'draft' },
})
session.append(
'user/message',
{ content: [{ type: 'text', text: 'checkpoint' }], source: { kind: 'plugin', plugin: 'compact' } },
{ surfaceOp: { op: 'replace', start: first.seq, end: first.seq }, sourceEventSeqs: [first.seq] },
)
const retained = session.append(
'user/message',
{ content: [{ type: 'text', text: 'retained tail' }], source: { kind: 'user' } },
{ surfaceOp: 'append' },
)
session.append(
'user/message',
{ content: [{ type: 'text', text: 'latest checkpoint' }], source: { kind: 'plugin', plugin: 'compact' } },
{ surfaceOp: { op: 'replace', start: 2, end: retained.seq }, sourceEventSeqs: [2, retained.seq] },
)
session.append(
'assistant/message',
{ provenance: { provider: 'mock', model: 'mock' }, turn: 2, step: 1, content: [{ type: 'text', text: 'latest answer' }] },
{ surfaceOp: 'append' },
)
const snapshot = await ctx.sessionQuery.readSurface(session.id)
expect(snapshot.session).toEqual(session.header)
expect(snapshot.capturedThroughSeq).toBe(5)
expect(snapshot.events.map(event => [event.seq, event.type])).toEqual([
[4, 'user/message'],
[5, 'assistant/message'],
])
if (snapshot.events[0]?.type !== 'user/message') throw new Error('expected current user message')
snapshot.events[0].data.content = []
Object.assign(snapshot.session, { cwd: '/mutated' })
expect(session.events[4]?.type === 'user/message' && session.events[4].data.content).toHaveLength(1)
expect(session.header.cwd).toBe('/work')
})
it('returns an empty current surface with a null capture boundary', async () => {
const ctx = await liveContext()
const session = ctx.sessions.create(SessionId('empty-surface'))
await expect(ctx.sessionQuery.readSurface(session.id)).resolves.toMatchObject({
capturedThroughSeq: null,
events: [],
})
})
it('returns a bounded detached raw-event window and validates the request', async () => {
const ctx = await liveContext({ readWindowMax: 1 })
const session = ctx.sessions.create(SessionId('window'), { meta: { cwd: '/work' } })
@@ -173,8 +231,15 @@ describe('session-query exact reads', () => {
const liveRead = await ctx.sessionQuery.readEvent({ sessionId: shared.id, seq: 0 })
expect(liveRead.target.type === 'user/message' && liveRead.target.data.content[0])
.toMatchObject({ text: 'live' })
await expect(ctx.sessionQuery.readSurface(shared.id)).resolves.toMatchObject({
events: [{ data: { content: [{ text: 'live' }] } }],
})
await expect(ctx.sessionQuery.readEvent({ sessionId: durable.id, seq: 0 }))
.resolves.toMatchObject({ session: durable })
await expect(ctx.sessionQuery.readSurface(durable.id)).resolves.toMatchObject({
session: durable,
events: [{ data: { content: [{ text: 'durable' }] } }],
})
const sharedEntry = TestPersistence.entries.get(shared.id)!
sharedEntry.meta = { ...sharedEntry.meta, cwd: '/conflict' }