返回源码地图

packages/session/session-format-v3-to-v4/src/codec.ts

main snapshot · da00f7f5358f · 正文引用章节 16;完整原文可核对,不声称全文件人工逐行审计

完整原文供逐行核对;页面收录不代表每行都经过人工语义审核。MIT 许可见 许可证。

1/** V4 framing with native tool-role admission and released physical rows. */
2
3import { SessionFormatError, isSessionFormatJsonObject } from '@deepseek-ai/dsh-session-format'
4import type { SessionFormatCodec, SessionFormatCurrentEncoder, SessionFormatHeader, SessionFormatEvent } from '@deepseek-ai/dsh-session-format'
5import { releasedV2SessionFormatCodec } from '@deepseek-ai/dsh-session-format-v2-to-v3'
6import { assertV4SourceRowAdmission } from './message-sources.ts'
7import { assertV4RetiredSyntax } from './retired-syntax.ts'
8import { assertV4SystemMessageFields } from './system-message.ts'
9import { assertV4DeveloperData } from './developer.ts'
10import { assertV4ForkResult } from './fork-result.ts'
11import { assertV4ToolResultMessage } from './tool-role.ts'
12import { assertReleasedV4Header } from './validation.ts'
13
14function physicalV2(value: unknown): SessionFormatHeader {
15 if (!isSessionFormatJsonObject(value) || value['version'] !== 4) throw new SessionFormatError('expected format v4 physical header')
16 return { ...value, version: 2 } as SessionFormatHeader
17}
18
19/**
20 * V4 physical encoder and decoder retain the released row framing while
21 * validating the native tool-role message directly.
22 */
23export const releasedV4SessionFormatCodec = Object.freeze({
24 version: 4,
25 decodeHeader(value: unknown) {
26 return { ...releasedV2SessionFormatCodec.decodeHeader(physicalV2(value)), version: 4 }
27 },
28 createDecoder(value, recovery) {
29 const decoder = releasedV2SessionFormatCodec.createDecoder(physicalV2(value), recovery)
30 return {
31 ...decoder,
32 header: { ...decoder.header, version: 4 },
33 decodeRow(row, context) {
34 assertV4RowAdmission(row)
35 decoder.decodeRow(row, {
36 emitRun: context.emitRun.bind(context),
37 emitEvent: context.emitEvent.bind(context),
38 })
39 },
40 }
41 },
42 encodeHeader(header, inheritedEventCount) {
43 assertReleasedV4Header(header)
44 return { ...releasedV2SessionFormatCodec.encodeHeader({ ...header, version: 2 }, inheritedEventCount), version: 4 }
45 },
46 encodeEvent(event: SessionFormatEvent) {
47 if (event.type === 'developer/message' && event['ignorable'] === true) {
48 assertV4DeveloperData(event)
49 assertV4RetiredSyntax(event)
50 }
51 assertV4RowAdmission(event)
52 return releasedV2SessionFormatCodec.encodeEvent(event)
53 },
54} satisfies SessionFormatCodec & SessionFormatCurrentEncoder)
55
56/**
57 * Apply native V4 admission before a scanner discards a recoverable suffix.
58 * Ignorable developer payloads require reader vocabulary; physical decoding defers them.
59 * @param row - parsed physical row before framing and source-event range decoding.
60 * @param knownEventTypes - installed event types, supplied by native readers before tail recovery.
61 */
62export function assertV4RowAdmission(row: unknown, knownEventTypes?: ReadonlySet<string>): void {
63 if (isSessionFormatJsonObject(row)) {
64 if (row['type'] === 'developer/message' && row['ignorable'] === true
65 && knownEventTypes?.has('developer/message') !== true) return
66 assertV4DeveloperData(row as unknown as SessionFormatEvent)
67 }
68 assertV4SourceRowAdmission(row)
69 assertV4RetiredSyntax(row)
70 assertV4SystemMessageFields(row)
71 if (!isSessionFormatJsonObject(row) || row['type'] !== 'tool/result') return
72 const event = row as unknown as SessionFormatEvent
73 assertV4ToolResultMessage(event)
74 assertV4ForkResult(event)
75}