@thejrsoft/subway-protocol 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/ACK_MESSAGES_IMPLEMENTATION_SUMMARY.md +128 -0
  2. package/ACK_MESSAGE_DESIGN.md +457 -0
  3. package/CHANGELOG.md +58 -0
  4. package/COMMAND_VALIDATION_RULES.md +178 -0
  5. package/DOCUMENTATION_REORGANIZATION_SUMMARY.md +81 -0
  6. package/DOCUMENTATION_STRUCTURE.md +106 -0
  7. package/GATEWAY_MIGRATION_GUIDE.md +130 -0
  8. package/GATEWAY_PROTOCOL_COMPARISON.md +216 -0
  9. package/INTEGRATION_GUIDE.md +190 -0
  10. package/OPTIONAL_FIELDS_WITHOUT_DEFAULTS.md +97 -0
  11. package/PROTOCOL_UTILS_USAGE.md +278 -0
  12. package/README.md +237 -0
  13. package/TYPE_FIXES_SUMMARY.md +210 -0
  14. package/UPDATE_ENUM_VALUES.md +139 -0
  15. package/dist/asyncapi-sync.d.ts +47 -0
  16. package/dist/asyncapi-sync.d.ts.map +1 -0
  17. package/dist/asyncapi-sync.js +85 -0
  18. package/dist/asyncapi-sync.js.map +1 -0
  19. package/dist/command-factory.d.ts +62 -0
  20. package/dist/command-factory.d.ts.map +1 -0
  21. package/dist/command-factory.js +137 -0
  22. package/dist/command-factory.js.map +1 -0
  23. package/dist/command-types.d.ts +27 -0
  24. package/dist/command-types.d.ts.map +1 -0
  25. package/dist/command-types.js +31 -0
  26. package/dist/command-types.js.map +1 -0
  27. package/dist/index.d.ts +403 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +413 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/message-validator.d.ts +102 -0
  32. package/dist/message-validator.d.ts.map +1 -0
  33. package/dist/message-validator.js +640 -0
  34. package/dist/message-validator.js.map +1 -0
  35. package/dist/protocol-utils.d.ts +108 -0
  36. package/dist/protocol-utils.d.ts.map +1 -0
  37. package/dist/protocol-utils.js +293 -0
  38. package/dist/protocol-utils.js.map +1 -0
  39. package/docs/01-protocol/README.md +45 -0
  40. package/docs/01-protocol/design-rationale.md +198 -0
  41. package/docs/01-protocol/message-types.md +669 -0
  42. package/docs/01-protocol/specification.md +1466 -0
  43. package/docs/02-commands/README.md +56 -0
  44. package/docs/02-commands/batch-command.md +435 -0
  45. package/docs/02-commands/complex-command.md +537 -0
  46. package/docs/02-commands/simple-command.md +332 -0
  47. package/docs/02-commands/typed-commands.md +362 -0
  48. package/docs/03-architecture/README.md +66 -0
  49. package/docs/03-architecture/device-protocol.md +430 -0
  50. package/docs/03-architecture/edge-proxy.md +727 -0
  51. package/docs/03-architecture/routing-flow.md +893 -0
  52. package/docs/04-integration/README.md +144 -0
  53. package/docs/04-integration/backend-guide.md +551 -0
  54. package/docs/04-integration/edge-guide.md +684 -0
  55. package/docs/04-integration/gateway-guide.md +180 -0
  56. package/docs/04-integration/migration-guide.md +226 -0
  57. package/docs/05-examples/README.md +141 -0
  58. package/docs/05-examples/progress-update-examples.md +757 -0
  59. package/docs/06-reference/README.md +67 -0
  60. package/docs/06-reference/api.md +572 -0
  61. package/docs/06-reference/faq.md +302 -0
  62. package/docs/06-reference/glossary.md +232 -0
  63. package/examples/backend-upgrade.ts +279 -0
  64. package/examples/edge-multi-device.ts +513 -0
  65. package/examples/gateway-upgrade.ts +150 -0
  66. package/examples/protocol-implementation.ts +715 -0
  67. package/package.json +48 -0
  68. package/scripts/validate-asyncapi.ts +78 -0
  69. package/src/__tests__/protocol.test.ts +297 -0
  70. package/src/asyncapi-sync.ts +84 -0
  71. package/src/command-factory.ts +183 -0
  72. package/src/command-types.ts +72 -0
  73. package/src/edge-proxy.ts +494 -0
  74. package/src/gateway-extensions.ts +278 -0
  75. package/src/index.ts +792 -0
  76. package/src/message-validator.ts +726 -0
  77. package/src/protocol-utils.ts +355 -0
  78. package/tsconfig.json +24 -0
