refactor: identify and freeze messages at creation
This commit is contained in:
99
packages/llm/llm/tests/message.spec.ts
Normal file
99
packages/llm/llm/tests/message.spec.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
CallId,
|
||||
createAssistantMessage,
|
||||
createToolResultMessage,
|
||||
createUserMessage,
|
||||
freezeMessage,
|
||||
MessageId,
|
||||
} from '@deepseek-ai/dsh-llm'
|
||||
|
||||
describe('message construction', () => {
|
||||
it('assigns identity immediately and returns a detached deep-frozen message', () => {
|
||||
const input = {
|
||||
content: [{ type: 'text' as const, text: 'original' }],
|
||||
source: { kind: 'plugin' as const, plugin: 'test' },
|
||||
}
|
||||
|
||||
const message = createUserMessage(input)
|
||||
|
||||
expect(message.id).toEqual(expect.any(String))
|
||||
expect(message.role).toBe('user')
|
||||
expect(message.id).not.toHaveLength(0)
|
||||
expect(message).not.toBe(input)
|
||||
expect(Object.isFrozen(message)).toBe(true)
|
||||
expect(Object.isFrozen(message.content)).toBe(true)
|
||||
expect(Object.isFrozen(message.content[0])).toBe(true)
|
||||
expect(Object.isFrozen(message.source)).toBe(true)
|
||||
|
||||
input.content[0]!.text = 'caller mutation'
|
||||
expect(message.content).toEqual([{ type: 'text', text: 'original' }])
|
||||
expect(() => {
|
||||
(message.content[0] as { text: string }).text = 'observer mutation'
|
||||
}).toThrow()
|
||||
})
|
||||
|
||||
it('freezes an existing identity without minting a replacement', () => {
|
||||
const id = MessageId('existing')
|
||||
const input = {
|
||||
id,
|
||||
role: 'assistant' as const,
|
||||
content: [{ type: 'text' as const, text: 'answer' }],
|
||||
source: { kind: 'model' as const, provider: 'test', model: 'test' },
|
||||
}
|
||||
|
||||
const message = freezeMessage(input)
|
||||
|
||||
expect(message).not.toBe(input)
|
||||
expect(message.id).toBe(id)
|
||||
expect(Object.isFrozen(message)).toBe(true)
|
||||
expect(Object.isFrozen(message.content[0])).toBe(true)
|
||||
})
|
||||
|
||||
it('fixes the assistant role and model source kind at creation', () => {
|
||||
const message = createAssistantMessage({
|
||||
content: [{ type: 'text', text: 'answer' }],
|
||||
source: {
|
||||
provider: 'test-provider',
|
||||
model: 'test-model',
|
||||
replayState: { request: 1 },
|
||||
},
|
||||
})
|
||||
|
||||
expect(message).toMatchObject({
|
||||
role: 'assistant',
|
||||
source: {
|
||||
kind: 'model',
|
||||
provider: 'test-provider',
|
||||
model: 'test-model',
|
||||
replayState: { request: 1 },
|
||||
},
|
||||
})
|
||||
expect(message.id).not.toHaveLength(0)
|
||||
expect(Object.isFrozen(message)).toBe(true)
|
||||
expect(Object.isFrozen(message.source)).toBe(true)
|
||||
})
|
||||
|
||||
it('couples tool-result content and provenance to one call identity', () => {
|
||||
const callId = CallId('call-1')
|
||||
const message = createToolResultMessage({
|
||||
callId,
|
||||
content: [{ type: 'text', text: 'result' }],
|
||||
isError: false,
|
||||
})
|
||||
|
||||
expect(message).toMatchObject({
|
||||
role: 'user',
|
||||
source: { kind: 'tool', callId },
|
||||
content: [{
|
||||
type: 'tool-result',
|
||||
toolCallId: callId,
|
||||
content: [{ type: 'text', text: 'result' }],
|
||||
isError: false,
|
||||
}],
|
||||
})
|
||||
expect(message.id).not.toHaveLength(0)
|
||||
expect(Object.isFrozen(message)).toBe(true)
|
||||
expect(Object.isFrozen(message.content[0])).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user