@tx5dr/contracts 1.7.12 → 2.0.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 (195) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +3 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/schema/__tests__/android-operator-audio.schema.test.d.ts +2 -0
  6. package/dist/schema/__tests__/android-operator-audio.schema.test.d.ts.map +1 -0
  7. package/dist/schema/__tests__/android-operator-audio.schema.test.js +27 -0
  8. package/dist/schema/__tests__/android-operator-audio.schema.test.js.map +1 -0
  9. package/dist/schema/__tests__/assisted-queue.schema.test.d.ts +2 -0
  10. package/dist/schema/__tests__/assisted-queue.schema.test.d.ts.map +1 -0
  11. package/dist/schema/__tests__/assisted-queue.schema.test.js +113 -0
  12. package/dist/schema/__tests__/assisted-queue.schema.test.js.map +1 -0
  13. package/dist/schema/__tests__/audio-sidecar.schema.test.d.ts +2 -0
  14. package/dist/schema/__tests__/audio-sidecar.schema.test.d.ts.map +1 -0
  15. package/dist/schema/__tests__/audio-sidecar.schema.test.js +42 -0
  16. package/dist/schema/__tests__/audio-sidecar.schema.test.js.map +1 -0
  17. package/dist/schema/__tests__/audio.schema.test.js +92 -1
  18. package/dist/schema/__tests__/audio.schema.test.js.map +1 -1
  19. package/dist/schema/__tests__/diagnostics.schema.test.d.ts +2 -0
  20. package/dist/schema/__tests__/diagnostics.schema.test.d.ts.map +1 -0
  21. package/dist/schema/__tests__/diagnostics.schema.test.js +31 -0
  22. package/dist/schema/__tests__/diagnostics.schema.test.js.map +1 -0
  23. package/dist/schema/__tests__/logbook-health.schema.test.d.ts +2 -0
  24. package/dist/schema/__tests__/logbook-health.schema.test.d.ts.map +1 -0
  25. package/dist/schema/__tests__/logbook-health.schema.test.js +104 -0
  26. package/dist/schema/__tests__/logbook-health.schema.test.js.map +1 -0
  27. package/dist/schema/__tests__/observability.schema.test.d.ts +2 -0
  28. package/dist/schema/__tests__/observability.schema.test.d.ts.map +1 -0
  29. package/dist/schema/__tests__/observability.schema.test.js +12 -0
  30. package/dist/schema/__tests__/observability.schema.test.js.map +1 -0
  31. package/dist/schema/__tests__/operator.schema.test.js +9 -3
  32. package/dist/schema/__tests__/operator.schema.test.js.map +1 -1
  33. package/dist/schema/__tests__/plugin-market.schema.test.js +43 -1
  34. package/dist/schema/__tests__/plugin-market.schema.test.js.map +1 -1
  35. package/dist/schema/__tests__/radio-power-support.test.js +12 -0
  36. package/dist/schema/__tests__/radio-power-support.test.js.map +1 -1
  37. package/dist/schema/__tests__/radio-profile.schema.test.d.ts +2 -0
  38. package/dist/schema/__tests__/radio-profile.schema.test.d.ts.map +1 -0
  39. package/dist/schema/__tests__/radio-profile.schema.test.js +36 -0
  40. package/dist/schema/__tests__/radio-profile.schema.test.js.map +1 -0
  41. package/dist/schema/__tests__/radio.schema.test.js +41 -1
  42. package/dist/schema/__tests__/radio.schema.test.js.map +1 -1
  43. package/dist/schema/__tests__/realtime-settings.schema.test.js +2 -1
  44. package/dist/schema/__tests__/realtime-settings.schema.test.js.map +1 -1
  45. package/dist/schema/__tests__/remote-access.schema.test.d.ts +2 -0
  46. package/dist/schema/__tests__/remote-access.schema.test.d.ts.map +1 -0
  47. package/dist/schema/__tests__/remote-access.schema.test.js +18 -0
  48. package/dist/schema/__tests__/remote-access.schema.test.js.map +1 -0
  49. package/dist/schema/android-operator-audio.schema.d.ts +174 -0
  50. package/dist/schema/android-operator-audio.schema.d.ts.map +1 -0
  51. package/dist/schema/android-operator-audio.schema.js +38 -0
  52. package/dist/schema/android-operator-audio.schema.js.map +1 -0
  53. package/dist/schema/api-response.schema.d.ts +268 -44
  54. package/dist/schema/api-response.schema.d.ts.map +1 -1
  55. package/dist/schema/audio-sidecar.schema.d.ts +75 -0
  56. package/dist/schema/audio-sidecar.schema.d.ts.map +1 -1
  57. package/dist/schema/audio-sidecar.schema.js +32 -0
  58. package/dist/schema/audio-sidecar.schema.js.map +1 -1
  59. package/dist/schema/audio.schema.d.ts +4749 -3
  60. package/dist/schema/audio.schema.d.ts.map +1 -1
  61. package/dist/schema/audio.schema.js +101 -2
  62. package/dist/schema/audio.schema.js.map +1 -1
  63. package/dist/schema/auth.schema.d.ts +171 -12
  64. package/dist/schema/auth.schema.d.ts.map +1 -1
  65. package/dist/schema/auth.schema.js +65 -1
  66. package/dist/schema/auth.schema.js.map +1 -1
  67. package/dist/schema/cpu-profile.schema.d.ts +2 -2
  68. package/dist/schema/cw-decoder.schema.d.ts +74 -74
  69. package/dist/schema/cw-keyer.schema.d.ts +20 -14
  70. package/dist/schema/cw-keyer.schema.d.ts.map +1 -1
  71. package/dist/schema/cw-keyer.schema.js +3 -0
  72. package/dist/schema/cw-keyer.schema.js.map +1 -1
  73. package/dist/schema/desktop-https.schema.d.ts +6 -6
  74. package/dist/schema/device-ui.schema.d.ts +6 -6
  75. package/dist/schema/diagnostics.schema.d.ts +163 -0
  76. package/dist/schema/diagnostics.schema.d.ts.map +1 -0
  77. package/dist/schema/diagnostics.schema.js +46 -0
  78. package/dist/schema/diagnostics.schema.js.map +1 -0
  79. package/dist/schema/ft8.schema.d.ts +12 -2
  80. package/dist/schema/ft8.schema.d.ts.map +1 -1
  81. package/dist/schema/ft8.schema.js +8 -0
  82. package/dist/schema/ft8.schema.js.map +1 -1
  83. package/dist/schema/logbook.schema.d.ts +1940 -18
  84. package/dist/schema/logbook.schema.d.ts.map +1 -1
  85. package/dist/schema/logbook.schema.js +158 -1
  86. package/dist/schema/logbook.schema.js.map +1 -1
  87. package/dist/schema/mode.schema.d.ts +2 -6
  88. package/dist/schema/mode.schema.d.ts.map +1 -1
  89. package/dist/schema/mode.schema.js +2 -6
  90. package/dist/schema/mode.schema.js.map +1 -1
  91. package/dist/schema/observability.schema.d.ts +66 -0
  92. package/dist/schema/observability.schema.d.ts.map +1 -0
  93. package/dist/schema/observability.schema.js +20 -0
  94. package/dist/schema/observability.schema.js.map +1 -0
  95. package/dist/schema/operator.schema.d.ts +6 -6
  96. package/dist/schema/operator.schema.d.ts.map +1 -1
  97. package/dist/schema/operator.schema.js +6 -1
  98. package/dist/schema/operator.schema.js.map +1 -1
  99. package/dist/schema/plugin.schema.d.ts +258 -78
  100. package/dist/schema/plugin.schema.d.ts.map +1 -1
  101. package/dist/schema/plugin.schema.js +57 -2
  102. package/dist/schema/plugin.schema.js.map +1 -1
  103. package/dist/schema/process-monitor.schema.d.ts +132 -132
  104. package/dist/schema/pskreporter.schema.d.ts +1 -3
  105. package/dist/schema/pskreporter.schema.d.ts.map +1 -1
  106. package/dist/schema/pskreporter.schema.js +1 -3
  107. package/dist/schema/pskreporter.schema.js.map +1 -1
  108. package/dist/schema/qso.schema.d.ts +7 -0
  109. package/dist/schema/qso.schema.d.ts.map +1 -1
  110. package/dist/schema/qso.schema.js +7 -0
  111. package/dist/schema/qso.schema.js.map +1 -1
  112. package/dist/schema/radio-capability.schema.d.ts +31 -40
  113. package/dist/schema/radio-capability.schema.d.ts.map +1 -1
  114. package/dist/schema/radio-capability.schema.js +7 -15
  115. package/dist/schema/radio-capability.schema.js.map +1 -1
  116. package/dist/schema/radio-power-support.d.ts.map +1 -1
  117. package/dist/schema/radio-power-support.js +3 -0
  118. package/dist/schema/radio-power-support.js.map +1 -1
  119. package/dist/schema/radio-power.schema.d.ts +87 -13
  120. package/dist/schema/radio-power.schema.d.ts.map +1 -1
  121. package/dist/schema/radio-power.schema.js +15 -8
  122. package/dist/schema/radio-power.schema.js.map +1 -1
  123. package/dist/schema/radio-profile.schema.d.ts +1240 -97
  124. package/dist/schema/radio-profile.schema.d.ts.map +1 -1
  125. package/dist/schema/radio.schema.d.ts +271 -48
  126. package/dist/schema/radio.schema.d.ts.map +1 -1
  127. package/dist/schema/radio.schema.js +44 -5
  128. package/dist/schema/radio.schema.js.map +1 -1
  129. package/dist/schema/realtime.schema.d.ts +60 -52
  130. package/dist/schema/realtime.schema.d.ts.map +1 -1
  131. package/dist/schema/realtime.schema.js +9 -1
  132. package/dist/schema/realtime.schema.js.map +1 -1
  133. package/dist/schema/slot-info.schema.d.ts +15 -9
  134. package/dist/schema/slot-info.schema.d.ts.map +1 -1
  135. package/dist/schema/slot-info.schema.js +15 -9
  136. package/dist/schema/slot-info.schema.js.map +1 -1
  137. package/dist/schema/spectrum.schema.d.ts +12 -12
  138. package/dist/schema/station-info.schema.d.ts +5 -0
  139. package/dist/schema/station-info.schema.d.ts.map +1 -1
  140. package/dist/schema/station-info.schema.js +5 -0
  141. package/dist/schema/station-info.schema.js.map +1 -1
  142. package/dist/schema/system.schema.d.ts +56 -6
  143. package/dist/schema/system.schema.d.ts.map +1 -1
  144. package/dist/schema/system.schema.js +22 -0
  145. package/dist/schema/system.schema.js.map +1 -1
  146. package/dist/schema/transmission.schema.d.ts +1 -7
  147. package/dist/schema/transmission.schema.d.ts.map +1 -1
  148. package/dist/schema/transmission.schema.js +2 -7
  149. package/dist/schema/transmission.schema.js.map +1 -1
  150. package/dist/schema/voice-keyer.schema.d.ts +16 -16
  151. package/dist/schema/websocket.schema.d.ts +3582 -555
  152. package/dist/schema/websocket.schema.d.ts.map +1 -1
  153. package/dist/schema/websocket.schema.js +160 -3
  154. package/dist/schema/websocket.schema.js.map +1 -1
  155. package/package.json +6 -1
  156. package/src/index.ts +3 -0
  157. package/src/schema/__tests__/android-operator-audio.schema.test.ts +31 -0
  158. package/src/schema/__tests__/assisted-queue.schema.test.ts +121 -0
  159. package/src/schema/__tests__/audio-sidecar.schema.test.ts +48 -0
  160. package/src/schema/__tests__/audio.schema.test.ts +102 -0
  161. package/src/schema/__tests__/diagnostics.schema.test.ts +32 -0
  162. package/src/schema/__tests__/logbook-health.schema.test.ts +117 -0
  163. package/src/schema/__tests__/observability.schema.test.ts +15 -0
  164. package/src/schema/__tests__/operator.schema.test.ts +11 -3
  165. package/src/schema/__tests__/plugin-market.schema.test.ts +49 -0
  166. package/src/schema/__tests__/radio-power-support.test.ts +14 -0
  167. package/src/schema/__tests__/radio-profile.schema.test.ts +44 -0
  168. package/src/schema/__tests__/radio.schema.test.ts +49 -1
  169. package/src/schema/__tests__/realtime-settings.schema.test.ts +2 -1
  170. package/src/schema/__tests__/remote-access.schema.test.ts +22 -0
  171. package/src/schema/android-operator-audio.schema.ts +49 -0
  172. package/src/schema/audio-sidecar.schema.ts +35 -0
  173. package/src/schema/audio.schema.ts +115 -2
  174. package/src/schema/auth.schema.ts +79 -1
  175. package/src/schema/cw-keyer.schema.ts +5 -0
  176. package/src/schema/diagnostics.schema.ts +55 -0
  177. package/src/schema/ft8.schema.ts +8 -0
  178. package/src/schema/logbook.schema.ts +204 -1
  179. package/src/schema/mode.schema.ts +2 -6
  180. package/src/schema/observability.schema.ts +26 -0
  181. package/src/schema/operator.schema.ts +7 -1
  182. package/src/schema/plugin.schema.ts +67 -2
  183. package/src/schema/pskreporter.schema.ts +1 -3
  184. package/src/schema/qso.schema.ts +7 -0
  185. package/src/schema/radio-capability.schema.ts +7 -15
  186. package/src/schema/radio-power-support.ts +3 -0
  187. package/src/schema/radio-power.schema.ts +15 -8
  188. package/src/schema/radio.schema.ts +55 -5
  189. package/src/schema/realtime.schema.ts +9 -1
  190. package/src/schema/slot-info.schema.ts +16 -10
  191. package/src/schema/station-info.schema.ts +5 -0
  192. package/src/schema/system.schema.ts +29 -0
  193. package/src/schema/transmission.schema.ts +2 -7
  194. package/src/schema/websocket.schema.ts +223 -6
  195. package/test/radio-capability-schema.test.ts +44 -0