@@ -0,0 +1,216 @@
1
+ # Gateway vs Protocol 类型定义比较
2
+
3
+ ## BaseMessage 比较
4
+
5
+ ### Gateway 定义
6
+ ```typescript
7
+ export interface BaseMessage {
8
+ type: MessageType;
9
+ targetClientId?: string;
10
+ }
11
+ ```
12
+
13
+ ### Protocol 定义
14
+ ```typescript
15
+ export interface BaseMessage {
16
+ type: MessageType;
17
+ timestamp: string; // ISO 8601 格式
18
+ version: string; // 协议版本 "1.0"
19
+ }
20
+ ```
21
+
22
+ ### 差异分析
23
+ | 字段 | Gateway | Protocol | 说明 |
24
+ |------|---------|----------|------|
25
+ | type | ✓ | ✓ | 都有,类型一致 |
26
+ | targetClientId | ✓ (可选) | ✗ | Gateway 特有,但应该只在特定消息中使用 |
27
+ | timestamp | ✗ | ✓ (必需) | Protocol 要求所有消息都有时间戳 |
28
+ | version | ✗ | ✓ (必需) | Protocol 要求协议版本号 |
29
+
30
+ ## CommandMessage 比较
31
+
32
+ ### Gateway 定义
33
+ ```typescript
34
+ export interface CommandMessage extends BaseMessage {
35
+ type: typeof WS_MESSAGE_TYPES.COMMAND;
36
+ requestRef: string;
37
+ targetClientId: string;
38
+ command: {
39
+ commandType?: 'SIMPLE' | 'BATCH' | 'COMPLEX';
40
+ commandCode: string;
41
+ deviceType: string;
42
+ deviceId?: number;
43
+ operationType: string;
44
+ parameters: Record<string, unknown>;
45
+ };
46
+ priority: string;
47
+ timeout: number;
48
+ timestamp: string;
49
+ callback?: string;
50
+ version?: string;
51
+ metadata?: Record<string, any>;
52
+ }
53
+ ```
54
+
55
+ ### Protocol 定义
56
+ ```typescript
57
+ export interface CommandMessage extends BaseMessage {
58
+ type: MessageType.COMMAND;
59
+ requestRef: string;
60
+ targetClientId: string;
61
+ command: Command; // 支持多种命令类型
62
+ priority: Priority; // 枚举类型
63
+ timeout: number;
64
+ retryCount?: number;
65
+ callback: string;
66
+ metadata?: Record<string, any>;
67
+ }
68
+
69
+ // Command 可以是:
70
+ // - SpecificCommand (从 C# 生成)
71
+ // - SimpleCommand
72
+ // - BatchCommand
73
+ // - ComplexCommand
74
+ // - GenericCommand
75
+ ```
76
+
77
+ ### 详细差异分析
78
+
79
+ #### 1. 继承的差异
80
+ - **Gateway**: 继承的 BaseMessage 有 `targetClientId?`
81
+ - **Protocol**: 继承的 BaseMessage 有 `timestamp` 和 `version`
82
+
83
+ #### 2. 字段级别差异
84
+
85
+ | 字段 | Gateway | Protocol | 差异说明 |
86
+ |------|---------|----------|----------|
87
+ | requestRef | ✓ string | ✓ string | ✅ 一致 |
88
+ | targetClientId | ✓ string | ✓ string | ✅ 一致 |
89
+ | command | 内联对象 | Command 类型 | ⚠️ Protocol 使用强类型 |
90
+ | priority | string | Priority 枚举 | ⚠️ Protocol 使用枚举 |
91
+ | timeout | ✓ number | ✓ number | ✅ 一致 |
92
+ | timestamp | ✓ string | 继承自 BaseMessage | ⚠️ Gateway 直接定义,Protocol 继承 |
93
+ | callback | ✓ 可选 | ✓ 必需 | ❌ **重要差异** |
94
+ | version | ✓ 可选 | 继承自 BaseMessage | ⚠️ Gateway 直接定义,Protocol 继承 |
95
+ | retryCount | ✗ | ✓ 可选 | ⚠️ Protocol 特有 |
96
+ | metadata | ✓ 可选 | ✓ 可选 | ✅ 一致 |
97
+
98
+ #### 3. Command 结构差异
99
+
100
+ **Gateway 的 command**:
101
+ ```typescript
102
+ command: {
103
+ commandType?: 'SIMPLE' | 'BATCH' | 'COMPLEX';
104
+ commandCode: string;
105
+ deviceType: string;
106
+ deviceId?: number;
107
+ operationType: string;
108
+ parameters: Record<string, unknown>;
109
+ }
110
+ ```
111
+
112
+ **Protocol 的 command**:
113
+ - 支持多种类型(SimpleCommand, BatchCommand, ComplexCommand, GenericCommand)
114
+ - deviceId 支持 `number | number[] | string`
115
+ - 有严格的类型定义和验证
116
+
117
+ ## 其他消息类型差异
118
+
119
+ ### RegisterMessage
120
+ **主要差异**:
121
+ - Gateway: `clientType: 'device' | 'edge' | 'backend'`
122
+ - Protocol: `clientType: ClientType` (枚举)
123
+ - Gateway: 没有 timestamp 和 version
124
+ - Protocol: 继承自 BaseMessage,有 timestamp 和 version
125
+
126
+ ### RegisterAckMessage
127
+ **主要差异**:
128
+ - Gateway: `message?: string`
129
+ - Protocol: `error?: { code: string; message: string }`
130
+ - Protocol 有更详细的 serverInfo
131
+
132
+ ## 字段一致性总结
133
+
134
+ ### CommandMessage 完全一致的字段:
135
+ - `requestRef: string` ✅
136
+ - `targetClientId: string` ✅
137
+ - `timeout: number` ✅
138
+ - `metadata?: Record<string, any>` ✅
139
+
140
+ ### 主要差异字段:
141
+ 1. **callback**: Gateway 可选 vs Protocol 必需 ❌
142
+ 2. **priority**: Gateway 字符串 vs Protocol 枚举 ⚠️
143
+ 3. **command**: Gateway 内联对象 vs Protocol 强类型 ⚠️
144
+ 4. **retryCount**: 只在 Protocol 中存在 ⚠️
145
+
146
+ ## 统一建议
147
+
148
+ ### 1. BaseMessage 统一
149
+ ```typescript
150
+ // 建议的统一定义
151
+ export interface BaseMessage {
152
+ type: MessageType;
153
+ timestamp: string; // 必需,便于追踪
154
+ version: string; // 必需,便于版本管理
155
+ // targetClientId 不应该在这里,只在需要的消息中定义
156
+ }
157
+ ```
158
+
159
+ ### 2. CommandMessage 统一
160
+ 需要决定:
161
+ - **callback**: 是否必需?
162
+ - **priority**: 使用枚举还是字符串?
163
+ - **command**: 使用强类型还是松散对象?
164
+
165
+ ### 3. 迁移步骤
166
+ 1. Gateway 先迁移到使用协议包
167
+ 2. 处理字段差异(添加 timestamp, version)
168
+ 3. 统一类型定义(枚举 vs 字符串)
169
+ 4. 更新验证逻辑
170
+
171
+ ## 影响评估
172
+
173
+ ### 如果采用 Protocol 的严格定义
174
+ **需要修改 Gateway**:
175
+ 1. 所有消息添加 timestamp 和 version
176
+ 2. callback 改为必需(或修改协议使其可选)
177
+ 3. priority 使用 Priority 枚举
178
+ 4. 移除 BaseMessage 中的 targetClientId
179
+
180
+ ### 如果放松 Protocol 的定义
181
+ **需要修改 Protocol**:
182
+ 1. callback 改为可选
183
+ 2. priority 改为可选并提供默认值
184
+ 3. 可能需要调整验证逻辑
185
+
186
+ ## 推荐方案
187
+
188
+ 1. **保持 Protocol 的严格定义**(推荐)
189
+ - 更好的类型安全
190
+ - 清晰的 API 契约
191
+ - Gateway 迁移到使用协议包
192
+
193
+ 2. **创建适配层**
194
+ - Gateway 保持现有定义
195
+ - 创建转换函数在 Gateway 和 Protocol 之间转换
196
+ - 逐步迁移
197
+
198
+ 3. **放松 Protocol 定义**
199
+ - 使某些字段可选
200
+ - 降低迁移成本
201
+ - 但可能导致运行时错误
202
+
203
+ ## 更新说明
204
+
205
+ ### 关于 timeout 字段
206
+ 经过检查,`timeout` 字段在 Gateway 和 Protocol 的 CommandMessage 定义中都存在,都是必需的 `number` 类型。这不是差异点。
207
+
208
+ ### Backend 使用情况
209
+ - Backend 已经完全迁移到使用 `@jrsoft/subway-protocol`
210
+ - Backend 的 `gateway.client.ts` 和 `command.dispatcher.ts` 都使用了协议包的类型定义
211
+ - Backend 中的 callback 使用 `appConfig.gateway.callbackUrl` 作为值
212
+
213
+ ### Gateway 使用情况
214
+ - Gateway 仍在使用自己的类型定义文件 (`src/types/common.types.ts`)
215
+ - Gateway 尚未迁移到协议包
216
+ - Gateway 的 callback 字段是可选的,这是主要差异之一
@@ -0,0 +1,190 @@
1
+ # JRSoft Subway Protocol - C# 模型集成指南
2
+
3
+ ## 概述
4
+
5
+ 本协议包设计为与 `jrsoft-subway-csharp-model` 生成的 TypeScript 类型配合使用。当前包含的命令类型(`ExampleCommand`)仅为示例,实际使用时应从 C# 模型包导入真实的命令类型。
6
+
7
+ ## 集成步骤
8
+
9
+ ### 1. 安装 C# 模型包
10
+
11
+ 首先,需要将 C# 模型包添加为依赖:
12
+
13
+ ```bash
14
+ # 如果 C# 模型包已发布到 npm
15
+ npm install @jrsoft/csharp-model
16
+
17
+ # 或者使用本地链接(开发时)
18
+ cd ../jrsoft-subway-csharp-model
19
+ npm link
20
+ cd ../jrsoft-subway-protocol
21
+ npm link @jrsoft/csharp-model
22
+ ```
23
+
24
+ ### 2. 更新 package.json
25
+
26
+ 在 `package.json` 中添加依赖:
27
+
28
+ ```json
29
+ {
30
+ "dependencies": {
31
+ "@jrsoft/csharp-model": "^1.0.0"
32
+ }
33
+ }
34
+ ```
35
+
36
+ 或者对于本地开发:
37
+
38
+ ```json
39
+ {
40
+ "dependencies": {
41
+ "@jrsoft/csharp-model": "file:../jrsoft-subway-csharp-model"
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### 3. 更新 command-types.ts
47
+
48
+ 将示例命令替换为真实的 C# 生成的命令:
49
+
50
+ ```typescript
51
+ // src/command-types.ts
52
+
53
+ import { OperationType, CommandType } from './index';
54
+
55
+ // 导入 C# 生成的命令类型
56
+ import {
57
+ LedSwitchCommand as CSharpLedSwitchCommand,
58
+ LedSwitchParameters,
59
+ BlockPlayCommand as CSharpBlockPlayCommand,
60
+ BlockPlayParameters,
61
+ // ... 更多命令
62
+ } from '@jrsoft/csharp-model/typescript-schemas';
63
+
64
+ // 适配命令接口(处理字段名差异,如 deviceID -> deviceId)
65
+ export interface LedSwitchCommand extends Omit<CSharpLedSwitchCommand, 'deviceID'> {
66
+ commandType: CommandType;
67
+ deviceId: number | number[] | string; // 重命名并支持批量
68
+ }
69
+
70
+ export interface BlockPlayCommand extends Omit<CSharpBlockPlayCommand, 'deviceID'> {
71
+ commandType: CommandType;
72
+ deviceId: number | number[] | string;
73
+ }
74
+
75
+ // 导出所有命令的联合类型
76
+ export type SpecificCommand =
77
+ | LedSwitchCommand
78
+ | BlockPlayCommand
79
+ // ... 更多命令
80
+ ;
81
+
82
+ // 命令映射
83
+ export interface CommandTypeMap {
84
+ 'LedSwitch': LedSwitchCommand;
85
+ 'BlockPlay': BlockPlayCommand;
86
+ // ... 更多映射
87
+ }
88
+ ```
89
+
90
+ ### 4. 更新 command-factory.ts
91
+
92
+ 为每个真实命令添加工厂方法:
93
+
94
+ ```typescript
95
+ // src/command-factory.ts
96
+
97
+ export class TypedCommandFactory {
98
+ static createLedSwitchCommand(
99
+ requestRef: string,
100
+ targetClientId: string,
101
+ deviceId: number | number[] | string,
102
+ switchState: 'ON' | 'OFF',
103
+ operationType: OperationType = OperationType.WRITE,
104
+ options?: CommandOptions
105
+ ): CommandMessage {
106
+ return this.createTypedCommandMessage(
107
+ requestRef,
108
+ targetClientId,
109
+ 'LedSwitch',
110
+ {
111
+ commandType: CommandType.SIMPLE,
112
+ deviceType: 'pillar',
113
+ deviceId,
114
+ operationType,
115
+ parameters: { switch: switchState }
116
+ },
117
+ options
118
+ );
119
+ }
120
+
121
+ // ... 更多命令工厂方法
122
+ }
123
+ ```
124
+
125
+ ## 字段映射说明
126
+
127
+ C# 生成的类型和协议要求的类型之间存在一些差异:
128
+
129
+ 1. **字段名称差异**
130
+ - C# 使用 `deviceID`(大写 ID)
131
+ - 协议使用 `deviceId`(小写 id)
132
+
133
+ 2. **额外字段**
134
+ - 协议需要 `commandType` 字段(SIMPLE/BATCH/COMPLEX)
135
+ - C# 生成的类型可能不包含此字段
136
+
137
+ 3. **批量操作支持**
138
+ - 协议的 `deviceId` 支持 `number | number[] | string`
139
+ - C# 可能只定义了 `number`
140
+
141
+ ## 开发建议
142
+
143
+ 1. **使用 TypeScript 接口扩展**
144
+ ```typescript
145
+ interface ProtocolCommand extends CSharpCommand {
146
+ commandType: CommandType;
147
+ // 其他协议特定字段
148
+ }
149
+ ```
150
+
151
+ 2. **创建适配器函数**
152
+ ```typescript
153
+ function adaptCSharpCommand(cmd: CSharpCommand): ProtocolCommand {
154
+ return {
155
+ ...cmd,
156
+ commandType: CommandType.SIMPLE,
157
+ deviceId: cmd.deviceID, // 字段重命名
158
+ };
159
+ }
160
+ ```
161
+
162
+ 3. **验证器更新**
163
+ - 确保验证器能处理 C# 生成的命令结构
164
+ - 添加特定命令的验证逻辑
165
+
166
+ ## 注意事项
167
+
168
+ 1. **版本同步**:确保 C# 模型包和协议包版本兼容
169
+ 2. **类型安全**:使用 TypeScript 的严格模式确保类型正确
170
+ 3. **测试覆盖**:为每个集成的命令添加单元测试
171
+ 4. **文档更新**:集成新命令时更新相关文档
172
+
173
+ ## 示例项目结构
174
+
175
+ ```
176
+ jrsoft-subway/
177
+ ├── jrsoft-subway-protocol/ # 协议定义
178
+ │ ├── src/
179
+ │ │ ├── index.ts # 核心协议
180
+ │ │ ├── command-types.ts # 命令类型(导入 C# 类型)
181
+ │ │ └── command-factory.ts # 命令工厂
182
+ │ └── package.json
183
+ ├── jrsoft-subway-csharp-model/ # C# 模型
184
+ │ ├── typescript-schemas/ # 生成的 TS 类型
185
+ │ │ ├── LedSwitchCommand.generated.ts
186
+ │ │ └── ...
187
+ │ └── package.json
188
+ └── jrsoft-subway-gateway/ # 使用协议的服务
189
+ └── package.json # 依赖 protocol 包
190
+ ```
@@ -0,0 +1,97 @@
1
+ # Protocol 中没有默认值的可选字段
2
+
3
+ ## 概述
4
+ 这些可选字段在 MessageFactory 中没有提供默认值,使用时需要显式传递或留空。
5
+
6
+ ## 1. RegisterMessage
7
+ - `clientInfo?: ClientInfo` - 没有默认值
8
+ - `name?: string`
9
+ - `version?: string`
10
+ - `platform?: string`
11
+ - `capabilities?: string[]`
12
+ - `deviceType?: string`
13
+ - `description?: string`
14
+ - `metadata?: Record<string, any>`
15
+ - `edgeInfo?: EdgeInfo` - 没有默认值
16
+ - `edgeVersion?: string`
17
+ - `connectionTime?: string`
18
+
19
+ ## 2. RegisterAckMessage
20
+ - `sessionId?: string` - 没有默认值
21
+ - `error?: { code: string; message: string }` - 根据 success 条件生成
22
+ - `serverInfo?: { ... }` - 没有默认值
23
+ - `currentLoad?: number`
24
+ - `maxClients?: number`
25
+
26
+ ## 3. UnregisterMessage
27
+ - `reason?: string` - 没有默认值
28
+
29
+ ## 4. UnregisterAckMessage
30
+ - `cleanupInfo?: { ... }` - 没有默认值
31
+
32
+ ## 5. CommandMessage
33
+ - `retryCount?: number` - 没有默认值
34
+ - `metadata?: Record<string, any>` - 没有默认值
35
+
36
+ ## 6. Command 相关
37
+ - `parameters?: Record<string, any>` - 没有默认值(所有 Command 类型)
38
+ - ComplexCommand 中的可选字段:
39
+ - `deviceId?: number | number[] | string`
40
+ - `deviceType?: string`
41
+ - `operationType?: OperationType`
42
+ - GenericCommand 中的可选字段(无默认值,但验证器会检查):
43
+ - `commandType?: CommandType`
44
+ - `deviceId?: number | number[] | string`
45
+ - `deviceType?: string`
46
+ - `operationType?: OperationType`
47
+
48
+ ## 7. CommandResponseMessage
49
+ - `result?: CommandResult` - 没有默认值
50
+ - `report?: ReportMessage` - 根据 message 参数条件生成
51
+ - `executionTime?: number` - 没有默认值
52
+
53
+ ## 8. HeartbeatAckMessage
54
+ - `latency?: number` - 没有默认值
55
+ - `serverStatus?: { ... }` - 没有默认值
56
+ - `cpuUsage?: number`
57
+ - `memoryUsage?: number`
58
+
59
+ ## 9. ErrorMessage
60
+ - `category?: string` - 没有默认值
61
+ - `context?: any` - 根据参数构建,但内部字段可能为空
62
+ - `retryable?: boolean` - 没有默认值
63
+
64
+ ## 10. ProgramResponseMessage
65
+ - `context?: ProgramContext` - 没有默认值(使用 result 参数)
66
+ - `report?: ReportMessage` - 根据 message 参数条件生成
67
+ - `executionTime?: number` - 没有默认值
68
+
69
+ ## 11. ProgressUpdateMessage
70
+ - `context?: ProgramContext` - 没有默认值
71
+ - `command?: DeviceOperationRecord` - 没有默认值
72
+ - `report?: ReportMessage` - 根据 message 参数条件生成
73
+ - `code?: string` - 没有默认值
74
+ - `data?: Record<string, any>` - 没有默认值
75
+
76
+ ## 12. DeviceOperationRecord
77
+ - `result?: Record<string, any>` - 没有默认值
78
+
79
+ ## 建议
80
+
81
+ ### 可以考虑添加默认值的字段:
82
+ 1. **retryCount** - 可以默认为 0
83
+ 2. **metadata** - 可以默认为空对象 {}
84
+ 3. **latency** - 可以根据时间戳计算
85
+ 4. **executionTime** - 可以根据开始和结束时间计算
86
+
87
+ ### 不应该有默认值的字段:
88
+ 1. **sessionId** - 必须由服务器生成
89
+ 2. **result** - 必须是实际执行结果
90
+ 3. **error** - 只在错误时存在
91
+ 4. **serverInfo/serverStatus** - 必须是实际服务器状态
92
+ 5. **context** - 必须是实际上下文信息
93
+
94
+ ### Gateway 迁移注意事项:
95
+ - 这些没有默认值的可选字段,Gateway 可以根据实际情况选择性提供
96
+ - 不提供时,字段会被省略(undefined),这符合 Protocol 的设计
97
+ - 某些字段(如 metadata)虽然没有默认值,但 Gateway 可以在自己的代码中设置默认空对象