mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
116 lines
4.4 KiB
TypeScript
116 lines
4.4 KiB
TypeScript
import { readFile } from 'node:fs/promises'
|
|
import { join } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
|
import {
|
|
assertFixtureInventory,
|
|
compareOrRefreshGolden,
|
|
launchWebScaffold,
|
|
seedSession,
|
|
type WebScaffold,
|
|
} from './scaffold.ts'
|
|
|
|
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/message-feedback-protocol', import.meta.url))
|
|
const SESSION_FIXTURE = join(SNAPSHOT_DIR, 'session.jsonl')
|
|
const PROTOCOL_EXPECTED = join(SNAPSHOT_DIR, 'protocol.expected.json')
|
|
const SESSION_ID = 'message-feedback-protocol'
|
|
const MESSAGE_ID = '11111111-1111-4111-8111-111111111111'
|
|
|
|
interface ProtocolExchange {
|
|
readonly endpoint: string
|
|
readonly request: unknown
|
|
readonly status: number
|
|
readonly response: unknown
|
|
}
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return typeof value === 'object' && value !== null
|
|
}
|
|
|
|
/** Extract the opaque item version while keeping every surrounding wire field snapshot-owned. */
|
|
function createdVersion(response: unknown): string {
|
|
if (!isRecord(response) || !isRecord(response.result) || response.result.ok !== true
|
|
|| !isRecord(response.result.value) || response.result.value.ok !== true
|
|
|| !isRecord(response.result.value.value)
|
|
|| typeof response.result.value.value.version !== 'string') {
|
|
throw new Error('messageFeedback.put did not return a successful versioned item')
|
|
}
|
|
return response.result.value.value.version
|
|
}
|
|
|
|
/** Replace only run-owned UUID/time values; all protocol names and business fields stay exact. */
|
|
function normalizeProtocol(exchanges: readonly ProtocolExchange[], version: string): string {
|
|
return JSON.stringify(exchanges, (key, value: unknown) => {
|
|
if ((key === 'version' || key === 'ifVersion') && value === version) return '{{version}}'
|
|
if ((key === 'createdAt' || key === 'updatedAt') && typeof value === 'number') return '{{timestamp}}'
|
|
return value
|
|
}, 2)
|
|
}
|
|
|
|
describe('message feedback Host Remote protocol', () => {
|
|
let scaffold: WebScaffold
|
|
|
|
beforeAll(async () => {
|
|
scaffold = await launchWebScaffold()
|
|
await seedSession(scaffold, await readFile(SESSION_FIXTURE, 'utf8'), SESSION_ID)
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await scaffold?.close()
|
|
})
|
|
|
|
it('snapshots strict list, put, conflict, and delete calls through the shipped Web Host', async () => {
|
|
const exchanges: ProtocolExchange[] = []
|
|
const invoke = async (rpcId: string, endpoint: string, request: unknown): Promise<unknown> => {
|
|
const payload = { args: { request } }
|
|
const response = await fetch(`${scaffold.baseUrl}/api/${endpoint}`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json' },
|
|
body: JSON.stringify({
|
|
type: 'client-request',
|
|
rpcId,
|
|
method: endpoint,
|
|
payload,
|
|
}),
|
|
})
|
|
const body: unknown = await response.json()
|
|
exchanges.push({ endpoint: `/api/${endpoint}`, request: payload, status: response.status, response: body })
|
|
return body
|
|
}
|
|
|
|
await invoke('feedback-invalid', 'messageFeedback/put', {
|
|
sessionId: SESSION_ID,
|
|
messageId: MESSAGE_ID,
|
|
rating: 'invalid-rating',
|
|
ifVersion: null,
|
|
})
|
|
await invoke('feedback-list-empty', 'messageFeedback/list', { sessionId: SESSION_ID })
|
|
const created = await invoke('feedback-put', 'messageFeedback/put', {
|
|
sessionId: SESSION_ID,
|
|
messageId: MESSAGE_ID,
|
|
rating: 'positive',
|
|
note: 'Useful answer',
|
|
ifVersion: null,
|
|
})
|
|
const version = createdVersion(created)
|
|
expect(version).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/)
|
|
await invoke('feedback-list-created', 'messageFeedback/list', { sessionId: SESSION_ID })
|
|
await invoke('feedback-conflict', 'messageFeedback/put', {
|
|
sessionId: SESSION_ID,
|
|
messageId: MESSAGE_ID,
|
|
rating: 'negative',
|
|
ifVersion: null,
|
|
})
|
|
await invoke('feedback-delete', 'messageFeedback/delete', {
|
|
sessionId: SESSION_ID,
|
|
messageId: MESSAGE_ID,
|
|
ifVersion: version,
|
|
})
|
|
await invoke('feedback-list-deleted', 'messageFeedback/list', { sessionId: SESSION_ID })
|
|
|
|
expect(exchanges.every(exchange => exchange.status === 200)).toBe(true)
|
|
await compareOrRefreshGolden(PROTOCOL_EXPECTED, normalizeProtocol(exchanges, version), scaffold.mode)
|
|
await assertFixtureInventory(SNAPSHOT_DIR, ['protocol.expected.json', 'session.jsonl'])
|
|
})
|
|
})
|