@@ -17,6 +17,11 @@ export const PluginTypeSchema = z.enum(['strategy', 'utility']);
17
17
  */
18
18
  export type PluginType = z.infer<typeof PluginTypeSchema>;
19
19
 
20
+ export const StrategyFeaturesSchema = z.object({
21
+ targetQueue: z.literal(1).optional(),
22
+ }).optional();
23
+ export type StrategyFeatures = z.infer<typeof StrategyFeaturesSchema>;
24
+
20
25
  /**
21
26
  * Runtime instance scope for a plugin.
22
27
  *
@@ -38,10 +43,16 @@ export type PluginInstanceScope = z.infer<typeof PluginInstanceScopeSchema>;
38
43
  */
39
44
  export const PluginPermissionSchema = z.enum([
40
45
  'network',
46
+ 'plugin:event-bus',
41
47
  'host:hamlib',
48
+ 'operator:transmit-control',
42
49
  'radio:read',
43
50
  'radio:control',
51
+ 'radio:tuner-control',
44
52
  'radio:power',
53
+ 'logbook:read',
54
+ 'logbook:write',
55
+ 'logbook:sync',
45
56
  'settings:ft8',
46
57
  'settings:decode-windows',
47
58
  'settings:realtime',
@@ -74,7 +85,17 @@ export type PluginPanelComponent = z.infer<typeof PluginPanelComponentSchema>;
74
85
  * These values control both validation expectations and default frontend
75
86
  * rendering in plugin settings UIs.
76
87
  */
77
- export const PluginSettingTypeSchema = z.enum(['boolean', 'number', 'string', 'string[]', 'object[]', 'keyedStringArrays', 'info']);
88
+ export const PluginSettingTypeSchema = z.enum([
89
+ 'boolean',
90
+ 'number',
91
+ 'string',
92
+ 'string[]',
93
+ 'object[]',
94
+ 'keyedStringArrays',
95
+ 'keyedObjectArrays',
96
+ 'keyedObjects',
97
+ 'info',
98
+ ]);
78
99
 
79
100
  /**
80
101
  * Supported generated-form field types for plugin settings.
@@ -94,6 +115,11 @@ export const PluginSettingOptionSchema = z.object({
94
115
  */
95
116
  export type PluginSettingOption = z.infer<typeof PluginSettingOptionSchema>;
96
117
 
118
+ /**
119
+ * Field descriptor used for each item in an `object[]` or `keyedObjectArrays`
120
+ * setting editor. `key` becomes the object property; `type` controls the Host
121
+ * input; `required` and `default` are applied per item.
122
+ */
97
123
  export const PluginObjectArrayFieldSchema = z.object({
98
124
  key: z.string(),
99
125
  type: z.enum(['string', 'number', 'boolean']).optional().default('string'),
@@ -101,9 +127,14 @@ export const PluginObjectArrayFieldSchema = z.object({
101
127
  description: z.string().optional(),
102
128
  placeholder: z.string().optional(),
103
129
  required: z.boolean().optional(),
130
+ default: z.unknown().optional(),
104
131
  });
105
132
  export type PluginObjectArrayField = z.infer<typeof PluginObjectArrayFieldSchema>;
106
133
 
134
+ /**
135
+ * Fixed key exposed by keyed setting editors. `key` is persisted in the value;
136
+ * `label` and `description` are literal text or plugin locale keys.
137
+ */
107
138
  export const PluginKeyedStringArrayKeySchema = z.object({
108
139
  key: z.string(),
109
140
  label: z.string(),
@@ -111,10 +142,18 @@ export const PluginKeyedStringArrayKeySchema = z.object({
111
142
  });
112
143
  export type PluginKeyedStringArrayKey = z.infer<typeof PluginKeyedStringArrayKeySchema>;
113
144
 
145
+ /**
146
+ * Declarative condition evaluated against values in the same settings form.
147
+ * A leaf compares one `setting` with `equals` or `notEquals`; `allOf` requires
148
+ * every nested condition and `anyOf` requires at least one. Nested groups may
149
+ * be combined recursively.
150
+ */
114
151
  export interface PluginSettingCondition {
115
152
  /** Single setting key to compare. Preserves the original condition shape. */
116
153
  setting?: string;
154
+ /** Match when the referenced value is strictly equal to this value. */
117
155
  equals?: unknown;
156
+ /** Match when the referenced value is not strictly equal to this value. */
118
157
  notEquals?: unknown;
119
158
  /** All nested conditions must match. */
120
159
  allOf?: PluginSettingCondition[];
@@ -130,6 +169,7 @@ export const PluginSettingConditionSchema: z.ZodType<PluginSettingCondition> = z
130
169
  anyOf: z.array(PluginSettingConditionSchema).optional(),
131
170
  }));
132
171
 
172
+ /** Description override selected when its condition matches. */
133
173
  export const PluginSettingConditionalDescriptionSchema = z.object({
134
174
  when: PluginSettingConditionSchema,
135
175
  description: z.string(),
@@ -156,6 +196,17 @@ export type PluginSettingScope = z.infer<typeof PluginSettingScopeSchema>;
156
196
  *
157
197
  * The host uses this schema to generate configuration forms, validate updates
158
198
  * and resolve default values before injecting them into `ctx.config`.
199
+ *
200
+ * Collection defaults must match the selected renderer:
201
+ * - `string[]` -> `string[]`
202
+ * - `object[]` -> `Array<Record<string, unknown>>` described by `itemFields`
203
+ * - `keyedStringArrays` -> `Record<string, string[]>`
204
+ * - `keyedObjectArrays` -> `Record<string, Array<Record<string, unknown>>>`
205
+ * - `keyedObjects` -> `Record<string, Record<string, unknown>>`
206
+ *
207
+ * Keyed editors use `keys` for their fixed outer keys; object-based editors use
208
+ * `itemFields` for the nested shape. `info` is display-only and cannot be used
209
+ * by `quickSettings`.
159
210
  */
160
211
  export const PluginSettingDescriptorSchema = z.object({
161
212
  type: PluginSettingTypeSchema,
@@ -167,7 +218,7 @@ export const PluginSettingDescriptorSchema = z.object({
167
218
  options: z.array(PluginSettingOptionSchema).optional(),
168
219
  /** Field schema used by generated editors for `object[]` settings. */
169
220
  itemFields: z.array(PluginObjectArrayFieldSchema).optional(),
170
- /** Fixed key list used by generated editors for `keyedStringArrays` settings. */
221
+ /** Fixed key list used by generated keyed setting editors. */
171
222
  keys: z.array(PluginKeyedStringArrayKeySchema).optional(),
172
223
  /** Conditionally show the field based on another setting in the same form. */
173
224
  visibleWhen: PluginSettingConditionSchema.optional(),
@@ -231,6 +282,7 @@ export type PluginQuickSetting = z.infer<typeof PluginQuickSettingSchema>;
231
282
  * about plugin roles without hard-coding specific plugin names.
232
283
  */
233
284
  export const PluginCapabilitySchema = z.enum([
285
+ 'auto_call_control',
234
286
  'auto_call_candidate',
235
287
  'auto_call_execution',
236
288
  ]);
@@ -354,6 +406,10 @@ export const PluginPanelDescriptorSchema = z.object({
354
406
  */
355
407
  export type PluginPanelDescriptor = z.infer<typeof PluginPanelDescriptorSchema>;
356
408
 
409
+ /**
410
+ * Plugin instance that owns a runtime panel contribution: the single global
411
+ * instance or one explicitly identified operator instance.
412
+ */
357
413
  export const PluginUIPanelContributionTargetSchema = z.discriminatedUnion('kind', [
358
414
  z.object({ kind: z.literal('global') }),
359
415
  z.object({ kind: z.literal('operator'), operatorId: z.string() }),
@@ -455,9 +511,11 @@ export type PluginStorageConfig = z.infer<typeof PluginStorageConfigSchema>;
455
511
  * host can expose to management UI and diagnostics.
456
512
  */
457
513
  export const PluginManifestSchema = z.object({
514
+ apiVersion: z.literal(2).optional(),
458
515
  name: z.string(),
459
516
  version: z.string(),
460
517
  type: PluginTypeSchema,
518
+ strategyFeatures: StrategyFeaturesSchema,
461
519
  instanceScope: PluginInstanceScopeSchema.optional().default('operator'),
462
520
  description: z.string().optional(),
463
521
  permissions: z.array(PluginPermissionSchema).optional(),
@@ -503,6 +561,7 @@ export type PluginLocales = z.infer<typeof PluginLocalesSchema>;
503
561
  export const PluginStatusSchema = z.object({
504
562
  name: z.string(),
505
563
  type: PluginTypeSchema,
564
+ strategyFeatures: StrategyFeaturesSchema,
506
565
  instanceScope: PluginInstanceScopeSchema.optional().default('operator'),
507
566
  version: z.string(),
508
567
  description: z.string().optional(),
@@ -521,6 +580,8 @@ export const PluginStatusSchema = z.object({
521
580
  panels: z.array(PluginPanelDescriptorSchema).optional(),
522
581
  permissions: z.array(PluginPermissionSchema).optional(),
523
582
  capabilities: z.array(PluginCapabilitySchema).optional(),
583
+ autoCallEnabledOperatorIds: z.array(z.string()).optional(),
584
+ pausedOperatorIds: z.array(z.string()).optional(),
524
585
  ui: PluginUIConfigSchema.optional(),
525
586
  locales: PluginLocalesSchema.optional(),
526
587
  source: PluginSourceSchema.optional(),
@@ -620,6 +681,8 @@ export const PluginMarketCatalogEntrySchema = z.object({
620
681
  name: z.string(),
621
682
  title: z.string(),
622
683
  description: z.string(),
684
+ readmeMarkdown: z.string().max(100 * 1024).optional(),
685
+ readmeSourceUrl: z.string().url().optional(),
623
686
  locales: PluginLocalesSchema.optional(),
624
687
  latestVersion: z.string(),
625
688
  minHostVersion: z.string(),
@@ -686,6 +749,8 @@ export const PluginsConfigSchema = z.object({
686
749
  z.string(),
687
750
  z.record(z.string(), z.record(z.string(), z.unknown()))
688
751
  ).optional().default({}),
752
+ /** 每操作员暂停的 transmit-control 插件:operatorId → pluginName[] */
753
+ operatorPluginPauses: z.record(z.string(), z.array(z.string())).optional().default({}),
689
754
  });
690
755
  export type PluginsConfig = z.infer<typeof PluginsConfigSchema>;
691
756
 
@@ -16,9 +16,7 @@ export const PSKReporterStatsSchema = z.object({
16
16
  consecutiveFailures: z.number().default(0),
17
17
  });
18
18
 
19
- /**
20
- * PSKReporter 配置 Schema
21
- */
19
+ /** PSK Reporter publishing identity, antenna metadata, interval and counters. */
22
20
  export const PSKReporterConfigSchema = z.object({
23
21
  /** 是否启用 PSKReporter 上报 */
24
22
  enabled: z.boolean().default(false),
@@ -91,6 +91,13 @@ export const QslSimpleStatusSchema = z.enum(['Y', 'N']).optional();
91
91
  * - DXCC enrichment and review metadata;
92
92
  * - LoTW / QRZ confirmation state;
93
93
  * - station-location metadata used when exporting ADIF-like records.
94
+ *
95
+ * `frequency` is the RF frequency in hertz; `startTime`/`endTime` and QSL dates
96
+ * are Unix epoch milliseconds. `mode` is the ADIF main mode and `submode` is the
97
+ * optional ADIF submode. `messageHistory` contains the raw digital-mode exchange.
98
+ * Sync providers update the service-specific LoTW/QRZ fields using ADIF status
99
+ * codes (`Y`, `N`, `R`, `Q`, `I`, and received-only `V`) rather than a generic
100
+ * `qslStatus` field.
94
101
  */
95
102
  export const QSORecordSchema = z.object({
96
103
  id: z.string(),
@@ -36,9 +36,7 @@ export type CapabilityUpdateMode = z.infer<typeof CapabilityUpdateModeSchema>;
36
36
  export const CapabilityOptionValueSchema = z.union([z.string(), z.number()]);
37
37
  export type CapabilityOptionValue = z.infer<typeof CapabilityOptionValueSchema>;
38
38
 
39
- /**
40
- * 运行时能力值。
41
- */
39
+ /** Runtime value carried by a radio capability state. */
42
40
  export const CapabilityValueSchema = z.union([z.boolean(), z.number(), z.string()]);
43
41
  export type CapabilityValue = z.infer<typeof CapabilityValueSchema>;
44
42
 
@@ -84,10 +82,7 @@ export const CapabilityDisplaySchema = z.object({
84
82
  });
85
83
  export type CapabilityDisplay = z.infer<typeof CapabilityDisplaySchema>;
86
84
 
87
- /**
88
- * 能力描述符
89
- * 由服务端在运行时下发,作为当前连接会话的真源。
90
- */
85
+ /** Host-provided descriptor that defines one capability for the current session. */
91
86
  export const CapabilityDescriptorSchema = z.object({
92
87
  /** 全局唯一能力 ID,如 'tuner_switch', 'rf_power', 'lock_mode' */
93
88
  id: z.string(),
@@ -165,10 +160,7 @@ export const CapabilityDescriptorSchema = z.object({
165
160
 
166
161
  export type CapabilityDescriptor = z.infer<typeof CapabilityDescriptorSchema>;
167
162
 
168
- /**
169
- * 能力运行时状态
170
- * 动态数据,通过 WebSocket 实时同步到前端。
171
- */
163
+ /** Dynamic support, availability and value state for one capability. */
172
164
  export const CapabilityStateSchema = z.object({
173
165
  /** 能力 ID,与 CapabilityDescriptor.id 对应 */
174
166
  id: z.string(),
@@ -209,9 +201,7 @@ export const CapabilityStateSchema = z.object({
209
201
 
210
202
  export type CapabilityState = z.infer<typeof CapabilityStateSchema>;
211
203
 
212
- /**
213
- * 能力列表快照(radioCapabilityList WS 消息 / REST 响应的 data 部分)
214
- */
204
+ /** Complete descriptor/state snapshot returned by radio capability APIs. */
215
205
  export const CapabilityListSchema = z.object({
216
206
  descriptors: z.array(CapabilityDescriptorSchema),
217
207
  capabilities: z.array(CapabilityStateSchema),
@@ -220,7 +210,8 @@ export const CapabilityListSchema = z.object({
220
210
  export type CapabilityList = z.infer<typeof CapabilityListSchema>;
221
211
 
222
212
  /**
223
- * 写命令负载(writeRadioCapability WS 命令的 data 部分)
213
+ * Legacy WebSocket payload for writing a generic radio capability.
214
+ * Plugin API v2 uses explicit radio/tuner command ports instead.
224
215
  */
225
216
  export const WriteCapabilityPayloadSchema = z.object({
226
217
  /** 能力 ID */
@@ -284,6 +275,7 @@ export const CAPABILITY_IDS = [
284
275
  'agc_mode',
285
276
  'preamp',
286
277
  'attenuator',
278
+ 'radio_mode',
287
279
  'mode_bandwidth',
288
280
  'split_enabled',
289
281
  'vfo_select',
@@ -111,6 +111,9 @@ export function decidePowerSupport(
111
111
  // ICOM WLAN 的 CI-V-over-UDP 通道在电台关机后无法维持;即便已连接
112
112
  // 发送 powerstat(off) 也不能可靠恢复。整体不暴露电源控制。
113
113
  return { canPowerOn: false, canPowerOff: false, supportedStates: [], reason: 'model-unsupported' };
114
+ case 'tci':
115
+ // TCI/ExpertSDR does not expose a safe physical power-on path here.
116
+ return { canPowerOn: false, canPowerOff: false, supportedStates: [], reason: 'model-unsupported' };
114
117
  case 'serial': {
115
118
  if (!rigInfo) {
116
119
  return { canPowerOn: false, canPowerOff: false, supportedStates: [], reason: 'model-unsupported' };
@@ -37,7 +37,9 @@ export const RadioPowerStageSchema = z.enum([
37
37
  export type RadioPowerStage = z.infer<typeof RadioPowerStageSchema>;
38
38
 
39
39
  /**
40
- * WS event payload: server client.
40
+ * Last known power transition state exposed through WebSocket events and
41
+ * `ctx.radioPower.getState()`. `state` is the controller's high-level state;
42
+ * `stage` is finer progress; errors use a localized key plus diagnostic detail.
41
43
  */
42
44
  export const RadioPowerStateEventSchema = z.object({
43
45
  profileId: z.string().optional(),
@@ -51,12 +53,17 @@ export const RadioPowerStateEventSchema = z.object({
51
53
  export type RadioPowerStateEvent = z.infer<typeof RadioPowerStateEventSchema>;
52
54
 
53
55
  /**
54
- * REST request body: POST /api/radio/power
56
+ * Power targets accepted by Host commands. `on`/`off` control physical power;
57
+ * `standby`/`operate` switch a responding radio between controller states.
55
58
  */
56
- /** Allowed physical radio target states for a power request. */
57
59
  export const RadioPowerTargetSchema = z.enum(['on', 'off', 'standby', 'operate']);
58
60
  export type RadioPowerTarget = z.infer<typeof RadioPowerTargetSchema>;
59
61
 
62
+ /**
63
+ * Request to transition one radio profile to a physical/controller power state.
64
+ * `profileId` selects the profile, `state` is the requested target, and
65
+ * `autoEngine` controls whether TX-5DR starts after a successful power-on.
66
+ */
60
67
  export const RadioPowerRequestSchema = z.object({
61
68
  profileId: z.string().min(1),
62
69
  /** Physical radio power target. This is not the TX-5DR software engine state. */
@@ -66,9 +73,7 @@ export const RadioPowerRequestSchema = z.object({
66
73
  });
67
74
  export type RadioPowerRequest = z.infer<typeof RadioPowerRequestSchema>;
68
75
 
69
- /**
70
- * REST response: POST /api/radio/power
71
- */
76
+ /** Result returned by the REST endpoint and `ctx.radioPowerCommands.submit()`. */
72
77
  export const RadioPowerResponseSchema = z.object({
73
78
  success: z.boolean(),
74
79
  target: RadioPowerTargetSchema,
@@ -77,8 +82,10 @@ export const RadioPowerResponseSchema = z.object({
77
82
  export type RadioPowerResponse = z.infer<typeof RadioPowerResponseSchema>;
78
83
 
79
84
  /**
80
- * REST response: GET /api/radio/power/support?profileId=xxx
81
- * The server resolves mfgName/modelName internally via HamLib.getSupportedRigs().
85
+ * Power operations supported by one radio profile, returned by REST and
86
+ * `ctx.radioPower.getSupport()`. `reason` explains why wake is unavailable;
87
+ * `supportedStates` lists connected-state transitions the Host may accept.
88
+ * The Host resolves manufacturer/model names through Hamlib.
82
89
  */
83
90
  export const RadioPowerSupportInfoSchema = z.object({
84
91
  profileId: z.string(),
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { CWKeyActiveLevelSchema } from './cw-keyer.schema.js';
2
3
 
3
4
  /**
4
5
  * 中继差频方向
@@ -10,9 +11,7 @@ export const RepeaterShiftSchema = z.enum(['none', 'minus', 'plus']);
10
11
  */
11
12
  export const ToneSquelchModeSchema = z.enum(['none', 'ctcss', 'dcs']);
12
13
 
13
- /**
14
- * 预设频率Schema
15
- */
14
+ /** Saved dial-frequency preset with band, digital mode and radio modulation. */
16
15
  export const PresetFrequencySchema = z.object({
17
16
  band: z.string(),
18
17
  mode: z.string(), // 协议模式,如 FT8, FT4
@@ -192,11 +191,26 @@ export const IcomWlanConfigSchema = z.object({
192
191
  dataMode: z.boolean().optional().default(true),
193
192
  });
194
193
 
194
+
195
+ /**
196
+ * TCI / SunSDR 连接配置Schema
197
+ */
198
+ export const TciConfigSchema = z.object({
199
+ host: z.string().default('127.0.0.1'),
200
+ port: z.number().int().min(1).max(65535).default(40001),
201
+ receiver: z.number().int().min(0).default(0),
202
+ trx: z.number().int().min(0).default(0),
203
+ vfo: z.number().int().min(0).default(0),
204
+ audioEnabled: z.boolean().optional().default(true),
205
+ audioSampleRate: z.number().int().min(8000).max(48000).optional().default(12000),
206
+ });
207
+
195
208
  /**
196
209
  * 串口连接配置Schema
197
210
  */
198
211
  export const SerialConnectionConfigSchema = z.object({
199
212
  path: z.string(),
213
+ serialNumber: z.string().optional(),
200
214
  rigModel: z.number().int(),
201
215
  serialConfig: SerialConfigSchema.optional(),
202
216
  backendConfig: HamlibBackendConfigSchema.optional(),
@@ -206,6 +220,15 @@ export const HamlibSpectrumConfigSchema = z.object({
206
220
  speed: z.number().int().min(0).max(255).optional(),
207
221
  });
208
222
 
223
+ /**
224
+ * FT8/FT4 数字模式切换频率时的电台 CAT 模式偏好。
225
+ *
226
+ * - none: 只切换频率,不主动设置电台模式
227
+ * - usb: 设置普通 USB
228
+ * - usb-data: 设置 USB-DATA / PKTUSB 类数据模式
229
+ */
230
+ export const DigitalModeRadioModePreferenceSchema = z.enum(['none', 'usb', 'usb-data']);
231
+
209
232
  /**
210
233
  * PTT (Push-to-Talk) 方法Schema
211
234
  *
@@ -216,6 +239,15 @@ export const HamlibSpectrumConfigSchema = z.object({
216
239
  */
217
240
  export const PttMethodSchema = z.enum(['cat', 'vox', 'dtr', 'rts']);
218
241
 
242
+ /**
243
+ * 虚拟频差(Virtual Frequency Offset / "Fake It" Split)配置Schema
244
+ * 目标音频频率与滞回区间目前由服务端常量控制(~1500Hz),此处仅暴露开关,预留扩展位。
245
+ */
246
+ export const FakeFrequencyConfigSchema = z.object({
247
+ enabled: z.boolean(),
248
+ });
249
+ export type FakeFrequencyConfig = z.infer<typeof FakeFrequencyConfigSchema>;
250
+
219
251
  /**
220
252
  * Hamlib配置Schema - 嵌套对象结构
221
253
  *
@@ -226,7 +258,7 @@ export const PttMethodSchema = z.enum(['cat', 'vox', 'dtr', 'rts']);
226
258
  * - 根据 type 字段读取对应的配置对象
227
259
  */
228
260
  export const HamlibConfigSchema = z.object({
229
- type: z.enum(['none', 'network', 'serial', 'icom-wlan']),
261
+ type: z.enum(['none', 'network', 'serial', 'icom-wlan', 'tci']),
230
262
 
231
263
  // 网络模式配置
232
264
  network: NetworkConfigSchema.optional(),
@@ -234,17 +266,29 @@ export const HamlibConfigSchema = z.object({
234
266
  // ICOM WLAN 模式配置
235
267
  icomWlan: IcomWlanConfigSchema.optional(),
236
268
 
269
+ // TCI / SunSDR 模式配置
270
+ tci: TciConfigSchema.optional(),
271
+
237
272
  // 串口模式配置
238
273
  serial: SerialConnectionConfigSchema.optional(),
239
274
 
240
275
  // Hamlib 频谱配置(当前仅用于官方频谱流 speed)
241
276
  spectrum: HamlibSpectrumConfigSchema.optional(),
242
277
 
278
+ // FT8/FT4 切换频率时是否主动设置电台 CAT 模式;未设置时按 none 处理
279
+ digitalModeRadioMode: DigitalModeRadioModePreferenceSchema.optional(),
280
+
243
281
  // 发射时序补偿(毫秒)- 用于补偿电台和网络的处理延迟
244
282
  // 正值表示提前发射,负值表示延后发射
245
283
  // 范围限制:-1000~1000ms,适用于各种网络和设备延迟场景
246
284
  transmitCompensationMs: z.number().int().min(-1000).max(1000).optional(),
247
285
 
286
+ // 虚拟频差(Virtual Frequency Offset / WSJT-X "Fake It" Split)
287
+ // 启用后,发射时临时反向平移电台 dial 频率,使送进电台的音频载波保持在甜区(~1500Hz),
288
+ // 而打到空中的实际 RF 位置与用户设定的发射频点完全一致。
289
+ // 用于规避部分电台在音频频率过高/过低时发射功率衰减的问题;对用户透明(接收 dial、TX 标记不变)。
290
+ fakeFrequency: FakeFrequencyConfigSchema.optional(),
291
+
248
292
  // PTT 方法(默认 'cat',即 Hamlib RIG 类型)
249
293
  // 仅对 network 和 serial 连接类型有效,icom-wlan 固定使用 CI-V PTT
250
294
  pttMethod: PttMethodSchema.optional(),
@@ -258,6 +302,9 @@ export const HamlibConfigSchema = z.object({
258
302
 
259
303
  // CW 键控引脚类型(dtr 或 rts)
260
304
  cwKeyMethod: z.enum(['dtr', 'rts']).optional(),
305
+
306
+ // CW 键控有效电平(默认 high,即高电平按下;部分接口为低电平按下)
307
+ cwKeyActiveLevel: CWKeyActiveLevelSchema.optional(),
261
308
  });
262
309
 
263
310
  /**
@@ -303,7 +350,7 @@ export const RadioInfoSchema = z.object({
303
350
  /** Hamlib 电台型号 ID (serial/network 模式使用,icom-wlan 模式可选) */
304
351
  rigModel: z.number().optional(),
305
352
  /** 连接类型 */
306
- connectionType: z.enum(['serial', 'network', 'icom-wlan']),
353
+ connectionType: z.enum(['serial', 'network', 'icom-wlan', 'tci']),
307
354
  /** 固件版本 (如果可获取) */
308
355
  firmwareVersion: z.string().optional(),
309
356
  /** 序列号 (如果可获取) */
@@ -315,6 +362,7 @@ export const RadioInfoSchema = z.object({
315
362
  */
316
363
  export const SerialPortSchema = z.object({
317
364
  path: z.string(),
365
+ friendlyName: z.string().optional(),
318
366
  manufacturer: z.string().optional(),
319
367
  serialNumber: z.string().optional(),
320
368
  pnpId: z.string().optional(),
@@ -461,8 +509,10 @@ export type HamlibConfigFieldType = z.infer<typeof HamlibConfigFieldTypeSchema>;
461
509
  export type HamlibConfigField = z.infer<typeof HamlibConfigFieldSchema>;
462
510
  export type NetworkConfig = z.infer<typeof NetworkConfigSchema>;
463
511
  export type IcomWlanConfig = z.infer<typeof IcomWlanConfigSchema>;
512
+ export type TciConfig = z.infer<typeof TciConfigSchema>;
464
513
  export type SerialConnectionConfig = z.infer<typeof SerialConnectionConfigSchema>;
465
514
  export type HamlibSpectrumConfig = z.infer<typeof HamlibSpectrumConfigSchema>;
515
+ export type DigitalModeRadioModePreference = z.infer<typeof DigitalModeRadioModePreferenceSchema>;
466
516
  export type PttMethod = z.infer<typeof PttMethodSchema>;
467
517
  export type HamlibConfig = z.infer<typeof HamlibConfigSchema>;
468
518
  export type RadioConfigResponse = z.infer<typeof RadioConfigResponseSchema>;
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
  export const RealtimeScopeSchema = z.enum(['radio', 'openwebrx-preview']);
4
4
  export type RealtimeScope = z.infer<typeof RealtimeScopeSchema>;
5
5
 
6
- export const RealtimeTransportKindSchema = z.enum(['rtc-data-audio', 'ws-compat']);
6
+ export const RealtimeTransportKindSchema = z.enum(['rtc-data-audio', 'ws-compat', 'android-native']);
7
7
  export type RealtimeTransportKind = z.infer<typeof RealtimeTransportKindSchema>;
8
8
 
9
9
  export const RealtimeSessionDirectionSchema = z.enum(['recv', 'send']);
@@ -307,6 +307,13 @@ export const RealtimeSessionResponseSchema = z.object({
307
307
 
308
308
  export type RealtimeSessionResponse = z.infer<typeof RealtimeSessionResponseSchema>;
309
309
 
310
+ /**
311
+ * Persisted realtime-audio transport preferences.
312
+ *
313
+ * `transportPolicy` selects automatic or explicit transport behavior. The
314
+ * optional public host/UDP port advertise an RTC data-audio endpoint to remote
315
+ * clients; null/omitted values disable that public candidate.
316
+ */
310
317
  export const RealtimeSettingsSchema = z.object({
311
318
  transportPolicy: RealtimeTransportPolicySchema.optional(),
312
319
  rtcDataAudioPublicHost: RtcDataAudioPublicHostSchema.optional(),
@@ -333,6 +340,7 @@ export const RealtimeSettingsRuntimeSchema = z.object({
333
340
 
334
341
  export type RealtimeSettingsRuntime = z.infer<typeof RealtimeSettingsRuntimeSchema>;
335
342
 
343
+ /** Realtime settings plus the Host's current resolved runtime projection. */
336
344
  export const RealtimeSettingsResponseDataSchema = RealtimeSettingsSchema.extend({
337
345
  runtime: RealtimeSettingsRuntimeSchema.optional(),
338
346
  });
@@ -1,6 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { DxccStatusSchema, SubdivisionConfidenceSchema } from './qso.schema.js';
3
3
 
4
+ /** Number of non-empty slot packs retained for live FT8/FT4 message history. */
5
+ export const SLOT_PACK_HISTORY_LIMIT = 1000;
6
+
4
7
  /**
5
8
  * Frequency context captured when a slot pack is created.
6
9
  * Fields are optional so older persisted slot packs remain valid.
@@ -16,11 +19,12 @@ export const SlotPackFrequencyContextSchema = z.object({
16
19
  export type SlotPackFrequencyContext = z.infer<typeof SlotPackFrequencyContextSchema>;
17
20
 
18
21
  /**
19
- * 时隙周期(偶数奇数)
20
- */
21
-
22
- /**
23
- * 时隙信息
22
+ * Timing and identity of one FT8/FT4 receive or transmit slot.
23
+ *
24
+ * `startMs` is the calibrated Unix epoch start in milliseconds; `phaseMs` is
25
+ * elapsed time inside the slot; `driftMs` is the clock correction; `cycleNumber`
26
+ * is the absolute slot index (use modulo two for even/odd); and `utcSeconds` is
27
+ * the integer epoch-second form used for display and logs.
24
28
  */
25
29
  export const SlotInfoSchema = z.object({
26
30
  /** 时隙唯一标识符 */
@@ -41,9 +45,7 @@ export const SlotInfoSchema = z.object({
41
45
 
42
46
  export type SlotInfo = z.infer<typeof SlotInfoSchema>;
43
47
 
44
- /**
45
- * 基于日志本的消息分析结果
46
- */
48
+ /** Logbook-derived enrichment attached to a decoded message when available. */
47
49
  export const LogbookAnalysisSchema = z.object({
48
50
  /** 是否为新呼号(之前没有通联过) */
49
51
  isNewCallsign: z.boolean().optional(),
@@ -76,7 +78,9 @@ export const LogbookAnalysisSchema = z.object({
76
78
  export type LogbookAnalysis = z.infer<typeof LogbookAnalysisSchema>;
77
79
 
78
80
  /**
79
- * FT8 帧数据
81
+ * Original decoder frame with RF metrics and unparsed message text.
82
+ * `snr` is dB, `freq` is audio offset in hertz, `dt` is seconds, and
83
+ * `confidence` is normalized to 0..1.
80
84
  */
81
85
  export const FrameMessageSchema = z.object({
82
86
  /** 信号强度 (dB) */
@@ -157,7 +161,9 @@ export const DecodeResultSchema = z.object({
157
161
  export type DecodeResult = z.infer<typeof DecodeResultSchema>;
158
162
 
159
163
  /**
160
- * 时隙封装信息(去重和多次解码取优)
164
+ * Deduplicated best-frame collection for one slot, including decode statistics,
165
+ * history and the dial-frequency context captured when the slot began.
166
+ * `startMs`, `endMs` and history timestamps use Unix epoch milliseconds.
161
167
  */
162
168
  export const SlotPackSchema = z.object({
163
169
  /** 时隙ID */
@@ -16,6 +16,11 @@ export const StationQthSchema = z.object({
16
16
  longitude: z.number().min(-180).max(180).optional(),
17
17
  });
18
18
 
19
+ /**
20
+ * Public station profile shown to clients and exposed through plugin settings.
21
+ * It contains optional display identity, callsign, Markdown description and QTH
22
+ * coordinates/grid; it never contains authentication or radio credentials.
23
+ */
19
24
  export const StationInfoSchema = z.object({
20
25
  /** Station display name, e.g. "BG7XXX Remote Station" */
21
26
  name: z.string().max(100).optional(),
@@ -1,4 +1,6 @@
1
1
  import { z } from 'zod';
2
+ import { RemoteAccessPresetSchema } from './auth.schema.js';
3
+ import { PluginDistributionSchema } from './plugin.schema.js';
2
4
 
3
5
  // ===== 网络信息 =====
4
6
 
@@ -13,10 +15,35 @@ export const NetworkInfoSchema = z.object({
13
15
  addresses: z.array(NetworkAddressSchema),
14
16
  hostname: z.string(),
15
17
  webPort: z.number(),
18
+ exposure: RemoteAccessPresetSchema.default('lan'),
19
+ listenHost: z.string().default('0.0.0.0'),
20
+ runtimeManagement: z.enum(['electron', 'external']).default('external'),
21
+ distribution: PluginDistributionSchema.default('generic-server'),
22
+ supportsLocalOnly: z.boolean().default(false),
23
+ supportedPresets: z.array(RemoteAccessPresetSchema).min(1).default(['lan', 'public']),
24
+ activeConnections: z.number().int().nonnegative().default(0),
25
+ maxConnections: z.number().int().positive().default(32),
16
26
  });
17
27
 
18
28
  export type NetworkInfo = z.infer<typeof NetworkInfoSchema>;
19
29
 
30
+ // ===== 日志设置 =====
31
+
32
+ export const SystemLogLevelSchema = z.enum(['debug', 'info', 'warn', 'error']);
33
+ export type SystemLogLevel = z.infer<typeof SystemLogLevelSchema>;
34
+
35
+ export const SystemLoggingSettingsSchema = z.object({
36
+ level: SystemLogLevelSchema.optional(),
37
+ effectiveLevel: SystemLogLevelSchema,
38
+ logsDir: z.string(),
39
+ });
40
+ export type SystemLoggingSettings = z.infer<typeof SystemLoggingSettingsSchema>;
41
+
42
+ export const UpdateSystemLoggingSettingsSchema = z.object({
43
+ level: SystemLogLevelSchema,
44
+ });
45
+ export type UpdateSystemLoggingSettingsRequest = z.infer<typeof UpdateSystemLoggingSettingsSchema>;
46
+
20
47
  // ===== 时钟状态 =====
21
48
 
22
49
  export const ClockSyncStateSchema = z.enum(['synced', 'stale', 'never', 'failed']);
@@ -115,12 +142,14 @@ const NtpServerArraySchema = z.array(NtpServerHostSchema).min(1).superRefine((se
115
142
  }
116
143
  });
117
144
 
145
+ /** Active NTP server list together with the Host-provided default list. */
118
146
  export const NtpServerListSettingsSchema = z.object({
119
147
  servers: NtpServerArraySchema,
120
148
  defaultServers: NtpServerArraySchema,
121
149
  });
122
150
  export type NtpServerListSettings = z.infer<typeof NtpServerListSettingsSchema>;
123
151
 
152
+ /** Complete replacement list accepted by `ctx.settings.ntp.update()`. */
124
153
  export const UpdateNtpServerListRequestSchema = z.object({
125
154
  servers: NtpServerArraySchema,
126
155
  });