@nekro-nxt/contracts 0.0.0-stage → 0.2.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,4694 @@
1
+ import { z } from "zod";
2
+ //#region src/domain.ts
3
+ const brandedId = (prefix, brand) => z.string().regex(new RegExp(`^${prefix}_[0-9A-Za-z]+$`), `${brand} has an invalid format.`).brand(brand);
4
+ const AgentIdSchema = brandedId("agt", "AgentId");
5
+ const AgentRevisionIdSchema = brandedId("arev", "AgentRevisionId");
6
+ const ConnectionIdSchema = brandedId("con", "ConnectionId");
7
+ const ConnectionEventIdSchema = brandedId("cev", "ConnectionEventId");
8
+ const ChannelIdSchema = brandedId("chn", "ChannelId");
9
+ const ChannelEventIdSchema = brandedId("evt", "ChannelEventId");
10
+ const PlatformIdentityIdSchema = brandedId("pid", "PlatformIdentityId");
11
+ const ChannelMemberIdSchema = brandedId("mbr", "ChannelMemberId");
12
+ const AdmissionIdSchema = brandedId("adm", "AdmissionId");
13
+ const OutboundIntentIdSchema = brandedId("out", "OutboundIntentId");
14
+ const LogicalMessageIdSchema = brandedId("msg", "LogicalMessageId");
15
+ const PhysicalDeliveryIdSchema = brandedId("phy", "PhysicalDeliveryId");
16
+ const AssetIdSchema = brandedId("ast", "AssetId");
17
+ const EpisodeIdSchema = brandedId("eps", "EpisodeId");
18
+ const EpisodeHandoffIdSchema = brandedId("hof", "EpisodeHandoffId");
19
+ const ExtensionIdSchema = brandedId("ext", "ExtensionId");
20
+ const ExtensionRevisionIdSchema = brandedId("xrv", "ExtensionRevisionId");
21
+ const DshPluginPackageIdSchema = brandedId("dsp", "DshPluginPackageId");
22
+ const DshPluginEntryIdSchema = brandedId("dse", "DshPluginEntryId");
23
+ const HostUiPageInstanceIdSchema = brandedId("hup", "HostUiPageInstanceId");
24
+ const AuthoringTaskIdSchema = brandedId("aut", "AuthoringTaskId");
25
+ const AuthoringAttemptIdSchema = brandedId("aua", "AuthoringAttemptId");
26
+ const AdapterActivityKeySchema = z.string().trim().min(1).max(128).regex(/^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/u, "Adapter activity key has an invalid format.");
27
+ const PromptTextSegmentSchema = z.object({
28
+ type: z.literal("text"),
29
+ text: z.string()
30
+ }).strict();
31
+ const PromptReferenceLabelSchema = z.string().trim().min(1).max(120);
32
+ const PromptReferenceSegmentSchema = z.discriminatedUnion("kind", [
33
+ z.object({
34
+ type: z.literal("reference"),
35
+ kind: z.literal("platform-user"),
36
+ targetId: PlatformIdentityIdSchema,
37
+ labelSnapshot: PromptReferenceLabelSchema
38
+ }).strict(),
39
+ z.object({
40
+ type: z.literal("reference"),
41
+ kind: z.literal("channel"),
42
+ targetId: ChannelIdSchema,
43
+ labelSnapshot: PromptReferenceLabelSchema
44
+ }).strict(),
45
+ z.object({
46
+ type: z.literal("reference"),
47
+ kind: z.literal("extension"),
48
+ targetId: ExtensionIdSchema,
49
+ labelSnapshot: PromptReferenceLabelSchema
50
+ }).strict()
51
+ ]);
52
+ const PromptSegmentSchema = z.union([PromptTextSegmentSchema, PromptReferenceSegmentSchema]);
53
+ const PROMPT_DOCUMENT_MAX_REFERENCES = 128;
54
+ const PROMPT_DOCUMENT_MAX_PLAIN_TEXT_LENGTH = 64 * 1024;
55
+ const PromptDocumentV1Schema = z.object({
56
+ version: z.literal(1),
57
+ segments: z.array(PromptSegmentSchema)
58
+ }).strict().superRefine((document, context) => {
59
+ if (document.segments.filter((segment) => segment.type === "reference").length > 128) context.addIssue({
60
+ code: "custom",
61
+ message: `Prompt document must not contain more than 128 references.`,
62
+ path: ["segments"]
63
+ });
64
+ if (document.segments.reduce((length, segment) => length + (segment.type === "text" ? segment.text.length : segment.labelSnapshot.length + 1), 0) > 65536) context.addIssue({
65
+ code: "custom",
66
+ message: `Prompt document plain-text projection must not exceed ${PROMPT_DOCUMENT_MAX_PLAIN_TEXT_LENGTH} characters.`,
67
+ path: ["segments"]
68
+ });
69
+ });
70
+ const promptDocumentFromText = (text) => normalizePromptDocument({
71
+ version: 1,
72
+ segments: text.length === 0 ? [] : [{
73
+ type: "text",
74
+ text
75
+ }]
76
+ });
77
+ const promptDocumentPlainText = (document) => document.segments.map((segment) => segment.type === "text" ? segment.text : `@${segment.labelSnapshot}`).join("");
78
+ const normalizePromptDocument = (input) => {
79
+ const parsed = PromptDocumentV1Schema.parse(input);
80
+ const segments = [];
81
+ for (const segment of parsed.segments) {
82
+ if (segment.type === "text") {
83
+ if (segment.text.length === 0) continue;
84
+ const previous = segments.at(-1);
85
+ if (previous?.type === "text") segments[segments.length - 1] = {
86
+ type: "text",
87
+ text: `${previous.text}${segment.text}`
88
+ };
89
+ else segments.push(segment);
90
+ continue;
91
+ }
92
+ segments.push(segment);
93
+ }
94
+ return PromptDocumentV1Schema.parse({
95
+ version: 1,
96
+ segments
97
+ });
98
+ };
99
+ const JsonValueSchema = z.json();
100
+ function parseJsonValue(input) {
101
+ return JsonValueSchema.parse(input);
102
+ }
103
+ const utf8ByteLength = (value) => new TextEncoder().encode(value).byteLength;
104
+ const RICH_EXTENSION_MAX_BYTES = 64 * 1024;
105
+ const RichExtensionSchema = JsonValueSchema.refine((value) => utf8ByteLength(JSON.stringify(value)) <= RICH_EXTENSION_MAX_BYTES, `rich extension must not exceed ${RICH_EXTENSION_MAX_BYTES} bytes.`);
106
+ const RichTargetUrlSchema = z.url().max(2048).refine((value) => {
107
+ const protocol = new URL(value).protocol;
108
+ return protocol === "http:" || protocol === "https:";
109
+ }, "rich target URL must use HTTP or HTTPS.");
110
+ const MessagePartSchema = z.discriminatedUnion("type", [
111
+ z.object({
112
+ type: z.literal("text"),
113
+ text: z.string()
114
+ }).strict(),
115
+ z.object({
116
+ type: z.literal("mention"),
117
+ memberId: ChannelMemberIdSchema
118
+ }).strict(),
119
+ z.object({
120
+ type: z.literal("image"),
121
+ assetId: AssetIdSchema,
122
+ alt: z.string().optional()
123
+ }).strict(),
124
+ z.object({
125
+ type: z.literal("file"),
126
+ assetId: AssetIdSchema,
127
+ name: z.string().optional()
128
+ }).strict(),
129
+ z.object({
130
+ type: z.literal("audio"),
131
+ assetId: AssetIdSchema
132
+ }).strict(),
133
+ z.object({
134
+ type: z.literal("quote"),
135
+ messageId: LogicalMessageIdSchema
136
+ }).strict(),
137
+ z.object({
138
+ type: z.literal("rich"),
139
+ adapterKey: z.string().trim().min(1).max(64),
140
+ kind: z.string().trim().min(1).max(64),
141
+ summary: z.string().trim().min(1).max(500),
142
+ title: z.string().trim().min(1).max(200).optional(),
143
+ source: z.string().trim().min(1).max(80).optional(),
144
+ targetUrl: RichTargetUrlSchema.optional(),
145
+ previewAssetId: AssetIdSchema.optional(),
146
+ extension: RichExtensionSchema.optional()
147
+ }).strict()
148
+ ]);
149
+ const MessagePartsSchema = z.array(MessagePartSchema);
150
+ const NonEmptyMessagePartsSchema = MessagePartsSchema.min(1);
151
+ function parseMessageParts(input) {
152
+ return MessagePartsSchema.parse(input);
153
+ }
154
+ const collectRichAssetIds = (value, into) => {
155
+ if (value === null || value === void 0 || typeof value === "boolean" || typeof value === "number") return;
156
+ if (typeof value === "string") return;
157
+ if (Array.isArray(value)) {
158
+ for (const item of value) collectRichAssetIds(item, into);
159
+ return;
160
+ }
161
+ for (const [key, child] of Object.entries(value)) if ((key === "imageAssetId" || key === "previewAssetId") && typeof child === "string") {
162
+ const parsed = AssetIdSchema.safeParse(child);
163
+ if (parsed.success) into.push(parsed.data);
164
+ } else collectRichAssetIds(child, into);
165
+ };
166
+ const messagePartAssetIds = (part) => {
167
+ if (part.type === "image" || part.type === "file" || part.type === "audio") return [part.assetId];
168
+ if (part.type !== "rich") return [];
169
+ const ids = [];
170
+ if (part.previewAssetId) ids.push(part.previewAssetId);
171
+ collectRichAssetIds(part.extension, ids);
172
+ return ids;
173
+ };
174
+ const messagePartAssetId = (part) => messagePartAssetIds(part)[0];
175
+ const asJsonRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
176
+ const richItemLine = (value) => {
177
+ const item = asJsonRecord(value);
178
+ if (!item) return void 0;
179
+ const sender = typeof item["sender"] === "string" ? item["sender"] : void 0;
180
+ const text = typeof item["text"] === "string" ? item["text"] : void 0;
181
+ const card = asJsonRecord(item["card"]);
182
+ const cardSummary = typeof card?.["summary"] === "string" ? card["summary"] : typeof card?.["title"] === "string" ? card["title"] : void 0;
183
+ const imageName = typeof item["imageName"] === "string" ? item["imageName"] : void 0;
184
+ const imageText = typeof item["imageAssetId"] === "string" ? `[图片${imageName ? ` ${imageName}` : ""}]` : void 0;
185
+ const body = [
186
+ text,
187
+ cardSummary ? `[卡片] ${cardSummary}` : void 0,
188
+ imageText
189
+ ].filter((part) => Boolean(part && part.length > 0)).join(" ");
190
+ if (!sender && !body) return void 0;
191
+ return sender ? `${sender}:${body}` : body;
192
+ };
193
+ /** Flatten a rich part for search and model context. */
194
+ const richPartContextText = (part) => {
195
+ const header = [
196
+ part.summary,
197
+ part.title,
198
+ part.source
199
+ ].filter((value, index, all) => typeof value === "string" && value.length > 0 && all.indexOf(value) === index);
200
+ const items = asJsonRecord(part.extension)?.["items"];
201
+ const itemLines = Array.isArray(items) ? items.flatMap((item) => {
202
+ const line = richItemLine(item);
203
+ return line === void 0 ? [] : [line];
204
+ }) : [];
205
+ return [...header, ...itemLines].join("\n");
206
+ };
207
+ const messagePartsSearchText = (parts) => parts.flatMap((part) => {
208
+ if (part.type === "text") return [part.text];
209
+ if (part.type === "rich") return [richPartContextText(part)];
210
+ return [];
211
+ }).join("\n");
212
+ //#endregion
213
+ //#region src/config-schema.ts
214
+ /**
215
+ * The single configuration format: serialized Schemastery (`Schema.toJSON()`), restricted to the subset the
216
+ * product form can render and the Host can validate without executing Schema callbacks.
217
+ *
218
+ * Supported nodes: object (dict), string, number, natural, percent, boolean, const, union of consts (enum) and
219
+ * array of primitives. `meta.role: 'secret'` marks a write-only credential. NekroNXT reads three extra meta keys:
220
+ * `hint` (help text), `advanced` (collapsed by default) and `visibleWhen` (show only when a sibling equals a value).
221
+ */
222
+ const CONFIG_SCHEMA_MAX_BYTES = 64 * 1024;
223
+ const DescriptionSchema = z.union([z.string(), z.record(z.string(), z.string())]);
224
+ const ConfigSchemaMetaSchema = z.object({
225
+ description: DescriptionSchema.optional(),
226
+ hint: z.string().max(500).optional(),
227
+ required: z.boolean().optional(),
228
+ default: JsonValueSchema.optional(),
229
+ role: z.string().max(32).optional(),
230
+ hidden: z.boolean().optional(),
231
+ min: z.number().finite().optional(),
232
+ max: z.number().finite().optional(),
233
+ step: z.number().finite().positive().optional(),
234
+ pattern: z.object({
235
+ source: z.string().max(500),
236
+ flags: z.string().max(8).optional()
237
+ }).optional(),
238
+ advanced: z.boolean().optional(),
239
+ group: z.string().max(40).optional(),
240
+ visibleWhen: z.object({
241
+ key: z.string().min(1).max(64),
242
+ equals: JsonValueSchema
243
+ }).strict().optional()
244
+ }).loose();
245
+ const SAFE_KEY = /^(?!__proto__$|prototype$|constructor$)[A-Za-z_$][\w$-]{0,63}$/u;
246
+ const ConfigSchemaNodeSchema = z.lazy(() => z.union([
247
+ z.object({
248
+ type: z.literal("object"),
249
+ dict: z.record(z.string().regex(SAFE_KEY), ConfigSchemaNodeSchema),
250
+ meta: ConfigSchemaMetaSchema.optional()
251
+ }).loose(),
252
+ z.object({
253
+ type: z.enum([
254
+ "string",
255
+ "number",
256
+ "natural",
257
+ "percent",
258
+ "boolean"
259
+ ]),
260
+ meta: ConfigSchemaMetaSchema.optional()
261
+ }).loose(),
262
+ z.object({
263
+ type: z.literal("const"),
264
+ value: JsonValueSchema,
265
+ meta: ConfigSchemaMetaSchema.optional()
266
+ }).loose(),
267
+ z.object({
268
+ type: z.literal("union"),
269
+ list: z.array(ConfigSchemaNodeSchema).min(1).max(64),
270
+ meta: ConfigSchemaMetaSchema.optional()
271
+ }).loose(),
272
+ z.object({
273
+ type: z.literal("array"),
274
+ inner: ConfigSchemaNodeSchema,
275
+ meta: ConfigSchemaMetaSchema.optional()
276
+ }).loose()
277
+ ]));
278
+ /** A whole configuration document: always an object at the root. */
279
+ const ConfigSchemaDocumentSchema = ConfigSchemaNodeSchema.refine((node) => node.type === "object", "配置 Schema 的根节点必须是 object。").refine((node) => new TextEncoder().encode(JSON.stringify(node)).length <= CONFIG_SCHEMA_MAX_BYTES, { message: `配置 Schema 不能超过 ${CONFIG_SCHEMA_MAX_BYTES} 字节。` });
280
+ const EMPTY_CONFIG_SCHEMA = {
281
+ type: "object",
282
+ dict: {}
283
+ };
284
+ const configDescription = (meta) => {
285
+ const description = meta?.description;
286
+ if (typeof description === "string") return description;
287
+ if (description) return description["zh-CN"] ?? description["zh"] ?? Object.values(description)[0];
288
+ };
289
+ const isEnumUnion = (node) => node.type === "union" && node.list.every((option) => option.type === "const");
290
+ const configFieldKind = (node) => {
291
+ if (node.meta?.role === "secret") return "secret";
292
+ if (node.type === "string") return "string";
293
+ if (node.type === "number" || node.type === "natural" || node.type === "percent") return "number";
294
+ if (node.type === "boolean") return "boolean";
295
+ if (node.type === "array") return "array";
296
+ if (node.type === "object") return "object";
297
+ if (node.type === "const" || isEnumUnion(node)) return "enum";
298
+ throw new TypeError("配置 Schema 只支持常量组成的 union。");
299
+ };
300
+ /** Flattens the top level of a document into product form fields (order preserved). */
301
+ const jsonLabel = (value) => typeof value === "string" ? value : JSON.stringify(value);
302
+ const configFields = (document) => Object.entries(document.dict).map(([key, node]) => {
303
+ const kind = configFieldKind(node);
304
+ const title = configDescription(node.meta) ?? key;
305
+ const options = node.type === "union" && isEnumUnion(node) ? node.list.map((option) => ({
306
+ value: option.type === "const" ? option.value : null,
307
+ label: configDescription(option.meta) ?? (option.type === "const" ? jsonLabel(option.value) : "")
308
+ })) : node.type === "const" ? [{
309
+ value: node.value,
310
+ label: configDescription(node.meta) ?? jsonLabel(node.value)
311
+ }] : void 0;
312
+ return {
313
+ key,
314
+ kind,
315
+ title,
316
+ ...node.meta?.hint === void 0 ? {} : { hint: node.meta.hint },
317
+ required: node.meta?.required === true,
318
+ ...node.meta?.default === void 0 ? {} : { default: node.meta.default },
319
+ advanced: node.meta?.advanced === true,
320
+ ...node.meta?.group === void 0 ? {} : { group: node.meta.group },
321
+ ...options === void 0 ? {} : { options },
322
+ node
323
+ };
324
+ });
325
+ const configSecretKeys = (document) => configFields(document).filter((field) => field.kind === "secret").map((field) => field.key);
326
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
327
+ const sameJson = (left, right) => JSON.stringify(left) === JSON.stringify(right);
328
+ const validateNode = (node, value, path, label, issues) => {
329
+ const resolved = value ?? node.meta?.default;
330
+ if (resolved === void 0 || resolved === null) {
331
+ if (node.meta?.required === true) issues.push({
332
+ path,
333
+ message: `请填写${label}。`
334
+ });
335
+ if (node.type === "object") return validateNode(node, {}, path, label, issues);
336
+ return;
337
+ }
338
+ switch (node.type) {
339
+ case "object": {
340
+ if (!isRecord(resolved)) {
341
+ issues.push({
342
+ path,
343
+ message: `${label}必须是对象。`
344
+ });
345
+ return;
346
+ }
347
+ const output = {};
348
+ for (const key of Object.keys(resolved)) if (!Object.hasOwn(node.dict, key)) issues.push({
349
+ path: path ? `${path}.${key}` : key,
350
+ message: `未知配置项:${key}`
351
+ });
352
+ for (const [key, child] of Object.entries(node.dict)) {
353
+ const childPath = path ? `${path}.${key}` : key;
354
+ const next = validateNode(child, resolved[key], childPath, configDescription(child.meta) ?? key, issues);
355
+ if (next !== void 0) output[key] = next;
356
+ }
357
+ return output;
358
+ }
359
+ case "string": {
360
+ if (typeof resolved !== "string") {
361
+ issues.push({
362
+ path,
363
+ message: `${label}必须是文本。`
364
+ });
365
+ return;
366
+ }
367
+ if (node.meta?.required === true && resolved.trim().length === 0) issues.push({
368
+ path,
369
+ message: `请填写${label}。`
370
+ });
371
+ const pattern = node.meta?.pattern;
372
+ if (pattern && resolved.length > 0 && !new RegExp(pattern.source, pattern.flags ?? "").test(resolved)) issues.push({
373
+ path,
374
+ message: `${label}的格式不正确。`
375
+ });
376
+ return resolved;
377
+ }
378
+ case "number":
379
+ case "natural":
380
+ case "percent":
381
+ if (typeof resolved !== "number" || !Number.isFinite(resolved)) {
382
+ issues.push({
383
+ path,
384
+ message: `${label}必须是数字。`
385
+ });
386
+ return;
387
+ }
388
+ if (node.type === "natural" && (!Number.isInteger(resolved) || resolved < 0)) issues.push({
389
+ path,
390
+ message: `${label}必须是非负整数。`
391
+ });
392
+ if (node.type === "percent" && (resolved < 0 || resolved > 1)) issues.push({
393
+ path,
394
+ message: `${label}必须在 0 到 1 之间。`
395
+ });
396
+ if (node.meta?.min !== void 0 && resolved < node.meta.min) issues.push({
397
+ path,
398
+ message: `${label}不能小于 ${node.meta.min}。`
399
+ });
400
+ if (node.meta?.max !== void 0 && resolved > node.meta.max) issues.push({
401
+ path,
402
+ message: `${label}不能大于 ${node.meta.max}。`
403
+ });
404
+ return resolved;
405
+ case "boolean":
406
+ if (typeof resolved !== "boolean") {
407
+ issues.push({
408
+ path,
409
+ message: `${label}必须是开关值。`
410
+ });
411
+ return;
412
+ }
413
+ return resolved;
414
+ case "const":
415
+ if (!sameJson(resolved, node.value)) issues.push({
416
+ path,
417
+ message: `${label}的取值无效。`
418
+ });
419
+ return resolved;
420
+ case "union":
421
+ if (!node.list.some((option) => option.type === "const" && sameJson(option.value, resolved))) issues.push({
422
+ path,
423
+ message: `${label}的取值无效。`
424
+ });
425
+ return resolved;
426
+ case "array":
427
+ if (!Array.isArray(resolved)) {
428
+ issues.push({
429
+ path,
430
+ message: `${label}必须是列表。`
431
+ });
432
+ return;
433
+ }
434
+ return resolved.flatMap((item, index) => {
435
+ const next = validateNode(node.inner, item, `${path}[${index}]`, `${label}第 ${index + 1} 项`, issues);
436
+ return next === void 0 ? [] : [next];
437
+ });
438
+ }
439
+ };
440
+ /**
441
+ * Validates a configuration value against a document and fills declared defaults. Secret fields are not part of the
442
+ * stored value; callers pass them through the credential store instead.
443
+ */
444
+ const validateConfigValue = (document, value, options = {}) => {
445
+ const skip = new Set(options.skipKeys ?? []);
446
+ const issues = [];
447
+ const input = isRecord(value) ? value : value === void 0 || value === null ? {} : void 0;
448
+ if (input === void 0) return {
449
+ value: {},
450
+ issues: [{
451
+ path: "",
452
+ message: "配置必须是对象。"
453
+ }]
454
+ };
455
+ const filtered = {
456
+ ...document,
457
+ dict: Object.fromEntries(Object.entries(document.dict).filter(([key]) => !skip.has(key)))
458
+ };
459
+ const output = validateNode(filtered, input, "", "配置", issues);
460
+ return {
461
+ value: isRecord(output) ? output : {},
462
+ issues
463
+ };
464
+ };
465
+ /** Throws the first validation issue as a user-readable error. */
466
+ const parseConfigValue = (document, value, options = {}) => {
467
+ const result = validateConfigValue(document, value, options);
468
+ const first = result.issues[0];
469
+ if (first) throw new TypeError(first.message);
470
+ return result.value;
471
+ };
472
+ const fieldMeta = (title, options = {}) => ({
473
+ description: title,
474
+ ...options.hint === void 0 ? {} : { hint: options.hint },
475
+ ...options.default === void 0 ? {} : { default: options.default },
476
+ ...options.required === void 0 ? {} : { required: options.required },
477
+ ...options.advanced === void 0 ? {} : { advanced: options.advanced },
478
+ ...options.group === void 0 ? {} : { group: options.group }
479
+ });
480
+ /** Builds serialized Schemastery documents without depending on the Schemastery runtime. */
481
+ const configSchema = {
482
+ object: (dict) => ({
483
+ type: "object",
484
+ dict
485
+ }),
486
+ string: (title, options = {}) => ({
487
+ type: "string",
488
+ meta: {
489
+ ...fieldMeta(title, options),
490
+ ...options.multiline ? { role: "textarea" } : {}
491
+ }
492
+ }),
493
+ secret: (title, options = {}) => ({
494
+ type: "string",
495
+ meta: {
496
+ ...fieldMeta(title, options),
497
+ role: "secret"
498
+ }
499
+ }),
500
+ number: (title, options = {}) => ({
501
+ type: options.integer ? "natural" : "number",
502
+ meta: {
503
+ ...fieldMeta(title, options),
504
+ ...options.min === void 0 ? {} : { min: options.min },
505
+ ...options.max === void 0 ? {} : { max: options.max }
506
+ }
507
+ }),
508
+ boolean: (title, options = {}) => ({
509
+ type: "boolean",
510
+ meta: fieldMeta(title, options)
511
+ }),
512
+ enum: (title, choices, options = {}) => ({
513
+ type: "union",
514
+ list: choices.map((choice) => ({
515
+ type: "const",
516
+ value: choice.value,
517
+ meta: { description: choice.label }
518
+ })),
519
+ meta: fieldMeta(title, options)
520
+ })
521
+ };
522
+ //#endregion
523
+ //#region src/extension-capabilities.ts
524
+ /**
525
+ * Host capability level this build implements. A Revision that declares `requires.sdk` above it is rejected at
526
+ * import with an "upgrade NekroNXT" message instead of an opaque schema error. Bump only when a new optional
527
+ * Manifest capability ships; never reuse a level for a different meaning.
528
+ */
529
+ const EXTENSION_SDK_LEVEL = 6;
530
+ const ExtensionRequiresSchema = z.object({ sdk: z.number().int().min(1).max(1e3) }).strict();
531
+ /** `api.example.com` or `*.example.com` (subdomains only); lower-case DNS labels, no scheme, port or path. */
532
+ const ExtensionNetworkDomainSchema = z.string().trim().toLowerCase().max(253).regex(/^(\*\.)?(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/u, { message: "网络域名必须是 api.example.com 或 *.example.com 形式,不含协议、端口和路径。" });
533
+ const ExtensionNetworkCapabilitySchema = z.discriminatedUnion("mode", [
534
+ z.object({
535
+ mode: z.literal("domains"),
536
+ domains: z.array(ExtensionNetworkDomainSchema).min(1).max(32)
537
+ }).strict(),
538
+ z.object({
539
+ mode: z.literal("config"),
540
+ /** Top-level config fields whose current value is a URL or host the user typed. */
541
+ fields: z.array(z.string().trim().min(1).max(64)).min(1).max(8)
542
+ }).strict(),
543
+ z.object({
544
+ mode: z.literal("unrestricted"),
545
+ /** Shown to the user next to the risk acknowledgement. */
546
+ purpose: z.string().trim().min(4).max(200)
547
+ }).strict()
548
+ ]);
549
+ const EXTENSION_STORAGE_SCOPES = [
550
+ "agent",
551
+ "channel",
552
+ "member",
553
+ "shared"
554
+ ];
555
+ const ExtensionStorageScopeSchema = z.enum(EXTENSION_STORAGE_SCOPES);
556
+ const EXTENSION_STORAGE_DEFAULT_QUOTA_BYTES = 8 * 1024 * 1024;
557
+ const EXTENSION_STORAGE_MAX_QUOTA_BYTES = 64 * 1024 * 1024;
558
+ const ExtensionStorageCapabilitySchema = z.object({
559
+ scopes: z.array(ExtensionStorageScopeSchema).min(1).max(EXTENSION_STORAGE_SCOPES.length),
560
+ quotaBytes: z.number().int().min(1024).max(EXTENSION_STORAGE_MAX_QUOTA_BYTES).optional()
561
+ }).strict().refine((value) => new Set(value.scopes).size === value.scopes.length, "存储作用域不能重复。");
562
+ const EXTENSION_CONTEXT_STATIC_MAX_CHARS = 4e3;
563
+ const EXTENSION_CONTEXT_DYNAMIC_MAX_CHARS = 2e3;
564
+ const ExtensionContextContributionSchema = z.object({
565
+ name: z.string().trim().regex(/^[a-z0-9][a-z0-9-]{0,39}$/u, "上下文名称只能使用小写字母、数字和连字符。"),
566
+ kind: z.enum(["static", "dynamic"]),
567
+ maxChars: z.number().int().min(1).max(EXTENSION_CONTEXT_STATIC_MAX_CHARS)
568
+ }).strict().refine((value) => value.kind === "static" || value.maxChars <= 2e3, `动态上下文最多 ${EXTENSION_CONTEXT_DYNAMIC_MAX_CHARS} 字。`);
569
+ const EXTENSION_LLM_MAX_CALLS_PER_TURN = 20;
570
+ const EXTENSION_LLM_MAX_OUTPUT_TOKENS = 8192;
571
+ const ExtensionLlmCapabilitySchema = z.object({
572
+ maxCallsPerTurn: z.number().int().min(1).max(20),
573
+ maxOutputTokens: z.number().int().min(64).max(EXTENSION_LLM_MAX_OUTPUT_TOKENS)
574
+ }).strict();
575
+ const EXTENSION_INBOUND_HOOK_MAX_TIMEOUT_MS = 15e3;
576
+ const ExtensionInboundHookCapabilitySchema = z.object({
577
+ /** `triggered`: only messages that would wake the agent anyway; `all`: every message in bound channels. */
578
+ reads: z.enum(["triggered", "all"]),
579
+ mayHide: z.boolean(),
580
+ mayForceTrigger: z.boolean(),
581
+ timeoutMs: z.number().int().min(100).max(EXTENSION_INBOUND_HOOK_MAX_TIMEOUT_MS)
582
+ }).strict();
583
+ const EXTENSION_JOB_MAX_RUNTIME = 50;
584
+ const ExtensionDeclaredJobSchema = z.object({
585
+ id: z.string().trim().regex(/^[a-z0-9][a-z0-9-]{0,39}$/u, "定时任务 id 只能使用小写字母、数字和连字符。"),
586
+ label: z.string().trim().min(1).max(200),
587
+ cron: z.string().trim().min(9).max(120),
588
+ timezone: z.string().trim().min(1).max(64).optional()
589
+ }).strict();
590
+ const ExtensionJobsCapabilitySchema = z.object({
591
+ /** Fixed schedules; each fires in every channel bound to the agent that enables the extension. */
592
+ declared: z.array(ExtensionDeclaredJobSchema).max(8).refine((jobs) => new Set(jobs.map(({ id }) => id)).size === jobs.length, "定时任务 id 不能重复。").optional(),
593
+ /** Jobs the extension creates at runtime (`ctx.nxt.jobs.schedule`), at most this many active per agent. */
594
+ runtime: z.object({ maxActive: z.number().int().min(1).max(50) }).strict().optional()
595
+ }).strict();
596
+ const AdapterKeySchema = z.string().trim().min(1).max(64);
597
+ const ExtensionPlatformCapabilitySchema = z.object({
598
+ /** Typed actions an Adapter declares, as `{ adapter, action }`. */
599
+ actions: z.array(z.object({
600
+ adapter: AdapterKeySchema,
601
+ action: z.string().regex(/^[a-z0-9_]{1,64}$/u)
602
+ }).strict()).max(32).default([]),
603
+ /** Adapters whose raw API passthrough the extension may call. */
604
+ raw: z.array(AdapterKeySchema).max(8).default([])
605
+ }).strict();
606
+ /** A header or environment value: literal text, or the current value of a `meta.role: 'secret'` config field. */
607
+ const ExtensionMcpValueSchema = z.union([z.string().max(4096), z.object({ secret: z.string().trim().min(1).max(64) }).strict()]);
608
+ /** Becomes the model-facing tool prefix `mcp__<name>__`. */
609
+ const ExtensionMcpServerNameSchema = z.string().regex(/^[A-Za-z0-9_-]{1,32}$/u);
610
+ const McpValueMapSchema = z.record(z.string().regex(/^[A-Za-z_][A-Za-z0-9_-]{0,127}$/u), ExtensionMcpValueSchema).refine((value) => Object.keys(value).length <= 32, "最多 32 项。").default({});
611
+ const ExtensionMcpServerSchema = z.discriminatedUnion("transport", [z.object({
612
+ transport: z.literal("streamable-http"),
613
+ name: ExtensionMcpServerNameSchema,
614
+ url: z.string().url().refine((value) => /^https?:\/\//iu.test(value), "MCP 地址必须是 http 或 https。"),
615
+ headers: McpValueMapSchema
616
+ }).strict(), z.object({
617
+ transport: z.literal("stdio"),
618
+ name: ExtensionMcpServerNameSchema,
619
+ command: z.string().trim().min(1).max(512),
620
+ args: z.array(z.string().max(4096)).max(64).default([]),
621
+ env: McpValueMapSchema
622
+ }).strict()]);
623
+ /**
624
+ * MCP servers the Host connects for the agent while the extension is enabled; their tools appear as
625
+ * `mcp__<name>__<tool>`. `stdio` runs a program on the Host and is only created from the administrator's form.
626
+ */
627
+ const ExtensionMcpCapabilitySchema = z.object({ servers: z.array(ExtensionMcpServerSchema).min(1).max(8).refine((value) => new Set(value.map(({ name }) => name)).size === value.length, "MCP 服务名称不能重复。") }).strict();
628
+ /** One header or environment row of the administrator's form; secret rows become credential config fields. */
629
+ const McpFormValueSchema = z.object({
630
+ name: z.string().regex(/^[A-Za-z_][A-Za-z0-9_-]{0,127}$/u, "名称只能包含字母、数字、下划线和连字符。"),
631
+ value: z.string().max(4096),
632
+ secret: z.boolean().default(false)
633
+ }).strict();
634
+ const McpServerFormSchema = z.discriminatedUnion("transport", [z.object({
635
+ transport: z.literal("streamable-http"),
636
+ name: ExtensionMcpServerNameSchema,
637
+ url: z.string().url(),
638
+ headers: z.array(McpFormValueSchema).max(32).default([])
639
+ }).strict(), z.object({
640
+ transport: z.literal("stdio"),
641
+ name: ExtensionMcpServerNameSchema,
642
+ command: z.string().trim().min(1).max(512),
643
+ args: z.array(z.string().max(4096)).max(64).default([]),
644
+ env: z.array(McpFormValueSchema).max(32).default([])
645
+ }).strict()]);
646
+ /** Secret config fields an MCP declaration reads. */
647
+ const mcpSecretFields = (mcp) => [...new Set((mcp?.servers ?? []).flatMap((server) => Object.values(server.transport === "stdio" ? server.env : server.headers).flatMap((value) => typeof value === "string" ? [] : [value.secret])))];
648
+ /** What a server connects to; changing it needs a new approval, unlike its credentials. */
649
+ const mcpTarget = (server) => server.transport === "stdio" ? JSON.stringify([
650
+ "stdio",
651
+ server.name,
652
+ server.command,
653
+ server.args
654
+ ]) : JSON.stringify([
655
+ "streamable-http",
656
+ server.name,
657
+ server.url
658
+ ]);
659
+ /**
660
+ * Optional Host capabilities of an agent-scope Revision. Every field is additive to Manifest V6: an absent field
661
+ * means the Revision cannot use that capability, exactly as before the field existed.
662
+ */
663
+ const ExtensionCapabilitiesSchema = z.object({
664
+ network: ExtensionNetworkCapabilitySchema.optional(),
665
+ storage: ExtensionStorageCapabilitySchema.optional(),
666
+ assets: z.object({ write: z.literal(true) }).strict().optional(),
667
+ history: z.object({ read: z.literal(true) }).strict().optional(),
668
+ inboundHook: ExtensionInboundHookCapabilitySchema.optional(),
669
+ jobs: ExtensionJobsCapabilitySchema.optional(),
670
+ platform: ExtensionPlatformCapabilitySchema.optional(),
671
+ llm: ExtensionLlmCapabilitySchema.optional(),
672
+ mcp: ExtensionMcpCapabilitySchema.optional(),
673
+ context: z.array(ExtensionContextContributionSchema).max(8).refine((value) => new Set(value.map(({ name }) => name)).size === value.length, "上下文名称不能重复。").optional()
674
+ }).strict();
675
+ const NETWORK_MODE_RANK = {
676
+ domains: 0,
677
+ config: 1,
678
+ unrestricted: 2
679
+ };
680
+ const networkExpands = (previous, next) => {
681
+ if (next === void 0) return false;
682
+ if (previous === void 0) return true;
683
+ if (NETWORK_MODE_RANK[next.mode] !== NETWORK_MODE_RANK[previous.mode]) return NETWORK_MODE_RANK[next.mode] > NETWORK_MODE_RANK[previous.mode];
684
+ if (next.mode === "domains" && previous.mode === "domains") return next.domains.some((domain) => !previous.domains.includes(domain));
685
+ if (next.mode === "config" && previous.mode === "config") return next.fields.some((field) => !previous.fields.includes(field));
686
+ return false;
687
+ };
688
+ /**
689
+ * Whether `next` asks for something an approval of `previous` did not cover. Narrowing never needs approval;
690
+ * storage quota is bounded by the Host maximum and is not an expansion. Context contributions are capped text
691
+ * shown in the trace, so adding one is not an expansion either.
692
+ */
693
+ const extensionCapabilitiesExpand = (previous, next) => {
694
+ if (next === void 0) return false;
695
+ if (networkExpands(previous?.network, next.network)) return true;
696
+ if (next.storage?.scopes.some((scope) => !(previous?.storage?.scopes ?? []).includes(scope))) return true;
697
+ if (next.assets !== void 0 && previous?.assets === void 0) return true;
698
+ if (next.history !== void 0 && previous?.history === void 0) return true;
699
+ const platformKey = ({ adapter, action }) => `${adapter}:${action}`;
700
+ const previousActions = new Set((previous?.platform?.actions ?? []).map(platformKey));
701
+ if ((next.platform?.actions ?? []).some((entry) => !previousActions.has(platformKey(entry)))) return true;
702
+ if ((next.platform?.raw ?? []).some((adapter) => !(previous?.platform?.raw ?? []).includes(adapter))) return true;
703
+ const hook = next.inboundHook;
704
+ const previousHook = previous?.inboundHook;
705
+ if (hook !== void 0 && (previousHook === void 0 || hook.reads === "all" && previousHook.reads === "triggered" || hook.mayHide && !previousHook.mayHide || hook.mayForceTrigger && !previousHook.mayForceTrigger)) return true;
706
+ if (next.jobs?.runtime !== void 0 && (previous?.jobs?.runtime === void 0 || next.jobs.runtime.maxActive > previous.jobs.runtime.maxActive)) return true;
707
+ const previousMcp = new Set((previous?.mcp?.servers ?? []).map(mcpTarget));
708
+ if ((next.mcp?.servers ?? []).some((server) => !previousMcp.has(mcpTarget(server)))) return true;
709
+ if (next.llm !== void 0 && (previous?.llm === void 0 || next.llm.maxCallsPerTurn > previous.llm.maxCallsPerTurn || next.llm.maxOutputTokens > previous.llm.maxOutputTokens)) return true;
710
+ return false;
711
+ };
712
+ /** User-facing summary of declared capabilities, in a stable order, for approval and inspection pages. */
713
+ const summarizeExtensionCapabilities = (capabilities) => {
714
+ if (capabilities === void 0) return [];
715
+ const items = [];
716
+ const network = capabilities.network;
717
+ if (network?.mode === "domains") items.push({
718
+ key: "network",
719
+ risk: "normal",
720
+ label: "访问指定网站",
721
+ detail: network.domains.join("、")
722
+ });
723
+ else if (network?.mode === "config") items.push({
724
+ key: "network",
725
+ risk: "normal",
726
+ label: "访问你在配置中填写的地址",
727
+ detail: network.fields.join("、")
728
+ });
729
+ else if (network?.mode === "unrestricted") items.push({
730
+ key: "network",
731
+ risk: "high",
732
+ label: "访问任意公网地址",
733
+ detail: network.purpose
734
+ });
735
+ if (capabilities.storage !== void 0) {
736
+ const shared = capabilities.storage.scopes.includes("shared");
737
+ items.push({
738
+ key: "storage",
739
+ risk: shared ? "sensitive" : "normal",
740
+ label: shared ? "保存数据,并在启用它的智能体之间共享" : "为这个智能体保存数据"
741
+ });
742
+ }
743
+ if (capabilities.assets !== void 0) items.push({
744
+ key: "assets",
745
+ risk: "normal",
746
+ label: "在当前频道生成图片或文件"
747
+ });
748
+ if (capabilities.history !== void 0) items.push({
749
+ key: "history",
750
+ risk: "normal",
751
+ label: "读取当前频道的聊天记录"
752
+ });
753
+ const hook = capabilities.inboundHook;
754
+ if (hook !== void 0) {
755
+ const effects = [hook.mayHide ? "对智能体隐藏消息" : "", hook.mayForceTrigger ? "让智能体回应原本不会回应的消息" : ""].filter((effect) => effect !== "").join("、");
756
+ items.push({
757
+ key: "inboundHook",
758
+ risk: hook.reads === "all" ? "high" : "sensitive",
759
+ label: hook.reads === "all" ? "查看频道里的全部消息" : "在智能体回应前查看要回应的消息",
760
+ ...effects === "" ? {} : { detail: `可以${effects}` }
761
+ });
762
+ }
763
+ const jobs = capabilities.jobs;
764
+ if (jobs?.declared !== void 0 && jobs.declared.length > 0) items.push({
765
+ key: "jobs.declared",
766
+ risk: "normal",
767
+ label: "按固定计划唤醒智能体",
768
+ detail: jobs.declared.map(({ label }) => label).join("、")
769
+ });
770
+ if (jobs?.runtime !== void 0) items.push({
771
+ key: "jobs.runtime",
772
+ risk: "sensitive",
773
+ label: "创建定时任务唤醒智能体",
774
+ detail: `同时最多 ${jobs.runtime.maxActive} 个`
775
+ });
776
+ const platform = capabilities.platform;
777
+ if (platform !== void 0 && platform.actions.length > 0) items.push({
778
+ key: "platform.actions",
779
+ risk: "high",
780
+ label: "在平台上执行操作",
781
+ detail: platform.actions.map(({ adapter, action }) => `${adapter} · ${action}`).join("、")
782
+ });
783
+ if (platform !== void 0 && platform.raw.length > 0) items.push({
784
+ key: "platform.raw",
785
+ risk: "high",
786
+ label: "直接调用平台原始接口",
787
+ detail: platform.raw.join("、")
788
+ });
789
+ if (capabilities.llm !== void 0) items.push({
790
+ key: "llm",
791
+ risk: "sensitive",
792
+ label: "使用这个智能体的模型",
793
+ detail: `每轮最多 ${capabilities.llm.maxCallsPerTurn} 次,计入智能体用量`
794
+ });
795
+ for (const server of capabilities.mcp?.servers ?? []) items.push(server.transport === "stdio" ? {
796
+ key: `mcp.${server.name}`,
797
+ risk: "high",
798
+ label: `在本机运行 MCP 程序 ${server.name}`,
799
+ detail: [server.command, ...server.args].join(" ")
800
+ } : {
801
+ key: `mcp.${server.name}`,
802
+ risk: "sensitive",
803
+ label: `连接 MCP 服务 ${server.name}`,
804
+ detail: new URL(server.url).host
805
+ });
806
+ if (capabilities.context !== void 0 && capabilities.context.length > 0) items.push({
807
+ key: "context",
808
+ risk: "normal",
809
+ label: "向智能体提供补充说明",
810
+ detail: capabilities.context.map(({ name }) => name).join("、")
811
+ });
812
+ return items;
813
+ };
814
+ //#endregion
815
+ //#region src/extension-ui.ts
816
+ const HostUiPermissionSchema = z.enum([
817
+ "agents.read",
818
+ "channels.read",
819
+ "connections.read",
820
+ "extensions.read",
821
+ "dsh-plugins.read",
822
+ "runtime.read",
823
+ "messages.read",
824
+ "assets.read",
825
+ "agents.manage",
826
+ "channels.manage",
827
+ "connections.manage",
828
+ "credentials.write",
829
+ "messages.send",
830
+ "notifications.publish",
831
+ "network.request"
832
+ ]);
833
+ const HOST_UI_KIT_COMPONENT_NAMES = [
834
+ "Button",
835
+ "IconButton",
836
+ "Input",
837
+ "Textarea",
838
+ "Select",
839
+ "Switch",
840
+ "Tabs",
841
+ "Dialog",
842
+ "Popover",
843
+ "Tooltip",
844
+ "Field",
845
+ "StatusBadge",
846
+ "InlineFeedback",
847
+ "EmptyState",
848
+ "Spinner",
849
+ "PageHeader",
850
+ "MetricStrip",
851
+ "Metric",
852
+ "Section",
853
+ "Stack",
854
+ "Grid",
855
+ "DataTable",
856
+ "PropertyList",
857
+ "PropertyRow"
858
+ ];
859
+ const HostUiKitComponentNameSchema = z.enum(HOST_UI_KIT_COMPONENT_NAMES);
860
+ const HostUiPageGeometryEvidenceSchema = z.object({
861
+ entryId: z.string().trim().regex(/^[a-z](?:[a-z0-9-]{0,62}[a-z0-9])?$/u),
862
+ objectPane: z.enum(["navigation", "hidden"]),
863
+ viewport: z.object({
864
+ width: z.number().finite().positive().max(16384),
865
+ height: z.number().finite().positive().max(16384)
866
+ }).strict(),
867
+ insets: z.object({
868
+ top: z.number().finite().nonnegative().max(512),
869
+ right: z.number().finite().nonnegative().max(512),
870
+ bottom: z.number().finite().nonnegative().max(512),
871
+ left: z.number().finite().nonnegative().max(512)
872
+ }).strict(),
873
+ contentAxesAligned: z.boolean(),
874
+ horizontalOverflow: z.boolean(),
875
+ titleDistinct: z.boolean()
876
+ }).strict();
877
+ const HostIconNameSchema = z.enum([
878
+ "app-window",
879
+ "bar-chart",
880
+ "book-open",
881
+ "boxes",
882
+ "database",
883
+ "file-text",
884
+ "folder",
885
+ "globe",
886
+ "layout-dashboard",
887
+ "puzzle",
888
+ "terminal",
889
+ "workflow",
890
+ "wrench"
891
+ ]);
892
+ const HostPageIconSchema = z.discriminatedUnion("kind", [z.object({
893
+ kind: z.literal("host-icon"),
894
+ name: HostIconNameSchema
895
+ }).strict(), z.object({
896
+ kind: z.literal("svg"),
897
+ path: z.string().trim().regex(/^assets\/[a-z0-9][a-z0-9/_-]*\.svg$/u),
898
+ sha256: z.string().regex(/^[a-f0-9]{64}$/u)
899
+ }).strict()]);
900
+ const HostPageContributionSchema = z.object({
901
+ kind: z.literal("host-page"),
902
+ entryId: z.string().trim().regex(/^[a-z](?:[a-z0-9-]{0,62}[a-z0-9])?$/u),
903
+ title: z.string().trim().min(1).max(40),
904
+ description: z.string().trim().max(120).optional(),
905
+ icon: HostPageIconSchema,
906
+ objectPane: z.enum(["navigation", "hidden"]),
907
+ startPath: z.string().trim().regex(/^(?:[a-z0-9][a-z0-9/_-]*)?$/u)
908
+ }).strict();
909
+ const HostUiNavigationItemSchema = z.object({
910
+ id: z.string().trim().min(1).max(80),
911
+ label: z.string().trim().min(1).max(80),
912
+ description: z.string().trim().max(120).optional(),
913
+ icon: HostPageIconSchema.optional(),
914
+ badge: z.string().trim().max(24).optional(),
915
+ status: z.enum([
916
+ "neutral",
917
+ "info",
918
+ "success",
919
+ "warning",
920
+ "error"
921
+ ]).optional(),
922
+ disabledReason: z.string().trim().max(160).optional(),
923
+ path: z.string().trim().regex(/^(?:[a-z0-9][a-z0-9/_-]*)?$/u)
924
+ }).strict();
925
+ const HostUiNavigationGroupSchema = z.object({
926
+ id: z.string().trim().min(1).max(80),
927
+ label: z.string().trim().max(80).optional(),
928
+ items: z.array(HostUiNavigationItemSchema).max(256)
929
+ }).strict();
930
+ const HostUiNavigationModelSchema = z.object({
931
+ revision: z.number().int().nonnegative(),
932
+ groups: z.array(HostUiNavigationGroupSchema).max(16)
933
+ }).strict().refine((model) => model.groups.reduce((total, group) => total + group.items.length, 0) <= 256, { message: "Host UI navigation cannot contain more than 256 items." });
934
+ const HostUiNetworkOriginSchema = z.string().url().transform((value, context) => {
935
+ const url = new URL(value);
936
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
937
+ context.addIssue({
938
+ code: "custom",
939
+ message: "Host UI network origins must use HTTP(S)."
940
+ });
941
+ return z.NEVER;
942
+ }
943
+ if (url.pathname !== "/" || url.search || url.hash || url.username || url.password) {
944
+ context.addIssue({
945
+ code: "custom",
946
+ message: "Host UI network origins cannot contain paths or credentials."
947
+ });
948
+ return z.NEVER;
949
+ }
950
+ return url.origin;
951
+ });
952
+ const HostUiPermissionDeclarationSchema = z.object({
953
+ permissions: z.array(HostUiPermissionSchema).max(HostUiPermissionSchema.options.length),
954
+ networkOrigins: z.array(HostUiNetworkOriginSchema).max(32).default([]),
955
+ /** Host capabilities of an agent-scope Revision; absent keeps the pre-capability digest unchanged. */
956
+ capabilities: ExtensionCapabilitiesSchema.optional()
957
+ }).strict().superRefine((value, context) => {
958
+ if (new Set(value.permissions).size !== value.permissions.length) context.addIssue({
959
+ code: "custom",
960
+ path: ["permissions"],
961
+ message: "Host UI permissions must be unique."
962
+ });
963
+ if (new Set(value.networkOrigins).size !== value.networkOrigins.length) context.addIssue({
964
+ code: "custom",
965
+ path: ["networkOrigins"],
966
+ message: "Host UI network origins must be unique."
967
+ });
968
+ if (value.networkOrigins.length > 0 && !value.permissions.includes("network.request")) context.addIssue({
969
+ code: "custom",
970
+ path: ["networkOrigins"],
971
+ message: "Host UI network origins require network.request."
972
+ });
973
+ });
974
+ const HostUiOwnerSchema = z.discriminatedUnion("kind", [z.object({
975
+ kind: z.literal("extension"),
976
+ extensionId: ExtensionIdSchema,
977
+ revisionId: ExtensionRevisionIdSchema
978
+ }).strict(), z.object({
979
+ kind: z.literal("dsh-plugin"),
980
+ entryId: z.string().trim().min(1),
981
+ artifactDigest: z.string().regex(/^[a-f0-9]{64}$/u)
982
+ }).strict()]);
983
+ const HostUiPageEntrySchema = z.object({
984
+ pageInstanceId: HostUiPageInstanceIdSchema,
985
+ owner: HostUiOwnerSchema,
986
+ entryId: z.string().trim().min(1).max(64),
987
+ title: z.string().trim().min(1).max(40),
988
+ description: z.string().trim().max(120).optional(),
989
+ icon: HostPageIconSchema,
990
+ objectPane: z.enum(["navigation", "hidden"]),
991
+ startPath: z.string(),
992
+ visible: z.boolean(),
993
+ sortOrder: z.number().int().nonnegative(),
994
+ routeBase: z.string().regex(/^\/apps\/hup_[0-9A-Za-z]+$/u),
995
+ client: z.object({
996
+ moduleUrl: z.string().startsWith("/"),
997
+ buildKey: z.string().regex(/^[a-f0-9]{64}$/u)
998
+ }).strict(),
999
+ diagnostic: z.object({
1000
+ status: z.enum([
1001
+ "ready",
1002
+ "load-failed",
1003
+ "navigation-failed",
1004
+ "rpc-failed",
1005
+ "restore-failed"
1006
+ ]),
1007
+ message: z.string().optional(),
1008
+ observedAt: z.number().int().safe().nonnegative()
1009
+ }).strict().optional(),
1010
+ createdAt: z.number().int().safe().nonnegative(),
1011
+ updatedAt: z.number().int().safe().nonnegative()
1012
+ }).strict();
1013
+ const HostUiPagePreferencesSchema = z.object({
1014
+ revision: z.number().int().nonnegative(),
1015
+ entries: z.array(z.object({
1016
+ pageInstanceId: HostUiPageInstanceIdSchema,
1017
+ visible: z.boolean()
1018
+ }).strict())
1019
+ }).strict();
1020
+ const DshNxtHostUiSchema = z.object({
1021
+ schemaVersion: z.literal(1),
1022
+ entryKey: z.string().trim().min(1).max(120),
1023
+ client: z.string().trim().regex(/^(?!\/)(?!.*(?:^|\/)\.\.(?:\/|$))[a-zA-Z0-9._/-]+\.m?js$/u),
1024
+ css: z.string().trim().regex(/^(?!\/)(?!.*(?:^|\/)\.\.(?:\/|$))[a-zA-Z0-9._/-]+\.css$/u).optional(),
1025
+ pages: z.array(HostPageContributionSchema).min(1).max(8),
1026
+ permissions: HostUiPermissionDeclarationSchema.default({
1027
+ permissions: [],
1028
+ networkOrigins: []
1029
+ })
1030
+ }).strict();
1031
+ /** Where the product shell may place an extension panel. The Host decides the concrete page and position. */
1032
+ const ExtensionPanelAnchorSchema = z.enum([
1033
+ "agent",
1034
+ "channel",
1035
+ "extension",
1036
+ "connection"
1037
+ ]);
1038
+ const AGENT_PANEL_ANCHORS = [
1039
+ "agent",
1040
+ "channel",
1041
+ "extension"
1042
+ ];
1043
+ const ADAPTER_PANEL_ANCHORS = ["connection", "channel"];
1044
+ const PanelDensitySchema = z.enum(["compact", "full"]);
1045
+ const ConnectionPanelRoleSchema = z.enum([
1046
+ "setup",
1047
+ "status",
1048
+ "diagnostics"
1049
+ ]);
1050
+ const ToolViewDensitySchema = z.enum(["chip", "card"]);
1051
+ const panelFields = {
1052
+ id: z.string().trim().regex(/^[a-z](?:[a-z0-9-]{0,62}[a-z0-9])?$/u),
1053
+ anchor: ExtensionPanelAnchorSchema,
1054
+ title: z.string().trim().min(1).max(24),
1055
+ icon: HostIconNameSchema.optional(),
1056
+ densities: z.array(PanelDensitySchema).min(1).max(2),
1057
+ role: ConnectionPanelRoleSchema.optional(),
1058
+ when: z.object({ channelKinds: z.array(z.enum([
1059
+ "internal",
1060
+ "direct",
1061
+ "group"
1062
+ ])).min(1).max(3).optional() }).strict().optional()
1063
+ };
1064
+ const checkPanel = (value, context) => {
1065
+ if (new Set(value.densities).size !== value.densities.length) context.addIssue({
1066
+ code: "custom",
1067
+ path: ["densities"],
1068
+ message: "面板密度不能重复。"
1069
+ });
1070
+ if (value.anchor === "connection" && value.role === void 0) context.addIssue({
1071
+ code: "custom",
1072
+ path: ["role"],
1073
+ message: "连接面板必须声明 setup、status 或 diagnostics 角色。"
1074
+ });
1075
+ if (value.anchor !== "connection" && value.role !== void 0) context.addIssue({
1076
+ code: "custom",
1077
+ path: ["role"],
1078
+ message: "只有连接面板可以声明角色。"
1079
+ });
1080
+ if (value.when?.channelKinds !== void 0 && value.anchor !== "channel") context.addIssue({
1081
+ code: "custom",
1082
+ path: ["when"],
1083
+ message: "只有频道面板可以按频道类型限定。"
1084
+ });
1085
+ if (value.when?.channelKinds !== void 0 && new Set(value.when.channelKinds).size !== value.when.channelKinds.length) context.addIssue({
1086
+ code: "custom",
1087
+ path: ["when", "channelKinds"],
1088
+ message: "频道类型不能重复。"
1089
+ });
1090
+ };
1091
+ /** Client-side registration options for one panel; identical to the Manifest contribution without `kind`. */
1092
+ const ExtensionPanelDeclarationSchema = z.object(panelFields).strict().superRefine(checkPanel);
1093
+ const PanelContributionSchema = z.object({
1094
+ kind: z.literal("panel"),
1095
+ ...panelFields
1096
+ }).strict().superRefine(checkPanel);
1097
+ const ToolViewContributionSchema = z.object({
1098
+ kind: z.literal("tool-view"),
1099
+ tool: z.string().trim().min(1).max(64)
1100
+ }).strict();
1101
+ const RichKindSchema = z.string().trim().regex(/^[a-z0-9][a-z0-9._-]{0,62}$/u);
1102
+ const MessageRendererContributionSchema = z.object({
1103
+ kind: z.literal("message-renderer"),
1104
+ richKind: RichKindSchema
1105
+ }).strict();
1106
+ /** Optional configuration surface shared by every extension scope. */
1107
+ const ExtensionConfigDeclarationSchema = z.object({ schema: ConfigSchemaDocumentSchema }).strict();
1108
+ /** Product projection of what one Revision contributes to the shell. */
1109
+ const ExtensionUiContributionsSchema = z.object({
1110
+ panels: z.array(PanelContributionSchema).max(16),
1111
+ toolViews: z.array(z.string().trim().min(1).max(64)).max(32),
1112
+ messageRenderers: z.array(RichKindSchema).max(32)
1113
+ }).strict();
1114
+ const EMPTY_EXTENSION_UI_CONTRIBUTIONS = {
1115
+ panels: [],
1116
+ toolViews: [],
1117
+ messageRenderers: []
1118
+ };
1119
+ /** Read permission each Client data hook requires; the host enforces it in every runtime that renders a Client. */
1120
+ const EXTENSION_DATA_HOOK_PERMISSIONS = {
1121
+ useAgent: "agents.read",
1122
+ useChannel: "channels.read",
1123
+ useConnection: "connections.read",
1124
+ useChannelRuntime: "runtime.read"
1125
+ };
1126
+ //#endregion
1127
+ //#region src/runtime-compatibility.ts
1128
+ const RuntimeCompatibilityDiagnosticSchema = z.object({
1129
+ objectKind: z.enum([
1130
+ "agent",
1131
+ "model-provider",
1132
+ "extension",
1133
+ "dsh-plugin",
1134
+ "adapter",
1135
+ "client-page"
1136
+ ]),
1137
+ objectId: z.string().min(1),
1138
+ objectVersion: z.string().min(1),
1139
+ configurationRevision: z.string(),
1140
+ runtimeFingerprint: z.string().min(1),
1141
+ status: z.enum([
1142
+ "checking",
1143
+ "compatible",
1144
+ "isolated"
1145
+ ]),
1146
+ phase: z.enum([
1147
+ "configuration",
1148
+ "dependency",
1149
+ "build",
1150
+ "load",
1151
+ "render",
1152
+ "restore",
1153
+ "dispose"
1154
+ ]),
1155
+ reason: z.string().max(2048).optional(),
1156
+ retryable: z.boolean(),
1157
+ checkedAt: z.number().int().nonnegative()
1158
+ }).strict();
1159
+ const HostUpgradeSummarySchema = z.object({
1160
+ runtimeVersion: z.string().min(1),
1161
+ sessionCompatibilityId: z.string().min(1),
1162
+ backupId: z.string().optional(),
1163
+ resetContexts: z.boolean(),
1164
+ diagnostics: z.array(RuntimeCompatibilityDiagnosticSchema)
1165
+ }).strict();
1166
+ //#endregion
1167
+ //#region src/management-api.ts
1168
+ const NonEmptyStringSchema$1 = z.string().trim().min(1);
1169
+ const Base64UrlSchema = z.string().regex(/^[A-Za-z0-9_-]+$/u);
1170
+ const ServerInstanceIdSchema = z.string().regex(/^nxt_instance_[0-9A-HJKMNP-TV-Z]{26}$/u).brand();
1171
+ const ManagementDeviceIdSchema = z.string().regex(/^nxt_device_[0-9A-HJKMNP-TV-Z]{26}$/u).brand();
1172
+ const InstanceDescriptorWireSchema = z.object({
1173
+ format: z.literal("nxt.instance-descriptor"),
1174
+ descriptorVersion: z.number().int().positive(),
1175
+ instanceId: ServerInstanceIdSchema,
1176
+ releaseId: NonEmptyStringSchema$1.max(256),
1177
+ productVersion: NonEmptyStringSchema$1.max(64),
1178
+ managementProtocol: z.number().int().positive(),
1179
+ desktopChromeProtocol: z.number().int().positive(),
1180
+ transport: NonEmptyStringSchema$1.max(80)
1181
+ }).passthrough();
1182
+ const InstanceDescriptorSchema = z.object({
1183
+ format: z.literal("nxt.instance-descriptor"),
1184
+ descriptorVersion: z.literal(1),
1185
+ instanceId: ServerInstanceIdSchema,
1186
+ releaseId: NonEmptyStringSchema$1.max(256),
1187
+ productVersion: NonEmptyStringSchema$1.max(64),
1188
+ managementProtocol: z.union([z.literal(1), z.literal(2)]),
1189
+ desktopChromeProtocol: z.literal(1),
1190
+ transport: z.enum([
1191
+ "loopback-http",
1192
+ "auto-tls-pinned-v1",
1193
+ "explicit-http-v1"
1194
+ ])
1195
+ }).strict().superRefine((value, context) => {
1196
+ if (!(value.managementProtocol === 1 && (value.transport === "loopback-http" || value.transport === "auto-tls-pinned-v1") || value.managementProtocol === 2 && value.transport === "explicit-http-v1")) context.addIssue({
1197
+ code: "custom",
1198
+ message: "management protocol 与 transport 不匹配。"
1199
+ });
1200
+ });
1201
+ const ManagementChallengeResponseSchema = z.object({
1202
+ challengeId: Base64UrlSchema,
1203
+ serverNonce: Base64UrlSchema,
1204
+ instanceId: ServerInstanceIdSchema,
1205
+ spkiSha256: Base64UrlSchema,
1206
+ expiresAt: z.number().int().positive()
1207
+ }).strict();
1208
+ const InsecureHttpManagementChallengeResponseSchema = z.object({
1209
+ challengeId: Base64UrlSchema,
1210
+ serverNonce: Base64UrlSchema,
1211
+ instanceId: ServerInstanceIdSchema,
1212
+ transportBinding: Base64UrlSchema,
1213
+ expiresAt: z.number().int().positive()
1214
+ }).strict();
1215
+ const ManagementDeviceEnrollmentRequestSchema = z.object({
1216
+ challengeId: Base64UrlSchema,
1217
+ clientNonce: Base64UrlSchema,
1218
+ proof: Base64UrlSchema,
1219
+ label: z.string().trim().min(1).max(80),
1220
+ clientReleaseId: NonEmptyStringSchema$1.max(256)
1221
+ }).strict();
1222
+ const ManagementDeviceEnrollmentResponseSchema = z.object({
1223
+ deviceId: ManagementDeviceIdSchema,
1224
+ deviceSecret: Base64UrlSchema
1225
+ }).strict();
1226
+ const ManagementSessionRequestSchema = z.object({
1227
+ deviceId: ManagementDeviceIdSchema,
1228
+ deviceSecret: Base64UrlSchema
1229
+ }).strict();
1230
+ const ManagementSessionResponseSchema = z.object({
1231
+ authenticated: z.literal(true),
1232
+ deviceId: ManagementDeviceIdSchema,
1233
+ csrfToken: Base64UrlSchema
1234
+ }).strict();
1235
+ const ManagementDeviceViewSchema = z.object({
1236
+ id: ManagementDeviceIdSchema,
1237
+ label: z.string().trim().min(1).max(80),
1238
+ createdAt: z.number().int().nonnegative(),
1239
+ lastUsedAt: z.number().int().nonnegative().optional(),
1240
+ revokedAt: z.number().int().nonnegative().optional(),
1241
+ /** The device this request is signed in with. */
1242
+ current: z.boolean().optional()
1243
+ }).strict();
1244
+ const ClientNotificationSchema = z.object({
1245
+ id: z.string().trim().min(1).max(160),
1246
+ kind: z.enum(["action-required"]),
1247
+ title: z.string().trim().min(1).max(80),
1248
+ body: z.string().trim().min(1).max(240),
1249
+ occurredAt: z.number().int().nonnegative(),
1250
+ route: z.string().regex(/^\/(?:(?:live|channels|agents|workshop|wiring|settings|apps|work|connections|users|extensions)(?:\/[^?#]*)?)?$/u).optional()
1251
+ }).strict();
1252
+ const MANAGEMENT_PAIR_PROOF_PREFIX = "nxt-management-pair-v1";
1253
+ const managementPairProofMessage = (input) => [
1254
+ MANAGEMENT_PAIR_PROOF_PREFIX,
1255
+ input.challengeId,
1256
+ input.serverNonce,
1257
+ input.clientNonce,
1258
+ input.instanceId,
1259
+ input.spkiSha256
1260
+ ].join("\n");
1261
+ const INSECURE_HTTP_MANAGEMENT_PAIR_PROOF_PREFIX = "nxt-management-pair-insecure-http-v1";
1262
+ const insecureHttpManagementPairProofMessage = (input) => [
1263
+ INSECURE_HTTP_MANAGEMENT_PAIR_PROOF_PREFIX,
1264
+ input.challengeId,
1265
+ input.serverNonce,
1266
+ input.clientNonce,
1267
+ input.instanceId,
1268
+ input.transportBinding
1269
+ ].join("\n");
1270
+ //#endregion
1271
+ //#region src/community.ts
1272
+ /**
1273
+ * NekroNXT 社区在本机的投影。Host 代理社区开放接口并把结果归一到这些结构;社区新增的字段在 Host 处丢弃,
1274
+ * 不直接透传给页面。审查状态与社区 `ReviewStatus` 一致。
1275
+ */
1276
+ const COMMUNITY_REVIEW_STATUSES = [
1277
+ "pending",
1278
+ "reviewing",
1279
+ "passed",
1280
+ "passed_with_notes",
1281
+ "flagged",
1282
+ "held",
1283
+ "risk_confirmed",
1284
+ "rejected",
1285
+ "incomplete"
1286
+ ];
1287
+ const CommunityReviewStatusSchema = z.enum(COMMUNITY_REVIEW_STATUSES);
1288
+ const CommunityGradeSchema = z.enum([
1289
+ "A",
1290
+ "B",
1291
+ "C",
1292
+ "D"
1293
+ ]);
1294
+ const CommunityReleaseIdSchema = z.string().regex(/^rel_[0-9A-Za-z]+$/u);
1295
+ const CommunityAccountSchema = z.object({
1296
+ handle: z.string().min(1).max(80),
1297
+ displayName: z.string().max(200),
1298
+ avatarUrl: z.string().url().nullable()
1299
+ }).strict();
1300
+ const CommunityEnvironmentSchema = z.enum([
1301
+ "production",
1302
+ "staging",
1303
+ "development"
1304
+ ]);
1305
+ const CommunityStatusSchema = z.object({
1306
+ communityUrl: z.string().url(),
1307
+ /** 社区自我声明的环境;连不上或旧版社区时为 null。 */
1308
+ environment: CommunityEnvironmentSchema.nullable(),
1309
+ account: CommunityAccountSchema.nullable(),
1310
+ signedInAt: z.number().int().nullable(),
1311
+ /** 最近一次更新检查发现的可更新扩展数量(只读缓存,不发起网络请求)。 */
1312
+ updatesAvailable: z.number().int().nonnegative()
1313
+ }).strict();
1314
+ const CommunityPermissionItemSchema = z.object({
1315
+ key: z.string().max(120),
1316
+ level: z.enum([
1317
+ "normal",
1318
+ "elevated",
1319
+ "high"
1320
+ ]),
1321
+ label: z.string().max(200),
1322
+ detail: z.string().max(2e3).optional()
1323
+ }).strict();
1324
+ const CommunityReleaseSchema = z.object({
1325
+ id: CommunityReleaseIdSchema,
1326
+ reviewStatus: CommunityReviewStatusSchema,
1327
+ grade: CommunityGradeSchema.nullable(),
1328
+ permissions: z.array(CommunityPermissionItemSchema).max(64),
1329
+ packageSize: z.number().int().nonnegative(),
1330
+ requiresSdk: z.number().int().positive().nullable(),
1331
+ notes: z.string().max(2e3),
1332
+ createdAt: z.number().int()
1333
+ }).strict();
1334
+ /** 社区为官方扩展保留的发布者标识:官方扩展由多位官方成员维护,对外不显示个人账号。 */
1335
+ const COMMUNITY_OFFICIAL_HANDLE = "nekro-nxt";
1336
+ /** 发布者的展示文字:官方扩展显示「NekroNXT 官方」,其余显示 @账号。 */
1337
+ const communityPublisherLabel = (handle) => handle === "nekro-nxt" ? "NekroNXT 官方" : `@${handle}`;
1338
+ const CommunityExtensionSummarySchema = z.object({
1339
+ id: ExtensionIdSchema,
1340
+ scope: z.enum([
1341
+ "agent",
1342
+ "host-adapter",
1343
+ "host-ui"
1344
+ ]),
1345
+ displayName: z.string().max(200),
1346
+ summary: z.string().max(1e3),
1347
+ tags: z.array(z.string().max(40)).max(16),
1348
+ /** 由社区后台认定的官方扩展;此时发布者是社区保留的官方主页(`COMMUNITY_OFFICIAL_HANDLE`)。 */
1349
+ official: z.boolean(),
1350
+ publisher: CommunityAccountSchema,
1351
+ latest: CommunityReleaseSchema.nullable(),
1352
+ downloads: z.number().int().nonnegative(),
1353
+ updatedAt: z.number().int(),
1354
+ pageUrl: z.string().url()
1355
+ }).strict();
1356
+ const CommunityExtensionDetailSchema = CommunityExtensionSummarySchema.extend({
1357
+ description: z.string().max(2e4),
1358
+ sourceUrl: z.string().url().nullable(),
1359
+ review: z.object({
1360
+ status: CommunityReviewStatusSchema,
1361
+ grade: CommunityGradeSchema.nullable(),
1362
+ summary: z.string().max(2e3).nullable(),
1363
+ highlights: z.array(z.object({
1364
+ severity: z.string().max(20),
1365
+ title: z.string().max(200)
1366
+ }).strict()).max(16)
1367
+ }).strict().nullable()
1368
+ }).strict();
1369
+ const CommunityEndpointSchema = z.object({
1370
+ url: z.string().url(),
1371
+ source: z.enum([
1372
+ "setting",
1373
+ "environment",
1374
+ "default"
1375
+ ]),
1376
+ defaultUrl: z.string().url(),
1377
+ environmentUrl: z.string().url().nullable(),
1378
+ /** 当前地址是未加密的非本机地址。 */
1379
+ insecure: z.boolean()
1380
+ }).strict();
1381
+ const CommunitySourceSchema = z.object({
1382
+ kind: z.literal("community"),
1383
+ communityUrl: z.string().url(),
1384
+ releaseId: CommunityReleaseIdSchema,
1385
+ publisherHandle: z.string().min(1).max(80),
1386
+ installedAt: z.number().int().nonnegative()
1387
+ }).strict();
1388
+ const CommunityInstalledItemSchema = z.object({
1389
+ extensionId: ExtensionIdSchema,
1390
+ displayName: z.string(),
1391
+ revisionId: z.string(),
1392
+ source: CommunitySourceSchema,
1393
+ /** 来源与当前社区地址一致时才能检查更新。 */
1394
+ sameCommunity: z.boolean(),
1395
+ /** 社区仍有这个条目。 */
1396
+ found: z.boolean(),
1397
+ delisted: z.boolean(),
1398
+ delistedReason: z.string().nullable(),
1399
+ releaseWithdrawn: z.boolean(),
1400
+ latest: CommunityReleaseSchema.nullable(),
1401
+ updateAvailable: z.boolean(),
1402
+ addedPermissions: z.array(CommunityPermissionItemSchema)
1403
+ }).strict();
1404
+ const CommunityInstalledSchema = z.object({
1405
+ checkedAt: z.number().int().nullable(),
1406
+ items: z.array(CommunityInstalledItemSchema)
1407
+ }).strict();
1408
+ const CommunityMyExtensionSchema = CommunityExtensionSummarySchema.extend({
1409
+ releases: z.array(CommunityReleaseSchema.extend({ withdrawn: z.boolean() }).strict()),
1410
+ delisted: z.boolean(),
1411
+ delistedReason: z.string().nullable()
1412
+ }).strict();
1413
+ const COMMUNITY_REVIEW_DIMENSIONS = [
1414
+ "security",
1415
+ "transparency",
1416
+ "reliability",
1417
+ "context_cost",
1418
+ "usability",
1419
+ "maintainability",
1420
+ "compliance"
1421
+ ];
1422
+ const COMMUNITY_REVIEW_DIMENSION_LABELS = {
1423
+ security: "安全",
1424
+ transparency: "源码透明",
1425
+ reliability: "可靠性",
1426
+ context_cost: "上下文与成本",
1427
+ usability: "可用性",
1428
+ maintainability: "可维护性",
1429
+ compliance: "合规"
1430
+ };
1431
+ /** 作者看到的完整审查报告。 */
1432
+ const CommunityReviewReportSchema = z.object({
1433
+ releaseId: CommunityReleaseIdSchema,
1434
+ status: CommunityReviewStatusSchema,
1435
+ grade: CommunityGradeSchema.nullable(),
1436
+ deterministic: z.array(z.object({
1437
+ severity: z.enum([
1438
+ "info",
1439
+ "warning",
1440
+ "risk",
1441
+ "block"
1442
+ ]),
1443
+ title: z.string(),
1444
+ detail: z.string(),
1445
+ file: z.string().optional(),
1446
+ line: z.number().int().optional()
1447
+ }).strict()),
1448
+ ai: z.object({
1449
+ summary: z.string(),
1450
+ verdict: z.string(),
1451
+ grade: CommunityGradeSchema,
1452
+ dimensions: z.array(z.object({
1453
+ key: z.enum(COMMUNITY_REVIEW_DIMENSIONS),
1454
+ grade: CommunityGradeSchema,
1455
+ notes: z.string()
1456
+ }).strict()),
1457
+ findings: z.array(z.object({
1458
+ dimension: z.enum(COMMUNITY_REVIEW_DIMENSIONS),
1459
+ severity: z.enum([
1460
+ "info",
1461
+ "suggestion",
1462
+ "warning",
1463
+ "risk",
1464
+ "critical"
1465
+ ]),
1466
+ title: z.string(),
1467
+ detail: z.string(),
1468
+ file: z.string().optional(),
1469
+ line: z.number().int().optional(),
1470
+ suggestion: z.string().optional()
1471
+ }).strict()),
1472
+ exploitability: z.string().optional()
1473
+ }).strict().nullable(),
1474
+ model: z.string().nullable(),
1475
+ error: z.string().nullable(),
1476
+ decisions: z.array(z.object({
1477
+ decision: z.string(),
1478
+ note: z.string(),
1479
+ by: z.string(),
1480
+ createdAt: z.number().int()
1481
+ }).strict()),
1482
+ finishedAt: z.number().int().nullable(),
1483
+ reportUrl: z.string().url()
1484
+ }).strict();
1485
+ /** 安装者看到的审查标签:只描述审查发现,不做「安全」担保。 */
1486
+ const communityReviewLabel = (status) => {
1487
+ switch (status) {
1488
+ case "passed": return {
1489
+ tone: "ok",
1490
+ label: "审查通过"
1491
+ };
1492
+ case "passed_with_notes": return {
1493
+ tone: "accent",
1494
+ label: "审查通过,有建议"
1495
+ };
1496
+ case "flagged": return {
1497
+ tone: "warn",
1498
+ label: "有风险,待复审"
1499
+ };
1500
+ case "risk_confirmed": return {
1501
+ tone: "warn",
1502
+ label: "有风险"
1503
+ };
1504
+ case "held": return {
1505
+ tone: "bad",
1506
+ label: "暂停公开,待复审"
1507
+ };
1508
+ case "rejected": return {
1509
+ tone: "bad",
1510
+ label: "未通过"
1511
+ };
1512
+ case "pending":
1513
+ case "reviewing":
1514
+ case "incomplete": return {
1515
+ tone: "neutral",
1516
+ label: "风险未知"
1517
+ };
1518
+ }
1519
+ };
1520
+ //#endregion
1521
+ //#region src/host-api.ts
1522
+ const EmptyParamsSchema = z.object({}).strict();
1523
+ const NoRequestBodySchema = z.undefined();
1524
+ const NonEmptyStringSchema = z.string().trim().min(1);
1525
+ const DynamicIdSchema = NonEmptyStringSchema;
1526
+ const DynamicAttemptStatusSchema = z.enum([
1527
+ "awaiting-approval",
1528
+ "starting-host",
1529
+ "client-pending",
1530
+ "running",
1531
+ "waiting",
1532
+ "rejected",
1533
+ "failed",
1534
+ "cancelled",
1535
+ "stopped"
1536
+ ]);
1537
+ const DynamicHalfStateSchema = z.object({
1538
+ status: z.enum([
1539
+ "absent",
1540
+ "pending",
1541
+ "stopped",
1542
+ "running",
1543
+ "waiting",
1544
+ "failed"
1545
+ ]),
1546
+ waitingFor: z.array(z.string()),
1547
+ error: z.string().optional()
1548
+ }).strict();
1549
+ const DynamicAttemptErrorSchema = z.object({
1550
+ phase: z.enum([
1551
+ "approval",
1552
+ "host-load",
1553
+ "host-apply",
1554
+ "client-load",
1555
+ "client-apply",
1556
+ "client-render"
1557
+ ]),
1558
+ message: z.string(),
1559
+ stack: z.string().optional(),
1560
+ pluginId: DynamicIdSchema,
1561
+ packageId: DynamicIdSchema,
1562
+ pluginRunId: DynamicIdSchema
1563
+ }).strict();
1564
+ const DynamicLatestRunSchema = z.object({
1565
+ pluginRunId: DynamicIdSchema,
1566
+ packageId: DynamicIdSchema,
1567
+ mode: z.enum(["run", "update"]),
1568
+ status: DynamicAttemptStatusSchema,
1569
+ approvalRequestId: DynamicIdSchema.optional(),
1570
+ requiresApproval: z.boolean().optional(),
1571
+ host: DynamicHalfStateSchema,
1572
+ client: DynamicHalfStateSchema,
1573
+ error: DynamicAttemptErrorSchema.optional()
1574
+ }).strict();
1575
+ const AuthoringTaskStatusSchema = z.enum([
1576
+ "working",
1577
+ "awaiting-approval",
1578
+ "running",
1579
+ "ready",
1580
+ "repairing",
1581
+ "failed",
1582
+ "interrupted",
1583
+ "stopped",
1584
+ "completed"
1585
+ ]);
1586
+ const AuthoringAttemptStateSchema = z.enum([
1587
+ "drafting",
1588
+ "preflight-failed",
1589
+ "awaiting-approval",
1590
+ "starting-host",
1591
+ "loading-client",
1592
+ "verifying",
1593
+ "active",
1594
+ "failed",
1595
+ "rejected",
1596
+ "stopped"
1597
+ ]);
1598
+ const AuthoringAttemptSummarySchema = z.object({
1599
+ id: AuthoringAttemptIdSchema,
1600
+ ordinal: z.number().int().positive(),
1601
+ name: z.string(),
1602
+ purpose: z.string(),
1603
+ state: AuthoringAttemptStateSchema,
1604
+ riskDigest: z.string().regex(/^[a-f0-9]{64}$/u),
1605
+ host: DynamicHalfStateSchema,
1606
+ client: DynamicHalfStateSchema,
1607
+ error: z.object({
1608
+ phase: z.enum([
1609
+ "preflight",
1610
+ "approval",
1611
+ "host-load",
1612
+ "host-apply",
1613
+ "client-load",
1614
+ "client-apply",
1615
+ "client-render",
1616
+ "verification",
1617
+ "settlement",
1618
+ "restore"
1619
+ ]),
1620
+ message: z.string(),
1621
+ repairable: z.boolean()
1622
+ }).strict().optional(),
1623
+ createdAt: z.number().int().nonnegative(),
1624
+ settledAt: z.number().int().nonnegative().optional()
1625
+ }).strict();
1626
+ const AuthoringTaskSummarySchema = z.object({
1627
+ id: AuthoringTaskIdSchema,
1628
+ agentId: AgentIdSchema,
1629
+ channelId: ChannelIdSchema,
1630
+ episodeId: EpisodeIdSchema,
1631
+ title: z.string(),
1632
+ requirementSummary: z.string(),
1633
+ status: AuthoringTaskStatusSchema,
1634
+ approvalPolicy: z.enum(["risk-stable", "fully-automatic"]),
1635
+ approvedRiskDigest: z.string().regex(/^[a-f0-9]{64}$/u).optional(),
1636
+ revision: z.number().int().positive(),
1637
+ activeAttempt: AuthoringAttemptSummarySchema.optional(),
1638
+ candidateAttempt: AuthoringAttemptSummarySchema.optional(),
1639
+ /** Latest attempt that still carries product verification evidence; it can be restored as the candidate. */
1640
+ verifiedAttempt: AuthoringAttemptSummarySchema.optional(),
1641
+ createdAt: z.number().int().nonnegative(),
1642
+ updatedAt: z.number().int().nonnegative()
1643
+ }).strict();
1644
+ const ConnectionAliasInputSchema = z.string().trim().max(80).transform((value) => value || void 0);
1645
+ const ConnectionAliasOutputSchema = z.string().trim().min(1).max(80);
1646
+ const HostApiErrorSchema = z.object({ error: z.object({
1647
+ code: NonEmptyStringSchema,
1648
+ message: z.string()
1649
+ }).strict() }).strict();
1650
+ const AgentModelSchema = z.object({
1651
+ provider: NonEmptyStringSchema,
1652
+ model: NonEmptyStringSchema,
1653
+ reasoningEffort: NonEmptyStringSchema.optional()
1654
+ }).strict();
1655
+ const ImageUnderstandingPolicyApiSchema = z.object({
1656
+ history: z.object({
1657
+ mode: z.literal("persistent-distinct"),
1658
+ detail: z.enum([
1659
+ "low",
1660
+ "auto",
1661
+ "high"
1662
+ ]),
1663
+ restoreAfterCompaction: z.object({
1664
+ recentMessages: z.number().int().min(1).max(100),
1665
+ maxImages: z.number().int().min(1).max(50)
1666
+ }).strict()
1667
+ }).strict(),
1668
+ textModel: z.discriminatedUnion("mode", [z.object({ mode: z.literal("disabled") }).strict(), z.object({
1669
+ mode: z.literal("auxiliary"),
1670
+ model: AgentModelSchema,
1671
+ maxTokens: z.number().int().min(256).max(8192)
1672
+ }).strict()])
1673
+ }).strict();
1674
+ const AgentCapabilitiesSchema = z.object({
1675
+ subagents: z.boolean(),
1676
+ fileTools: z.boolean(),
1677
+ webSearch: z.boolean(),
1678
+ dynamicCreation: z.boolean(),
1679
+ developmentShell: z.boolean(),
1680
+ unrestrictedFileAccess: z.boolean(),
1681
+ /** Absent in older clients means on. */
1682
+ scheduledTasks: z.boolean().default(true)
1683
+ }).strict();
1684
+ const DynamicClientApprovalPolicySchema = z.enum(["manual", "automatic"]);
1685
+ const NotificationEventKeySchema = z.enum(["dynamic-client-approval-requested"]);
1686
+ const NotificationSettingsViewSchema = z.object({
1687
+ revision: z.number().int().positive().optional(),
1688
+ system: z.object({ enabled: z.boolean() }).strict(),
1689
+ bark: z.object({
1690
+ enabled: z.boolean(),
1691
+ serverUrl: z.url(),
1692
+ deviceKeyConfigured: z.boolean()
1693
+ }).strict(),
1694
+ events: z.record(NotificationEventKeySchema, z.boolean())
1695
+ }).strict();
1696
+ const UpdateNotificationSettingsRequestSchema = z.object({
1697
+ expectedRevision: z.number().int().positive().optional(),
1698
+ system: z.object({ enabled: z.boolean() }).strict(),
1699
+ bark: z.object({
1700
+ enabled: z.boolean(),
1701
+ serverUrl: z.url(),
1702
+ deviceKey: z.string().trim().min(1).max(2048).optional(),
1703
+ clearDeviceKey: z.boolean().optional()
1704
+ }).strict(),
1705
+ events: z.record(NotificationEventKeySchema, z.boolean())
1706
+ }).strict().refine((value) => !(value.bark.deviceKey !== void 0 && value.bark.clearDeviceKey === true), {
1707
+ message: "不能同时更新并清除 Bark Device Key。",
1708
+ path: ["bark"]
1709
+ });
1710
+ const TestBarkNotificationRequestSchema = z.object({
1711
+ serverUrl: z.url(),
1712
+ deviceKey: z.string().trim().min(1).max(2048).optional()
1713
+ }).strict();
1714
+ const ClientNotificationFeedResponseSchema = z.object({
1715
+ cursor: z.number().int().nonnegative(),
1716
+ notifications: z.array(ClientNotificationSchema)
1717
+ }).strict();
1718
+ const AgentRevisionRequestContentSchema = z.object({
1719
+ displayName: z.string().trim().min(1).max(80),
1720
+ persona: z.string().max(64 * 1024).default(""),
1721
+ personaDocument: PromptDocumentV1Schema.optional(),
1722
+ model: AgentModelSchema,
1723
+ imagePolicy: ImageUnderstandingPolicyApiSchema.optional(),
1724
+ dynamicClientApprovalPolicy: DynamicClientApprovalPolicySchema.optional()
1725
+ }).strict();
1726
+ const validatePersonaDocumentProjection = (value, context) => {
1727
+ if (value.personaDocument !== void 0 && promptDocumentPlainText(value.personaDocument) !== value.persona) context.addIssue({
1728
+ code: "custom",
1729
+ message: "人设文本必须与结构化人设文档一致。",
1730
+ path: ["personaDocument"],
1731
+ input: value
1732
+ });
1733
+ };
1734
+ const CreateAgentRequestSchema = AgentRevisionRequestContentSchema.extend({ capabilities: AgentCapabilitiesSchema.optional() }).superRefine((value, context) => {
1735
+ validatePersonaDocumentProjection(value, context);
1736
+ });
1737
+ const ReviseAgentRequestSchema = AgentRevisionRequestContentSchema.extend({ expectedCurrentRevisionId: AgentRevisionIdSchema }).superRefine((value, context) => {
1738
+ validatePersonaDocumentProjection(value, context);
1739
+ });
1740
+ const UpdateAgentCapabilitiesRequestSchema = AgentCapabilitiesSchema.partial().extend({ scheduledTasks: z.boolean().optional() }).strict().refine((value) => Object.values(value).some((entry) => entry !== void 0), "至少提供一个能力。");
1741
+ const TriggerPolicySchema = z.enum([
1742
+ "always",
1743
+ "mentioned-or-replied",
1744
+ "command",
1745
+ "observe-only"
1746
+ ]);
1747
+ const WorkTreeOrderSchema = z.object({
1748
+ agentIds: z.array(AgentIdSchema),
1749
+ channelIdsByAgent: z.record(AgentIdSchema, z.array(ChannelIdSchema)),
1750
+ unboundChannelIds: z.array(ChannelIdSchema)
1751
+ }).strict();
1752
+ const SnapshotMessagePartSchema = z.discriminatedUnion("type", [
1753
+ z.object({
1754
+ type: z.literal("text"),
1755
+ text: z.string()
1756
+ }).strict(),
1757
+ z.object({
1758
+ type: z.literal("mention"),
1759
+ memberId: ChannelMemberIdSchema,
1760
+ displayName: z.string().optional()
1761
+ }).strict(),
1762
+ z.object({
1763
+ type: z.literal("image"),
1764
+ assetId: AssetIdSchema,
1765
+ alt: z.string().optional()
1766
+ }).strict(),
1767
+ z.object({
1768
+ type: z.literal("file"),
1769
+ assetId: AssetIdSchema,
1770
+ name: z.string().optional()
1771
+ }).strict(),
1772
+ z.object({
1773
+ type: z.literal("audio"),
1774
+ assetId: AssetIdSchema
1775
+ }).strict(),
1776
+ z.object({
1777
+ type: z.literal("quote"),
1778
+ messageId: LogicalMessageIdSchema
1779
+ }).strict(),
1780
+ z.object({
1781
+ type: z.literal("rich"),
1782
+ adapterKey: z.string().trim().min(1).max(64),
1783
+ kind: z.string().trim().min(1).max(64),
1784
+ summary: z.string().trim().min(1).max(500),
1785
+ title: z.string().trim().min(1).max(200).optional(),
1786
+ source: z.string().trim().min(1).max(80).optional(),
1787
+ targetUrl: RichTargetUrlSchema.optional(),
1788
+ previewAssetId: AssetIdSchema.optional(),
1789
+ extension: RichExtensionSchema.optional()
1790
+ }).strict()
1791
+ ]);
1792
+ const HostSnapshotMessageSchema = z.object({
1793
+ id: z.union([ChannelEventIdSchema, OutboundIntentIdSchema]),
1794
+ channelId: ChannelIdSchema,
1795
+ role: z.enum([
1796
+ "member",
1797
+ "agent",
1798
+ "system"
1799
+ ]),
1800
+ parts: z.array(SnapshotMessagePartSchema),
1801
+ sender: z.object({
1802
+ memberId: ChannelMemberIdSchema,
1803
+ displayName: z.string().optional()
1804
+ }).strict().optional(),
1805
+ mentionedConnectionAccount: z.boolean().optional(),
1806
+ activityKey: AdapterActivityKeySchema.optional(),
1807
+ targetLogicalMessageId: LogicalMessageIdSchema.optional(),
1808
+ occurredAt: z.number().finite(),
1809
+ deliveryState: z.enum([
1810
+ "planned",
1811
+ "sending",
1812
+ "sent",
1813
+ "partially-sent",
1814
+ "failed",
1815
+ "unknown"
1816
+ ]).optional(),
1817
+ /** Latest administrator resolution of an unsettled delivery; history keeps the original receipt state. */
1818
+ deliveryResolution: z.object({
1819
+ action: z.enum(["retry", "confirm-delivered"]),
1820
+ resolvedAt: z.number().int().safe().nonnegative()
1821
+ }).strict().optional(),
1822
+ origin: z.enum(["admin-console"]).optional(),
1823
+ /** What the agent's inbound hooks decided for this message, when anything differs from the default. */
1824
+ inboundHook: z.object({
1825
+ trigger: z.enum([
1826
+ "default",
1827
+ "suppress",
1828
+ "force"
1829
+ ]),
1830
+ hidden: z.boolean(),
1831
+ annotation: z.string().optional(),
1832
+ extensions: z.array(z.string()),
1833
+ problems: z.array(z.string()).optional()
1834
+ }).strict().optional(),
1835
+ /** A scheduled task came due: a Host fact shown as a notice, not a member message. */
1836
+ scheduledTask: z.object({
1837
+ label: z.string(),
1838
+ extensionName: z.string().optional(),
1839
+ note: z.string().optional()
1840
+ }).strict().optional()
1841
+ }).strict();
1842
+ const HostConnectionEventSchema = z.object({
1843
+ id: ConnectionEventIdSchema,
1844
+ connectionId: ConnectionIdSchema,
1845
+ activityKey: AdapterActivityKeySchema,
1846
+ summary: z.string(),
1847
+ actor: z.object({
1848
+ identityId: PlatformIdentityIdSchema,
1849
+ displayName: z.string().optional()
1850
+ }).strict().optional(),
1851
+ subject: z.object({
1852
+ identityId: PlatformIdentityIdSchema,
1853
+ displayName: z.string().optional()
1854
+ }).strict().optional(),
1855
+ occurredAt: z.number().int().safe().nonnegative()
1856
+ }).strict();
1857
+ const PlatformUserChannelPreviewSchema = z.object({
1858
+ id: ChannelIdSchema,
1859
+ displayName: z.string().trim().min(1).max(120).optional(),
1860
+ kind: z.enum([
1861
+ "internal",
1862
+ "direct",
1863
+ "group"
1864
+ ])
1865
+ }).strict();
1866
+ const PlatformUserFacetAdapterSchema = z.object({
1867
+ key: NonEmptyStringSchema,
1868
+ displayName: NonEmptyStringSchema,
1869
+ userCount: z.number().int().nonnegative()
1870
+ }).strict();
1871
+ const PlatformUserFacetConnectionSchema = z.object({
1872
+ id: ConnectionIdSchema,
1873
+ adapterKey: NonEmptyStringSchema,
1874
+ displayName: NonEmptyStringSchema,
1875
+ userCount: z.number().int().nonnegative()
1876
+ }).strict();
1877
+ const PlatformUserListResponseSchema = z.object({
1878
+ total: z.number().int().nonnegative(),
1879
+ items: z.array(z.object({
1880
+ identityId: PlatformIdentityIdSchema,
1881
+ displayName: z.string().trim().min(1).max(120).optional(),
1882
+ adapter: z.object({
1883
+ key: NonEmptyStringSchema,
1884
+ displayName: NonEmptyStringSchema
1885
+ }).strict(),
1886
+ connection: z.object({
1887
+ id: ConnectionIdSchema,
1888
+ displayName: NonEmptyStringSchema
1889
+ }).strict(),
1890
+ activeChannelCount: z.number().int().nonnegative(),
1891
+ channelPreview: z.array(PlatformUserChannelPreviewSchema).max(3),
1892
+ historicalOnly: z.boolean()
1893
+ }).strict()),
1894
+ facets: z.object({
1895
+ adapters: z.array(PlatformUserFacetAdapterSchema),
1896
+ connections: z.array(PlatformUserFacetConnectionSchema)
1897
+ }).strict(),
1898
+ nextCursor: PlatformIdentityIdSchema.optional()
1899
+ }).strict();
1900
+ const ChannelFactSseItemSchema = z.object({
1901
+ kind: z.enum(["inbound", "outbound"]),
1902
+ sourceId: z.union([ChannelEventIdSchema, OutboundIntentIdSchema]),
1903
+ message: HostSnapshotMessageSchema
1904
+ }).strict();
1905
+ const ChannelFactSseDataSchema = z.object({
1906
+ channelId: ChannelIdSchema,
1907
+ revision: z.number().int().positive(),
1908
+ items: z.array(ChannelFactSseItemSchema).min(1)
1909
+ }).strict();
1910
+ const ChannelRuntimePhaseSchema = z.enum([
1911
+ "idle",
1912
+ "thinking",
1913
+ "using-tool",
1914
+ "waiting-input",
1915
+ "unavailable"
1916
+ ]);
1917
+ const ChannelRuntimeUsageSchema = z.object({
1918
+ inputTokens: z.number().int().nonnegative(),
1919
+ outputTokens: z.number().int().nonnegative(),
1920
+ totalTokens: z.number().int().nonnegative().optional(),
1921
+ cacheReadTokens: z.number().int().nonnegative().optional(),
1922
+ cacheWriteTokens: z.number().int().nonnegative().optional(),
1923
+ reasoningTokens: z.number().int().nonnegative().optional()
1924
+ }).strict();
1925
+ const ChannelRuntimeToolSchema = z.object({
1926
+ callId: NonEmptyStringSchema,
1927
+ name: NonEmptyStringSchema,
1928
+ displayName: NonEmptyStringSchema,
1929
+ state: z.enum([
1930
+ "running",
1931
+ "succeeded",
1932
+ "failed"
1933
+ ]),
1934
+ inputPreview: z.string().optional(),
1935
+ resultPreview: z.string().optional(),
1936
+ wroteToChannel: z.boolean().optional(),
1937
+ deliveryState: z.enum([
1938
+ "sent",
1939
+ "partially-sent",
1940
+ "failed",
1941
+ "unknown"
1942
+ ]).optional(),
1943
+ durationMs: z.number().int().nonnegative().optional()
1944
+ }).strict();
1945
+ const ChannelRuntimeStepSchema = z.object({
1946
+ step: z.number().int().nonnegative(),
1947
+ tools: z.array(ChannelRuntimeToolSchema),
1948
+ internalOutput: z.object({
1949
+ kind: z.literal("internal-output"),
1950
+ text: z.string().optional(),
1951
+ reasoning: z.string().optional()
1952
+ }).strict().optional(),
1953
+ durationMs: z.number().int().nonnegative().optional(),
1954
+ firstTokenMs: z.number().int().nonnegative().optional(),
1955
+ usage: ChannelRuntimeUsageSchema.optional()
1956
+ }).strict();
1957
+ const ChannelRuntimeTurnSchema = z.object({
1958
+ turn: z.number().int().nonnegative(),
1959
+ state: z.enum([
1960
+ "in-progress",
1961
+ "completed",
1962
+ "unreplied",
1963
+ "aborted",
1964
+ "error",
1965
+ "max-tokens",
1966
+ "interrupted"
1967
+ ]),
1968
+ producedReply: z.boolean(),
1969
+ responseState: z.enum([
1970
+ "not-required",
1971
+ "pending",
1972
+ "sent",
1973
+ "finished",
1974
+ "protocol-failed",
1975
+ "interrupted"
1976
+ ]),
1977
+ error: z.object({
1978
+ code: NonEmptyStringSchema,
1979
+ message: z.string()
1980
+ }).strict().optional(),
1981
+ steps: z.array(ChannelRuntimeStepSchema),
1982
+ durationMs: z.number().int().nonnegative().optional(),
1983
+ /** Session log time the turn opened. */
1984
+ startedAt: z.number().int().safe().nonnegative().optional(),
1985
+ /** Session log time the turn closed; absent while it is still running. */
1986
+ endedAt: z.number().int().safe().nonnegative().optional(),
1987
+ /** Newest Channel Event of the admission that opened this turn; absent for non-channel turns. */
1988
+ triggerEventId: ChannelEventIdSchema.optional()
1989
+ }).strict();
1990
+ const ChannelRuntimeOccupancySchema = z.object({
1991
+ projectedTokens: z.number().int().nonnegative(),
1992
+ contextWindow: z.number().int().positive(),
1993
+ breakdown: z.object({
1994
+ systemTokens: z.number().int().nonnegative(),
1995
+ toolsTokens: z.number().int().nonnegative(),
1996
+ messageTokens: z.number().int().nonnegative()
1997
+ }).strict().optional()
1998
+ }).strict();
1999
+ const ChannelRuntimeCacheSampleSchema = z.object({
2000
+ turn: z.number().int().nonnegative(),
2001
+ step: z.number().int().nonnegative(),
2002
+ at: z.number().nonnegative().optional(),
2003
+ uncachedInputTokens: z.number().int().nonnegative(),
2004
+ cacheReadTokens: z.number().int().nonnegative().optional(),
2005
+ cacheWriteTokens: z.number().int().nonnegative().optional()
2006
+ }).strict();
2007
+ const ChannelRuntimeCacheSchema = z.object({
2008
+ scope: z.literal("episode"),
2009
+ aggregate: z.object({
2010
+ usageRequestCount: z.number().int().nonnegative(),
2011
+ observedRequestCount: z.number().int().nonnegative(),
2012
+ shareRequestCount: z.number().int().nonnegative(),
2013
+ hitRequestCount: z.number().int().nonnegative(),
2014
+ uncachedInputTokens: z.number().int().nonnegative(),
2015
+ cacheReadTokens: z.number().int().nonnegative(),
2016
+ cacheWriteTokens: z.number().int().nonnegative(),
2017
+ averageRequestReadShare: z.number().min(0).max(1).optional()
2018
+ }).strict(),
2019
+ recent: z.object({
2020
+ windowSize: z.number().int().positive(),
2021
+ samples: z.array(ChannelRuntimeCacheSampleSchema)
2022
+ }).strict()
2023
+ }).strict();
2024
+ const ChannelRuntimePerformanceSampleSchema = z.object({
2025
+ turn: z.number().int().nonnegative(),
2026
+ step: z.number().int().nonnegative(),
2027
+ at: z.number().nonnegative().optional(),
2028
+ firstTokenMs: z.number().int().nonnegative().optional(),
2029
+ decodeMs: z.number().int().nonnegative().optional(),
2030
+ outputTokens: z.number().int().nonnegative().optional()
2031
+ }).strict();
2032
+ const ChannelRuntimePerformanceSchema = z.object({
2033
+ scope: z.literal("episode"),
2034
+ aggregate: z.object({
2035
+ steps: z.number().int().nonnegative(),
2036
+ llmMs: z.number().nonnegative(),
2037
+ toolMs: z.number().nonnegative(),
2038
+ ttftMs: z.number().nonnegative(),
2039
+ ttftSteps: z.number().int().nonnegative(),
2040
+ decodeMs: z.number().nonnegative(),
2041
+ decodeTokens: z.number().int().nonnegative(),
2042
+ decodeSteps: z.number().int().nonnegative(),
2043
+ retryCount: z.number().int().nonnegative(),
2044
+ retryDelayMs: z.number().nonnegative()
2045
+ }).strict(),
2046
+ recent: z.object({
2047
+ windowSize: z.number().int().positive(),
2048
+ samples: z.array(ChannelRuntimePerformanceSampleSchema)
2049
+ }).strict()
2050
+ }).strict();
2051
+ const ChannelRuntimeProjectionSchema = z.object({
2052
+ channelId: ChannelIdSchema,
2053
+ agentId: AgentIdSchema.optional(),
2054
+ episodeId: EpisodeIdSchema.optional(),
2055
+ phase: ChannelRuntimePhaseSchema,
2056
+ summary: z.string(),
2057
+ pendingInjectCount: z.number().int().nonnegative(),
2058
+ occupancy: ChannelRuntimeOccupancySchema.optional(),
2059
+ cache: ChannelRuntimeCacheSchema.optional(),
2060
+ performance: ChannelRuntimePerformanceSchema.optional(),
2061
+ turns: z.array(ChannelRuntimeTurnSchema)
2062
+ }).strict();
2063
+ const ChannelRuntimeSseDataSchema = ChannelRuntimeProjectionSchema.extend({
2064
+ revision: z.number().int().positive(),
2065
+ truncated: z.boolean().optional()
2066
+ }).strict();
2067
+ const AdapterConnectionCreationSchema = z.object({
2068
+ mode: z.enum(["schema-form", "qr-login"]),
2069
+ actionLabel: z.string().trim().min(1).optional(),
2070
+ pendingLabel: z.string().trim().min(1).optional()
2071
+ }).strict();
2072
+ const AdapterConnectionDescriptorSchema = z.object({
2073
+ key: NonEmptyStringSchema,
2074
+ displayName: z.string(),
2075
+ description: z.string(),
2076
+ provisioning: z.enum(["user-created", "system-singleton"]),
2077
+ aliasEditable: z.boolean(),
2078
+ channelDiscovery: z.enum(["host-created", "adapter-observed"]),
2079
+ channelKinds: z.array(z.enum([
2080
+ "internal",
2081
+ "direct",
2082
+ "group"
2083
+ ])).min(1),
2084
+ activities: z.array(z.object({
2085
+ key: AdapterActivityKeySchema,
2086
+ scope: z.enum(["channel", "connection"]),
2087
+ displayName: z.string().trim().min(1),
2088
+ description: z.string().trim().min(1),
2089
+ icon: HostIconNameSchema.optional(),
2090
+ triggerable: z.boolean(),
2091
+ channelKinds: z.array(z.enum([
2092
+ "internal",
2093
+ "direct",
2094
+ "group"
2095
+ ])).optional()
2096
+ }).strict()),
2097
+ features: z.object({ processingFeedback: z.object({ channelKinds: z.array(z.enum(["direct", "group"])).min(1) }).strict().optional() }).strict(),
2098
+ diagnostics: z.object({
2099
+ receive: z.boolean(),
2100
+ send: z.boolean()
2101
+ }).strict(),
2102
+ creation: AdapterConnectionCreationSchema.optional(),
2103
+ /** Typed platform actions the Adapter offers to agent extensions (`ctx.nxt.platform`). */
2104
+ platformActions: z.array(z.object({
2105
+ name: z.string().regex(/^[a-z0-9_]{1,64}$/u),
2106
+ title: z.string(),
2107
+ description: z.string(),
2108
+ risk: z.enum(["low", "admin"]),
2109
+ channelKinds: z.array(z.enum(["direct", "group"])).min(1),
2110
+ parameters: z.object({
2111
+ type: z.literal("object"),
2112
+ properties: z.record(z.string(), JsonValueSchema),
2113
+ required: z.array(z.string()).optional()
2114
+ }).strict()
2115
+ }).strict()).optional(),
2116
+ rawApi: z.object({ description: z.string() }).strict().optional(),
2117
+ configSchema: ConfigSchemaDocumentSchema
2118
+ }).strict();
2119
+ const AdapterCapabilityStateSchema = z.object({
2120
+ state: z.enum([
2121
+ "available",
2122
+ "disabled",
2123
+ "unsupported",
2124
+ "degraded",
2125
+ "unknown"
2126
+ ]),
2127
+ reason: z.string().optional()
2128
+ }).strict();
2129
+ const ActivityTriggerOverridesSchema = z.record(AdapterActivityKeySchema, z.boolean());
2130
+ const HostSyncCursorSchema = z.object({
2131
+ epoch: z.string().regex(/^[a-zA-Z0-9_-]{1,100}$/u),
2132
+ sequence: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER)
2133
+ }).strict();
2134
+ const AgentAppearanceSchema = z.object({
2135
+ hue: z.number().int().min(0).max(359).optional(),
2136
+ avatarAssetId: AssetIdSchema.optional()
2137
+ }).strict();
2138
+ /** Upper bound of a reported unread count; `unreadCapped` marks that more exist. */
2139
+ const CHANNEL_UNREAD_COUNT_CAP = 99;
2140
+ const ChannelActivitySummarySchema = z.object({
2141
+ lastActivityAt: z.number().int().safe().nonnegative().optional(),
2142
+ lastMessage: z.object({
2143
+ role: z.enum([
2144
+ "member",
2145
+ "agent",
2146
+ "admin",
2147
+ "system"
2148
+ ]),
2149
+ author: z.string().max(120),
2150
+ preview: z.string().max(160),
2151
+ occurredAt: z.number().int().safe().nonnegative()
2152
+ }).strict().optional(),
2153
+ unreadCount: z.number().int().nonnegative().max(99),
2154
+ unreadCapped: z.boolean()
2155
+ }).strict();
2156
+ const AttentionItemSchema = z.object({
2157
+ /** Stable fingerprint; a recurrence of the same condition gets a new fingerprint. */
2158
+ id: z.string().min(1).max(200),
2159
+ kind: z.enum([
2160
+ "delivery-unconfirmed",
2161
+ "delivery-failed",
2162
+ "turn-failed",
2163
+ "authoring-approval",
2164
+ "connection-unhealthy",
2165
+ "agent-model-unavailable",
2166
+ "agent-vision-unavailable"
2167
+ ]),
2168
+ severity: z.enum([
2169
+ "critical",
2170
+ "warning",
2171
+ "info"
2172
+ ]),
2173
+ subject: z.object({
2174
+ kind: z.enum([
2175
+ "outbound",
2176
+ "channel",
2177
+ "authoring-task",
2178
+ "connection",
2179
+ "agent"
2180
+ ]),
2181
+ id: NonEmptyStringSchema
2182
+ }).strict(),
2183
+ related: z.object({
2184
+ channelId: ChannelIdSchema.optional(),
2185
+ agentId: AgentIdSchema.optional(),
2186
+ connectionId: ConnectionIdSchema.optional(),
2187
+ taskId: AuthoringTaskIdSchema.optional(),
2188
+ outboundId: OutboundIntentIdSchema.optional()
2189
+ }).strict(),
2190
+ title: z.string().min(1).max(120),
2191
+ detail: z.string().max(400),
2192
+ action: z.object({
2193
+ kind: z.enum([
2194
+ "open-channel",
2195
+ "resolve-delivery",
2196
+ "open-authoring-task",
2197
+ "open-connection",
2198
+ "open-agent"
2199
+ ]),
2200
+ label: z.string().min(1).max(40)
2201
+ }).strict(),
2202
+ occurredAt: z.number().int().safe().nonnegative()
2203
+ }).strict();
2204
+ const AttentionListSchema = z.object({
2205
+ revision: z.string().min(1),
2206
+ items: z.array(AttentionItemSchema).max(200)
2207
+ }).strict();
2208
+ const ChannelPendingContextSchema = z.object({
2209
+ channelId: ChannelIdSchema,
2210
+ episodeId: EpisodeIdSchema.optional(),
2211
+ items: z.array(z.object({
2212
+ admissionId: NonEmptyStringSchema,
2213
+ /** `next-step`: injected at the next safe step boundary; `next-turn`: waits for a later turn. */
2214
+ target: z.enum(["next-step", "next-turn"]),
2215
+ events: z.array(z.object({
2216
+ eventId: ChannelEventIdSchema,
2217
+ author: z.string().max(120),
2218
+ preview: z.string().max(160),
2219
+ receivedAt: z.number().int().safe().nonnegative()
2220
+ }).strict())
2221
+ }).strict())
2222
+ }).strict();
2223
+ const ACTIVITY_MAX_WINDOW_MS = 1440 * 60 * 1e3;
2224
+ const ACTIVITY_MIN_BUCKET_MS = 60 * 1e3;
2225
+ const ACTIVITY_MAX_BUCKETS = 288;
2226
+ const ActivityDurationSchema = z.string().regex(/^[1-9][0-9]{0,4}[mh]$/u);
2227
+ const activityDurationMs = (value) => {
2228
+ const amount = Number(value.slice(0, -1));
2229
+ return value.endsWith("h") ? amount * 60 * 60 * 1e3 : amount * 60 * 1e3;
2230
+ };
2231
+ const ActivityQuerySchema = z.object({
2232
+ window: ActivityDurationSchema.default("2h"),
2233
+ bucket: ActivityDurationSchema.default("5m")
2234
+ }).strict().superRefine((value, context) => {
2235
+ const window = activityDurationMs(value.window);
2236
+ const bucket = activityDurationMs(value.bucket);
2237
+ if (window > 864e5) context.addIssue({
2238
+ code: "custom",
2239
+ path: ["window"],
2240
+ message: "统计窗口不能超过 24 小时。"
2241
+ });
2242
+ if (bucket < 6e4) context.addIssue({
2243
+ code: "custom",
2244
+ path: ["bucket"],
2245
+ message: "统计间隔不能小于 1 分钟。"
2246
+ });
2247
+ if (bucket > window) context.addIssue({
2248
+ code: "custom",
2249
+ path: ["bucket"],
2250
+ message: "统计间隔不能大于统计窗口。"
2251
+ });
2252
+ if (window / bucket > 288) context.addIssue({
2253
+ code: "custom",
2254
+ path: ["bucket"],
2255
+ message: `统计桶不能超过 288 个。`
2256
+ });
2257
+ });
2258
+ const ChannelActivitySeriesSchema = z.object({
2259
+ from: z.number().int().safe().nonnegative(),
2260
+ to: z.number().int().safe().nonnegative(),
2261
+ bucketMs: z.number().int().positive(),
2262
+ channels: z.array(z.object({
2263
+ channelId: ChannelIdSchema,
2264
+ counts: z.array(z.number().int().nonnegative()).max(288),
2265
+ total: z.number().int().nonnegative()
2266
+ }).strict())
2267
+ }).strict();
2268
+ const ScheduledTaskIdSchema = z.string().regex(/^job_[0-9A-Za-z]+$/u);
2269
+ /**
2270
+ * One scheduled task of an agent in one channel. `chat` tasks come from the agent's scheduling tools; `declared` and
2271
+ * `runtime` tasks belong to an extension (Manifest plan or `ctx.nxt.jobs`).
2272
+ */
2273
+ const ScheduledTaskSchema = z.object({
2274
+ id: ScheduledTaskIdSchema,
2275
+ agentId: AgentIdSchema,
2276
+ channelId: ChannelIdSchema,
2277
+ source: z.enum([
2278
+ "chat",
2279
+ "declared",
2280
+ "runtime"
2281
+ ]),
2282
+ extensionId: ExtensionIdSchema.optional(),
2283
+ extensionName: z.string().optional(),
2284
+ label: z.string(),
2285
+ note: z.string().optional(),
2286
+ schedule: z.discriminatedUnion("kind", [z.object({
2287
+ kind: z.literal("once"),
2288
+ at: z.number().int().safe()
2289
+ }).strict(), z.object({
2290
+ kind: z.literal("cron"),
2291
+ cron: z.string(),
2292
+ timezone: z.string()
2293
+ }).strict()]),
2294
+ /** `inactive`: the owning extension is disabled for this agent, so the task stays silent. */
2295
+ state: z.enum([
2296
+ "scheduled",
2297
+ "paused",
2298
+ "finished",
2299
+ "inactive"
2300
+ ]),
2301
+ nextRunAt: z.number().int().safe().optional(),
2302
+ lastFiredAt: z.number().int().safe().optional(),
2303
+ createdAt: z.number().int().safe()
2304
+ }).strict();
2305
+ const HostSnapshotSchema = z.object({
2306
+ upgrade: HostUpgradeSummarySchema.optional(),
2307
+ cursor: HostSyncCursorSchema,
2308
+ diagnosticsSampledAt: z.number().int().nonnegative(),
2309
+ productMetadata: z.object({
2310
+ displayName: NonEmptyStringSchema,
2311
+ organizationName: NonEmptyStringSchema,
2312
+ version: NonEmptyStringSchema,
2313
+ releaseId: NonEmptyStringSchema,
2314
+ repositoryUrl: z.url(),
2315
+ licenseSpdx: NonEmptyStringSchema.nullable(),
2316
+ dshVersion: NonEmptyStringSchema.optional()
2317
+ }).strict().optional(),
2318
+ models: z.array(z.object({
2319
+ provider: NonEmptyStringSchema,
2320
+ providerName: NonEmptyStringSchema,
2321
+ id: NonEmptyStringSchema,
2322
+ name: z.string(),
2323
+ description: z.string().optional(),
2324
+ inputModalities: z.array(z.string()).optional()
2325
+ }).strict()),
2326
+ capabilityAvailability: z.object({
2327
+ subagents: z.object({ available: z.boolean() }).strict(),
2328
+ webSearch: z.object({
2329
+ provider: z.literal("deepseek-official"),
2330
+ available: z.boolean(),
2331
+ credentialConfigured: z.boolean(),
2332
+ credentialReference: NonEmptyStringSchema,
2333
+ maxUsesPerCall: z.number().int().nonnegative(),
2334
+ maxResultsPerCall: z.number().int().nonnegative(),
2335
+ timeoutMs: z.number().int().nonnegative()
2336
+ }).strict()
2337
+ }).strict(),
2338
+ connectionAdapters: z.array(AdapterConnectionDescriptorSchema),
2339
+ notificationSettings: NotificationSettingsViewSchema,
2340
+ agents: z.array(z.object({
2341
+ id: AgentIdSchema,
2342
+ displayName: z.string(),
2343
+ persona: z.string(),
2344
+ personaDocument: PromptDocumentV1Schema,
2345
+ model: AgentModelSchema,
2346
+ capabilities: AgentCapabilitiesSchema,
2347
+ imagePolicy: ImageUnderstandingPolicyApiSchema,
2348
+ dynamicClientApprovalPolicy: DynamicClientApprovalPolicySchema,
2349
+ imageDiagnostics: z.object({
2350
+ route: z.object({
2351
+ mode: z.enum([
2352
+ "direct",
2353
+ "delegated",
2354
+ "unavailable"
2355
+ ]),
2356
+ provider: z.string().optional(),
2357
+ model: z.string().optional()
2358
+ }).strict(),
2359
+ activeSessions: z.number().int().nonnegative(),
2360
+ residentImages: z.number().int().nonnegative(),
2361
+ duplicateImagesSkipped: z.number().int().nonnegative(),
2362
+ lastInspection: z.object({
2363
+ mode: z.enum(["direct", "delegated"]),
2364
+ imageCount: z.number().int().nonnegative(),
2365
+ provider: z.string().optional(),
2366
+ model: z.string().optional(),
2367
+ cacheHit: z.boolean(),
2368
+ usage: ChannelRuntimeUsageSchema.optional(),
2369
+ errorCode: z.string().optional()
2370
+ }).strict().optional(),
2371
+ lastRestoration: z.object({
2372
+ compactionId: z.string(),
2373
+ candidateCount: z.number().int().nonnegative(),
2374
+ restoredCount: z.number().int().nonnegative(),
2375
+ skippedCount: z.number().int().nonnegative(),
2376
+ error: z.string().optional()
2377
+ }).strict().optional(),
2378
+ blockers: z.array(z.string())
2379
+ }).strict(),
2380
+ currentRevisionId: AgentRevisionIdSchema,
2381
+ runtimeStatus: z.enum(["idle", "running"]),
2382
+ runtimePhase: ChannelRuntimePhaseSchema.default("idle"),
2383
+ createdAt: z.number().finite(),
2384
+ channels: z.array(ChannelIdSchema),
2385
+ appearance: AgentAppearanceSchema.default({})
2386
+ }).strict()),
2387
+ channels: z.array(z.object({
2388
+ id: ChannelIdSchema,
2389
+ connectionId: ConnectionIdSchema,
2390
+ platformChannelId: NonEmptyStringSchema,
2391
+ kind: z.enum([
2392
+ "internal",
2393
+ "group",
2394
+ "direct"
2395
+ ]),
2396
+ displayName: z.string().optional(),
2397
+ boundAgentId: AgentIdSchema.optional(),
2398
+ runtimePhase: ChannelRuntimePhaseSchema.default("idle"),
2399
+ activity: ChannelActivitySummarySchema.default({
2400
+ unreadCount: 0,
2401
+ unreadCapped: false
2402
+ }),
2403
+ bindings: z.array(z.object({
2404
+ channelId: ChannelIdSchema,
2405
+ agentId: AgentIdSchema,
2406
+ triggerPolicy: TriggerPolicySchema,
2407
+ processingFeedback: z.enum(["auto", "off"]).default("auto"),
2408
+ activityTriggerOverrides: ActivityTriggerOverridesSchema.default({}),
2409
+ boundAt: z.number().int().safe().nonnegative()
2410
+ }).strict())
2411
+ }).strict()),
2412
+ workTreeOrder: WorkTreeOrderSchema.default({
2413
+ agentIds: [],
2414
+ channelIdsByAgent: {},
2415
+ unboundChannelIds: []
2416
+ }),
2417
+ messages: z.array(HostSnapshotMessageSchema),
2418
+ connections: z.array(z.object({
2419
+ id: ConnectionIdSchema,
2420
+ adapterKey: NonEmptyStringSchema,
2421
+ alias: ConnectionAliasOutputSchema.optional(),
2422
+ activityTriggerDefaults: z.array(AdapterActivityKeySchema).default([]),
2423
+ status: z.object({
2424
+ state: z.enum([
2425
+ "stopped",
2426
+ "connecting",
2427
+ "connected",
2428
+ "reconnecting",
2429
+ "failed"
2430
+ ]),
2431
+ message: z.string().optional(),
2432
+ credentialConfigured: z.boolean(),
2433
+ proactiveSend: z.boolean(),
2434
+ accountReference: z.string().optional(),
2435
+ implementation: z.object({
2436
+ name: z.string().optional(),
2437
+ version: z.string().optional(),
2438
+ protocolVersion: z.string().optional()
2439
+ }).strict().optional(),
2440
+ optionalCapabilities: z.record(z.string(), z.enum([
2441
+ "unknown",
2442
+ "available",
2443
+ "unsupported",
2444
+ "degraded"
2445
+ ])).optional(),
2446
+ activities: z.record(z.string(), AdapterCapabilityStateSchema).default({}),
2447
+ processingFeedback: AdapterCapabilityStateSchema.optional()
2448
+ }).strict().default({
2449
+ state: "stopped",
2450
+ credentialConfigured: false,
2451
+ proactiveSend: false,
2452
+ activities: {}
2453
+ }),
2454
+ channelCount: z.number().int().nonnegative(),
2455
+ knownChannels: z.array(z.object({
2456
+ id: ChannelIdSchema,
2457
+ name: z.string(),
2458
+ kind: z.enum([
2459
+ "internal",
2460
+ "group",
2461
+ "direct"
2462
+ ])
2463
+ }).strict()),
2464
+ lastInbound: z.object({
2465
+ channelId: ChannelIdSchema,
2466
+ platformMessageId: NonEmptyStringSchema,
2467
+ receivedAt: z.number().int().safe().nonnegative()
2468
+ }).strict().optional(),
2469
+ receiveTest: z.lazy(() => ConnectionTestResultSchema).optional(),
2470
+ sendTest: z.lazy(() => ConnectionTestResultSchema).optional(),
2471
+ configuration: z.record(z.string(), z.union([
2472
+ z.string(),
2473
+ z.number(),
2474
+ z.boolean()
2475
+ ])).default({})
2476
+ }).strict()),
2477
+ archivedConnections: z.array(z.object({
2478
+ id: ConnectionIdSchema,
2479
+ adapterKey: NonEmptyStringSchema,
2480
+ alias: ConnectionAliasOutputSchema.optional(),
2481
+ channelCount: z.number().int().nonnegative(),
2482
+ archivedAt: z.number().int().safe().nonnegative()
2483
+ }).strict()).default([]),
2484
+ extensions: z.array(z.object({
2485
+ id: ExtensionIdSchema,
2486
+ scope: z.enum([
2487
+ "agent",
2488
+ "host-adapter",
2489
+ "host-ui"
2490
+ ]),
2491
+ slug: NonEmptyStringSchema,
2492
+ displayName: z.string(),
2493
+ description: z.string(),
2494
+ createdByAgentId: AgentIdSchema.optional(),
2495
+ revisions: z.array(z.object({
2496
+ id: ExtensionRevisionIdSchema,
2497
+ revisionNumber: z.number().int().positive(),
2498
+ format: z.enum(["current", "unavailable"]).optional(),
2499
+ ui: ExtensionUiContributionsSchema.default(EMPTY_EXTENSION_UI_CONTRIBUTIONS),
2500
+ configSchema: ConfigSchemaDocumentSchema.optional(),
2501
+ createdAt: z.number().int().safe().nonnegative(),
2502
+ /** 从社区安装的保存记录的来源;本机保存与文件导入没有来源。 */
2503
+ source: CommunitySourceSchema.optional(),
2504
+ scope: z.enum([
2505
+ "agent",
2506
+ "host-adapter",
2507
+ "host-ui"
2508
+ ]),
2509
+ contributions: z.array(z.string()),
2510
+ verification: z.object({
2511
+ verifiedAt: z.number().int().nonnegative(),
2512
+ dshVersion: z.string(),
2513
+ contractVersion: z.string(),
2514
+ hostBuilt: z.boolean(),
2515
+ clientBuilt: z.boolean(),
2516
+ buildKey: z.string(),
2517
+ toolInvocationCount: z.number().int().nonnegative(),
2518
+ rpcMethods: z.array(z.string()),
2519
+ renderedPanels: z.array(z.string()).default([]),
2520
+ renderedToolViews: z.array(z.string()).default([]),
2521
+ renderedMessageRenderers: z.array(z.string()).default([]),
2522
+ renderedPages: z.array(HostPageContributionSchema).max(8).optional(),
2523
+ usedUiComponents: z.array(HostUiKitComponentNameSchema).optional(),
2524
+ pageGeometry: z.array(HostUiPageGeometryEvidenceSchema).max(8).optional(),
2525
+ permissions: HostUiPermissionDeclarationSchema.optional(),
2526
+ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u).optional(),
2527
+ permissionApprovalRequired: z.boolean().optional(),
2528
+ adapter: z.object({
2529
+ apiVersion: z.literal(2),
2530
+ key: NonEmptyStringSchema,
2531
+ descriptorDigest: z.string().regex(/^[a-f0-9]{64}$/u),
2532
+ registered: z.boolean(),
2533
+ started: z.boolean(),
2534
+ stopped: z.boolean(),
2535
+ inboundCommitted: z.boolean(),
2536
+ outboundReceipt: z.enum([
2537
+ "sent",
2538
+ "failed",
2539
+ "unknown"
2540
+ ])
2541
+ }).strict().optional()
2542
+ }).strict().optional()
2543
+ }).strict()),
2544
+ activations: z.array(z.object({
2545
+ agentId: AgentIdSchema,
2546
+ extensionRevisionId: ExtensionRevisionIdSchema,
2547
+ /** Secret fields are removed; `configuredSecrets` lists those the Host stores. */
2548
+ config: JsonValueSchema,
2549
+ configuredSecrets: z.array(z.string()).optional(),
2550
+ activatedAt: z.number().int().safe().nonnegative(),
2551
+ runtime: z.object({
2552
+ status: z.enum([
2553
+ "active",
2554
+ "restore-failed",
2555
+ "dispose-failed"
2556
+ ]),
2557
+ message: z.string().optional(),
2558
+ observedAt: z.number().int().safe().nonnegative()
2559
+ }).optional(),
2560
+ /** Latest connection attempt of each MCP server this Activation declares. */
2561
+ mcpServers: z.array(z.object({
2562
+ name: z.string(),
2563
+ state: z.enum([
2564
+ "connecting",
2565
+ "connected",
2566
+ "unavailable",
2567
+ "missing-credentials"
2568
+ ]),
2569
+ toolCount: z.number().int().nonnegative().optional(),
2570
+ missing: z.array(z.string()).optional(),
2571
+ message: z.string().optional(),
2572
+ observedAt: z.number().int().safe().nonnegative()
2573
+ }).strict()).optional()
2574
+ }).strict()),
2575
+ installation: z.object({
2576
+ extensionRevisionId: ExtensionRevisionIdSchema,
2577
+ installedAt: z.number().int().safe().nonnegative(),
2578
+ config: JsonValueSchema.default({}),
2579
+ runtime: z.object({
2580
+ status: z.enum([
2581
+ "active",
2582
+ "restore-failed",
2583
+ "dispose-failed"
2584
+ ]),
2585
+ message: z.string().optional(),
2586
+ observedAt: z.number().int().safe().nonnegative()
2587
+ }).optional()
2588
+ }).strict().optional(),
2589
+ hostUiPermission: z.object({
2590
+ declaration: HostUiPermissionDeclarationSchema,
2591
+ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u),
2592
+ approvalRequired: z.boolean()
2593
+ }).strict().optional(),
2594
+ hostClientDiagnostic: z.object({
2595
+ revisionId: ExtensionRevisionIdSchema,
2596
+ status: z.enum(["loaded", "failed"]),
2597
+ message: z.string().optional(),
2598
+ observedAt: z.number().int().safe().nonnegative()
2599
+ }).strict().optional(),
2600
+ clientDiagnostics: z.array(z.object({
2601
+ agentId: AgentIdSchema,
2602
+ revisionId: ExtensionRevisionIdSchema,
2603
+ status: z.enum(["loaded", "failed"]),
2604
+ message: z.string().optional(),
2605
+ observedAt: z.number().int().nonnegative()
2606
+ }).strict())
2607
+ }).strict()),
2608
+ hostUi: z.object({
2609
+ preferencesRevision: z.number().int().nonnegative(),
2610
+ pages: z.array(HostUiPageEntrySchema)
2611
+ }).strict().default({
2612
+ preferencesRevision: 0,
2613
+ pages: []
2614
+ }),
2615
+ dynamic: z.array(z.object({
2616
+ agentId: AgentIdSchema,
2617
+ episodeId: EpisodeIdSchema,
2618
+ pluginId: DynamicIdSchema,
2619
+ packageId: DynamicIdSchema.optional(),
2620
+ currentPackageId: DynamicIdSchema.optional(),
2621
+ nextPackageId: DynamicIdSchema.optional(),
2622
+ approvalRequestId: DynamicIdSchema.optional(),
2623
+ status: DynamicAttemptStatusSchema,
2624
+ activeRun: z.object({
2625
+ pluginRunId: DynamicIdSchema,
2626
+ packageId: DynamicIdSchema
2627
+ }).strict().optional(),
2628
+ latestRun: DynamicLatestRunSchema.optional(),
2629
+ packages: z.array(z.object({
2630
+ packageId: DynamicIdSchema,
2631
+ name: z.string(),
2632
+ purpose: z.string(),
2633
+ hasHostHalf: z.boolean(),
2634
+ hasClientHalf: z.boolean()
2635
+ }).strict()),
2636
+ policy: z.object({
2637
+ turn: z.number().int().nonnegative(),
2638
+ primaryPluginId: DynamicIdSchema.optional(),
2639
+ consecutiveFailures: z.number().int().nonnegative(),
2640
+ repeatedFingerprintCount: z.number().int().nonnegative(),
2641
+ lastErrorFingerprint: z.string().optional(),
2642
+ blockedReason: z.string().optional()
2643
+ }).strict()
2644
+ }).strict()),
2645
+ authoringTasks: z.array(AuthoringTaskSummarySchema).default([]),
2646
+ scheduledTasks: z.array(ScheduledTaskSchema).default([])
2647
+ }).strict();
2648
+ const MessageInputPartSchema = z.discriminatedUnion("type", [z.object({
2649
+ type: z.literal("text"),
2650
+ text: z.string().trim().min(1)
2651
+ }).strict(), z.object({
2652
+ type: z.literal("mention"),
2653
+ memberId: ChannelMemberIdSchema
2654
+ }).strict()]);
2655
+ const SendChannelMessageRequestSchema = z.object({
2656
+ parts: z.array(MessageInputPartSchema).min(1),
2657
+ clientEventId: NonEmptyStringSchema.optional(),
2658
+ senderMemberId: ChannelMemberIdSchema.optional()
2659
+ }).strict().refine((body) => body.parts.every((part) => part.type !== "text" || [...part.text].length <= 64 * 1024), "Message text must not exceed 64 KiB.");
2660
+ const DynamicErrorDetailsSchema = z.object({
2661
+ message: z.string(),
2662
+ stack: z.string().optional()
2663
+ }).strict();
2664
+ const DynamicRenderFailureSchema = z.object({
2665
+ slot: NonEmptyStringSchema,
2666
+ message: z.string(),
2667
+ stack: z.string().optional(),
2668
+ abdicated: z.boolean()
2669
+ }).strict();
2670
+ const DynamicRunResolutionSchema = z.discriminatedUnion("ok", [z.object({
2671
+ ok: z.literal(true),
2672
+ pluginRunId: DynamicIdSchema,
2673
+ waitingFor: z.array(z.string()).optional()
2674
+ }).strict(), z.object({
2675
+ ok: z.literal(false),
2676
+ reason: z.enum([
2677
+ "rejected",
2678
+ "host-half-failed",
2679
+ "client-half-failed"
2680
+ ]),
2681
+ pluginRunId: DynamicIdSchema.optional(),
2682
+ startedHere: z.boolean().optional(),
2683
+ message: z.string().optional(),
2684
+ stack: z.string().optional()
2685
+ }).strict()]);
2686
+ const DynamicRunResponseSchema = z.discriminatedUnion("ok", [z.object({
2687
+ ok: z.literal(true),
2688
+ status: z.enum([
2689
+ "awaiting-approval",
2690
+ "starting",
2691
+ "running"
2692
+ ]),
2693
+ pluginId: DynamicIdSchema,
2694
+ packageId: DynamicIdSchema,
2695
+ pluginRunId: DynamicIdSchema,
2696
+ waitingFor: z.array(z.string()),
2697
+ clientWaitingFor: z.array(z.string()).optional(),
2698
+ currentPackageId: DynamicIdSchema.optional(),
2699
+ nextPackageId: DynamicIdSchema.optional(),
2700
+ mode: z.enum(["run", "update"])
2701
+ }).strict(), z.object({
2702
+ ok: z.literal(false),
2703
+ reason: z.enum([
2704
+ "plugin-missing",
2705
+ "package-missing",
2706
+ "invalid-mode",
2707
+ "transition-in-flight",
2708
+ "host-half-failed",
2709
+ "client-half-failed",
2710
+ "rejected",
2711
+ "cancelled",
2712
+ "not-running"
2713
+ ]),
2714
+ message: z.string(),
2715
+ stack: z.string().optional()
2716
+ }).strict()]);
2717
+ const DynamicInventoryRowSchema = z.object({
2718
+ pluginId: DynamicIdSchema,
2719
+ agentId: NonEmptyStringSchema,
2720
+ packages: z.array(z.object({
2721
+ packageId: DynamicIdSchema,
2722
+ name: z.string(),
2723
+ purpose: z.string(),
2724
+ hasHostHalf: z.boolean(),
2725
+ hasClientHalf: z.boolean()
2726
+ }).strict()),
2727
+ currentPackageId: DynamicIdSchema.optional(),
2728
+ nextPackageId: DynamicIdSchema.optional(),
2729
+ activeRun: z.object({
2730
+ pluginRunId: DynamicIdSchema,
2731
+ packageId: DynamicIdSchema
2732
+ }).strict().optional(),
2733
+ latestRun: DynamicLatestRunSchema.optional()
2734
+ }).strict();
2735
+ const DshPluginCatalogEntrySchema = z.object({
2736
+ packageName: NonEmptyStringSchema,
2737
+ packageVersion: NonEmptyStringSchema,
2738
+ origin: z.enum([
2739
+ "builtin",
2740
+ "profile",
2741
+ "dynamic",
2742
+ "installed"
2743
+ ]),
2744
+ settingsNamespaces: z.array(NonEmptyStringSchema),
2745
+ loadError: z.object({
2746
+ code: NonEmptyStringSchema,
2747
+ message: NonEmptyStringSchema
2748
+ }).strict().optional(),
2749
+ packageId: DshPluginPackageIdSchema.optional(),
2750
+ installSource: z.enum([
2751
+ "registry",
2752
+ "tarball",
2753
+ "imported"
2754
+ ]).optional(),
2755
+ installedAt: z.number().int().safe().nonnegative().optional(),
2756
+ clientUiDetected: z.boolean().optional(),
2757
+ hostUi: DshNxtHostUiSchema.optional(),
2758
+ approvedBuilds: z.array(NonEmptyStringSchema).optional(),
2759
+ entries: z.array(z.object({
2760
+ id: DshPluginEntryIdSchema,
2761
+ entryKey: NonEmptyStringSchema,
2762
+ moduleName: NonEmptyStringSchema,
2763
+ suggestedScope: z.enum(["host", "agent"]),
2764
+ selectedScope: z.enum(["host", "agent"]).optional(),
2765
+ config: JsonValueSchema,
2766
+ activations: z.array(z.object({
2767
+ targetKey: NonEmptyStringSchema,
2768
+ target: z.enum(["host", "agent"]),
2769
+ agentId: AgentIdSchema.optional(),
2770
+ activatedAt: z.number().int().safe().nonnegative(),
2771
+ diagnostic: z.object({
2772
+ status: z.enum([
2773
+ "active",
2774
+ "load-failed",
2775
+ "restore-failed",
2776
+ "dispose-failed"
2777
+ ]),
2778
+ phase: z.enum([
2779
+ "import",
2780
+ "apply",
2781
+ "update",
2782
+ "dispose",
2783
+ "restore"
2784
+ ]),
2785
+ message: z.string().optional(),
2786
+ observedAt: z.number().int().safe().nonnegative()
2787
+ }).optional()
2788
+ }).strict())
2789
+ }).strict()).optional()
2790
+ }).strict();
2791
+ const DshSettingsNamespaceSchema = z.object({
2792
+ ns: NonEmptyStringSchema,
2793
+ schema: JsonValueSchema,
2794
+ resolved: JsonValueSchema,
2795
+ base: JsonValueSchema.optional(),
2796
+ user: JsonValueSchema.optional(),
2797
+ applies: z.enum(["live", "restart"]),
2798
+ secrets: z.array(z.object({
2799
+ path: z.array(z.string()),
2800
+ set: z.boolean()
2801
+ }).strict()),
2802
+ revision: z.number().int().nonnegative(),
2803
+ writable: z.boolean(),
2804
+ owner: z.object({
2805
+ packageName: NonEmptyStringSchema,
2806
+ packageVersion: NonEmptyStringSchema
2807
+ }).strict().optional()
2808
+ }).strict();
2809
+ const DshSettingsPathSchema = z.array(z.string().min(1).max(200)).min(1).max(32);
2810
+ const DshSettingsPathOperationSchema = z.discriminatedUnion("op", [z.object({
2811
+ op: z.literal("set"),
2812
+ path: DshSettingsPathSchema,
2813
+ value: JsonValueSchema
2814
+ }).strict(), z.object({
2815
+ op: z.literal("unset"),
2816
+ path: DshSettingsPathSchema
2817
+ }).strict()]);
2818
+ const DshSettingsMutationRequestSchema = z.object({
2819
+ expectedRevision: z.number().int().nonnegative(),
2820
+ ops: z.array(DshSettingsPathOperationSchema).min(1).max(128)
2821
+ }).strict();
2822
+ const DshCredentialRefSchema = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/u).max(200);
2823
+ const DshCredentialViewSchema = z.object({
2824
+ configured: z.boolean(),
2825
+ source: z.string().optional(),
2826
+ writable: z.boolean()
2827
+ }).strict();
2828
+ const DshSettingsChangedSseDataSchema = z.object({
2829
+ namespace: NonEmptyStringSchema,
2830
+ revision: z.number().int().nonnegative()
2831
+ }).strict();
2832
+ const DshCredentialsChangedSseDataSchema = z.object({ ref: DshCredentialRefSchema }).strict();
2833
+ const DynamicChangedSseDataSchema = z.object({ agentId: AgentIdSchema }).strict();
2834
+ const HostSseStatusDataSchema = z.object({
2835
+ ok: z.boolean(),
2836
+ message: z.string(),
2837
+ replay: z.enum([
2838
+ "none",
2839
+ "complete",
2840
+ "expired"
2841
+ ]).optional()
2842
+ }).strict();
2843
+ const DshPluginOperationSseDataSchema = z.object({
2844
+ operationId: z.string().uuid(),
2845
+ kind: z.enum(["inspect", "install"]),
2846
+ phase: z.enum([
2847
+ "download",
2848
+ "dependencies",
2849
+ "build-scripts",
2850
+ "validation",
2851
+ "publish"
2852
+ ]),
2853
+ status: z.enum([
2854
+ "running",
2855
+ "done",
2856
+ "failed"
2857
+ ]),
2858
+ message: z.string()
2859
+ }).strict();
2860
+ const HostSseEventSchema = z.discriminatedUnion("event", [
2861
+ z.object({
2862
+ event: z.literal("snapshot-changed"),
2863
+ data: z.object({ changed: z.literal(true) }).strict()
2864
+ }).strict(),
2865
+ z.object({
2866
+ event: z.literal("channel-fact"),
2867
+ data: ChannelFactSseDataSchema
2868
+ }).strict(),
2869
+ z.object({
2870
+ event: z.literal("connection-fact"),
2871
+ data: HostConnectionEventSchema
2872
+ }).strict(),
2873
+ z.object({
2874
+ event: z.literal("runtime"),
2875
+ data: ChannelRuntimeSseDataSchema
2876
+ }).strict(),
2877
+ z.object({
2878
+ event: z.literal("extensions-changed"),
2879
+ data: z.object({ changed: z.literal(true) }).strict()
2880
+ }).strict(),
2881
+ z.object({
2882
+ event: z.literal("dsh-plugins-changed"),
2883
+ data: z.object({ changed: z.literal(true) }).strict()
2884
+ }).strict(),
2885
+ z.object({
2886
+ event: z.literal("dsh-plugin-operation"),
2887
+ data: DshPluginOperationSseDataSchema
2888
+ }).strict(),
2889
+ z.object({
2890
+ event: z.literal("dynamic-changed"),
2891
+ data: DynamicChangedSseDataSchema
2892
+ }).strict(),
2893
+ z.object({
2894
+ event: z.literal("dsh-settings-changed"),
2895
+ data: DshSettingsChangedSseDataSchema
2896
+ }).strict(),
2897
+ z.object({
2898
+ event: z.literal("dsh-credentials-changed"),
2899
+ data: DshCredentialsChangedSseDataSchema
2900
+ }).strict(),
2901
+ z.object({
2902
+ event: z.literal("status"),
2903
+ data: HostSseStatusDataSchema
2904
+ }).strict(),
2905
+ z.object({
2906
+ event: z.literal("attention-changed"),
2907
+ data: z.object({ revision: z.string().min(1) }).strict()
2908
+ }).strict(),
2909
+ z.object({
2910
+ event: z.literal("binding-change"),
2911
+ data: z.object({
2912
+ operationId: NonEmptyStringSchema,
2913
+ channelId: ChannelIdSchema,
2914
+ kind: z.enum([
2915
+ "bind",
2916
+ "replace",
2917
+ "clear"
2918
+ ]),
2919
+ step: NonEmptyStringSchema,
2920
+ status: z.enum([
2921
+ "running",
2922
+ "skipped",
2923
+ "done",
2924
+ "failed"
2925
+ ]),
2926
+ message: z.string()
2927
+ }).strict()
2928
+ }).strict()
2929
+ ]);
2930
+ /** Request content a model accepts; `image` enables native vision for agents using the model. */
2931
+ const LlmModelInputModalitiesSchema = z.array(z.enum(["text", "image"])).min(1);
2932
+ const LlmProviderModelSchema = z.object({
2933
+ id: NonEmptyStringSchema,
2934
+ name: NonEmptyStringSchema,
2935
+ contextWindow: z.number().int().positive().optional(),
2936
+ maxTokens: z.number().int().positive().optional(),
2937
+ inputModalities: LlmModelInputModalitiesSchema.optional()
2938
+ }).strict();
2939
+ const LlmDiscoveredModelSchema = z.object({
2940
+ id: NonEmptyStringSchema,
2941
+ name: NonEmptyStringSchema.optional(),
2942
+ contextWindow: z.number().int().positive().optional(),
2943
+ maxTokens: z.number().int().positive().optional(),
2944
+ inputModalities: LlmModelInputModalitiesSchema.optional()
2945
+ }).strict();
2946
+ const LlmProviderCredentialSchema = z.object({
2947
+ configured: z.boolean(),
2948
+ source: z.string().optional(),
2949
+ writable: z.boolean()
2950
+ }).strict();
2951
+ const LlmProviderViewSchema = z.object({
2952
+ provider: NonEmptyStringSchema,
2953
+ displayName: z.string(),
2954
+ settingsNs: NonEmptyStringSchema,
2955
+ settingsPath: z.array(NonEmptyStringSchema),
2956
+ settingsRevision: z.number().int().nonnegative(),
2957
+ declared: z.boolean(),
2958
+ active: z.boolean(),
2959
+ configured: z.boolean(),
2960
+ baseURL: z.string().optional(),
2961
+ api: NonEmptyStringSchema.optional(),
2962
+ credential: LlmProviderCredentialSchema.optional(),
2963
+ models: z.array(LlmProviderModelSchema),
2964
+ /** The model list was edited on this host; built-in providers can restore their own catalog. */
2965
+ modelsCustomized: z.boolean(),
2966
+ /** The provider's adapter can list the models its endpoint offers. */
2967
+ discoverable: z.boolean()
2968
+ }).strict();
2969
+ const LlmProviderSettingsSchema = z.object({
2970
+ writable: z.boolean(),
2971
+ protocols: z.array(NonEmptyStringSchema),
2972
+ providers: z.array(LlmProviderViewSchema)
2973
+ }).strict();
2974
+ const ConnectionTestResultSchema = z.discriminatedUnion("status", [
2975
+ z.object({
2976
+ status: z.literal("received"),
2977
+ channelId: ChannelIdSchema,
2978
+ platformMessageId: NonEmptyStringSchema
2979
+ }).strict(),
2980
+ z.object({
2981
+ status: z.literal("sent"),
2982
+ channelId: ChannelIdSchema,
2983
+ platformMessageId: NonEmptyStringSchema.optional()
2984
+ }).strict(),
2985
+ z.object({
2986
+ status: z.enum([
2987
+ "waiting-for-message",
2988
+ "needs-channel",
2989
+ "needs-target",
2990
+ "not-connected"
2991
+ ]),
2992
+ message: z.string()
2993
+ }).strict(),
2994
+ z.object({
2995
+ status: z.literal("failed"),
2996
+ kind: NonEmptyStringSchema,
2997
+ message: z.string(),
2998
+ retryAfterMs: z.number().int().nonnegative().optional()
2999
+ }).strict()
3000
+ ]);
3001
+ /** 扩展包导入检查的结果:本地文件与社区下载共用同一确认步骤。 */
3002
+ const ExtensionImportInspectionSchema = z.object({
3003
+ token: NonEmptyStringSchema,
3004
+ extensionId: ExtensionIdSchema,
3005
+ revisionId: ExtensionRevisionIdSchema,
3006
+ slug: NonEmptyStringSchema,
3007
+ displayName: NonEmptyStringSchema,
3008
+ scope: z.enum([
3009
+ "agent",
3010
+ "host-adapter",
3011
+ "host-ui"
3012
+ ]),
3013
+ idempotent: z.boolean(),
3014
+ slugConflict: z.boolean()
3015
+ }).strict();
3016
+ const defineContract = (contract) => ({
3017
+ ...contract,
3018
+ parseParams: (input) => contract.params.parse(input),
3019
+ parseRequest: (input) => contract.request.parse(input),
3020
+ parseResponse: (input) => contract.response.parse(input),
3021
+ parseError: (input) => contract.error.parse(input)
3022
+ });
3023
+ const agentParam = z.object({ agentId: AgentIdSchema }).strict();
3024
+ const agentRevisionParam = z.object({
3025
+ agentId: AgentIdSchema,
3026
+ revisionId: AgentRevisionIdSchema
3027
+ }).strict();
3028
+ const AgentRevisionChangedFieldSchema = z.enum([
3029
+ "name",
3030
+ "persona",
3031
+ "model",
3032
+ "capabilities",
3033
+ "imagePolicy",
3034
+ "approvalPolicy"
3035
+ ]);
3036
+ const AgentRevisionHistorySchema = z.object({
3037
+ agentId: AgentIdSchema,
3038
+ currentRevisionId: AgentRevisionIdSchema,
3039
+ /** Newest first. `changedFields` compares each Revision with the one numbered just before it. */
3040
+ revisions: z.array(z.object({
3041
+ id: AgentRevisionIdSchema,
3042
+ revision: z.number().int().positive(),
3043
+ createdAt: z.number().int().nonnegative(),
3044
+ displayName: z.string(),
3045
+ model: z.object({
3046
+ provider: z.string(),
3047
+ model: z.string()
3048
+ }).strict(),
3049
+ changedFields: z.array(AgentRevisionChangedFieldSchema),
3050
+ current: z.boolean()
3051
+ }).strict())
3052
+ }).strict();
3053
+ const channelParam = z.object({ channelId: ChannelIdSchema }).strict();
3054
+ const connectionParam = z.object({ connectionId: ConnectionIdSchema }).strict();
3055
+ const agentExtensionParam = z.object({
3056
+ agentId: AgentIdSchema,
3057
+ extensionId: ExtensionIdSchema
3058
+ }).strict();
3059
+ const extensionParam = z.object({ extensionId: ExtensionIdSchema }).strict();
3060
+ const dshPluginPackageParam = z.object({ packageId: DshPluginPackageIdSchema }).strict();
3061
+ const dshPluginEntryParam = z.object({ entryId: DshPluginEntryIdSchema }).strict();
3062
+ const extensionRevisionParam = z.object({
3063
+ extensionId: ExtensionIdSchema,
3064
+ revisionId: ExtensionRevisionIdSchema
3065
+ }).strict();
3066
+ const dshSettingsParam = z.object({ namespace: NonEmptyStringSchema }).strict();
3067
+ const dshCredentialParam = z.object({ ref: DshCredentialRefSchema }).strict();
3068
+ const llmProviderParam = z.object({ provider: NonEmptyStringSchema }).strict();
3069
+ const authoringTaskParam = z.object({ taskId: AuthoringTaskIdSchema }).strict();
3070
+ const scheduledTaskParam = z.object({ taskId: ScheduledTaskIdSchema }).strict();
3071
+ const authoringAttemptParam = z.object({
3072
+ taskId: AuthoringTaskIdSchema,
3073
+ attemptId: AuthoringAttemptIdSchema
3074
+ }).strict();
3075
+ const DshPluginInstallInspectionSchema = z.object({
3076
+ token: NonEmptyStringSchema,
3077
+ operationId: z.string().uuid().optional(),
3078
+ packageName: NonEmptyStringSchema,
3079
+ packageVersion: NonEmptyStringSchema,
3080
+ packageDigest: z.string().regex(/^[a-f0-9]{64}$/u),
3081
+ lockfileDigest: z.string().regex(/^[a-f0-9]{64}$/u),
3082
+ blockedBuilds: z.array(NonEmptyStringSchema),
3083
+ clientUiDetected: z.boolean(),
3084
+ hostUi: DshNxtHostUiSchema.optional(),
3085
+ entries: z.array(z.object({
3086
+ entryKey: NonEmptyStringSchema,
3087
+ moduleName: NonEmptyStringSchema,
3088
+ suggestedScope: z.enum(["host", "agent"])
3089
+ }).strict())
3090
+ }).strict();
3091
+ const BinaryUploadRequestSchema = z.object({
3092
+ bytes: z.instanceof(Uint8Array),
3093
+ fileName: z.string().max(255).optional(),
3094
+ operationId: z.string().uuid().optional()
3095
+ }).strict();
3096
+ const encodeBinaryUpload = (input) => ({
3097
+ body: input.bytes,
3098
+ headers: {
3099
+ "content-type": "application/octet-stream",
3100
+ ...input.fileName === void 0 ? {} : { "x-file-name": input.fileName },
3101
+ ...input.operationId === void 0 ? {} : { "x-operation-id": input.operationId }
3102
+ }
3103
+ });
3104
+ const HostApiContracts = {
3105
+ retryRuntimeCompatibility: defineContract({
3106
+ method: "POST",
3107
+ path: "/api/runtime/compatibility/retry",
3108
+ params: EmptyParamsSchema,
3109
+ request: z.object({
3110
+ objectKind: RuntimeCompatibilityDiagnosticSchema.shape.objectKind,
3111
+ objectId: z.string().min(1)
3112
+ }).strict(),
3113
+ response: z.object({ diagnostics: z.array(RuntimeCompatibilityDiagnosticSchema) }).strict(),
3114
+ error: HostApiErrorSchema,
3115
+ invalidatesSnapshot: true
3116
+ }),
3117
+ snapshot: defineContract({
3118
+ method: "GET",
3119
+ path: "/api/snapshot",
3120
+ params: EmptyParamsSchema,
3121
+ request: NoRequestBodySchema,
3122
+ response: HostSnapshotSchema,
3123
+ error: HostApiErrorSchema
3124
+ }),
3125
+ getAuthoringTask: defineContract({
3126
+ method: "GET",
3127
+ path: "/api/authoring/tasks/:taskId",
3128
+ params: authoringTaskParam,
3129
+ request: NoRequestBodySchema,
3130
+ response: z.object({
3131
+ task: AuthoringTaskSummarySchema,
3132
+ attempts: z.array(AuthoringAttemptSummarySchema),
3133
+ /** Secret fields of the latest candidate and which have a test value for this task's dynamic runs. */
3134
+ testSecrets: z.object({
3135
+ fields: z.array(z.object({
3136
+ key: z.string(),
3137
+ title: z.string()
3138
+ }).strict()),
3139
+ configured: z.array(z.string())
3140
+ }).strict().optional(),
3141
+ events: z.array(z.object({
3142
+ sequence: z.number().int().positive(),
3143
+ kind: z.string(),
3144
+ attemptId: AuthoringAttemptIdSchema.optional(),
3145
+ payload: JsonValueSchema,
3146
+ createdAt: z.number().int().nonnegative()
3147
+ }).strict())
3148
+ }).strict(),
3149
+ error: HostApiErrorSchema
3150
+ }),
3151
+ decideAuthoringAttempt: defineContract({
3152
+ invalidatesSnapshot: true,
3153
+ method: "POST",
3154
+ path: "/api/authoring/tasks/:taskId/attempts/:attemptId/decision",
3155
+ params: authoringAttemptParam,
3156
+ request: z.object({
3157
+ expectedRevision: z.number().int().positive(),
3158
+ approved: z.boolean(),
3159
+ approveRiskStable: z.boolean()
3160
+ }).strict(),
3161
+ response: z.object({
3162
+ accepted: z.boolean(),
3163
+ taskRevision: z.number().int().positive(),
3164
+ executionRequired: z.boolean()
3165
+ }).strict(),
3166
+ error: HostApiErrorSchema
3167
+ }),
3168
+ restoreAuthoringAttempt: defineContract({
3169
+ invalidatesSnapshot: true,
3170
+ method: "POST",
3171
+ path: "/api/authoring/tasks/:taskId/attempts/:attemptId/restore",
3172
+ params: authoringAttemptParam,
3173
+ request: z.object({ expectedRevision: z.number().int().positive() }).strict(),
3174
+ response: AuthoringTaskSummarySchema,
3175
+ error: HostApiErrorSchema
3176
+ }),
3177
+ stopAuthoringTask: defineContract({
3178
+ invalidatesSnapshot: true,
3179
+ method: "POST",
3180
+ path: "/api/authoring/tasks/:taskId/stop",
3181
+ params: authoringTaskParam,
3182
+ request: z.object({ expectedRevision: z.number().int().positive() }).strict(),
3183
+ response: AuthoringTaskSummarySchema,
3184
+ error: HostApiErrorSchema
3185
+ }),
3186
+ setAuthoringTestSecrets: defineContract({
3187
+ method: "PUT",
3188
+ path: "/api/authoring/tasks/:taskId/test-secrets",
3189
+ params: authoringTaskParam,
3190
+ request: z.object({ secrets: z.record(z.string(), z.string().max(8192)) }).strict(),
3191
+ response: z.object({ configured: z.array(z.string()) }).strict(),
3192
+ error: HostApiErrorSchema
3193
+ }),
3194
+ deleteAuthoringTask: defineContract({
3195
+ invalidatesSnapshot: true,
3196
+ method: "DELETE",
3197
+ path: "/api/authoring/tasks/:taskId",
3198
+ params: authoringTaskParam,
3199
+ request: NoRequestBodySchema,
3200
+ response: z.object({ deleted: z.literal(true) }).strict(),
3201
+ error: HostApiErrorSchema
3202
+ }),
3203
+ pauseScheduledTask: defineContract({
3204
+ invalidatesSnapshot: true,
3205
+ method: "POST",
3206
+ path: "/api/scheduled-tasks/:taskId/pause",
3207
+ params: scheduledTaskParam,
3208
+ request: NoRequestBodySchema,
3209
+ response: ScheduledTaskSchema,
3210
+ error: HostApiErrorSchema
3211
+ }),
3212
+ resumeScheduledTask: defineContract({
3213
+ invalidatesSnapshot: true,
3214
+ method: "POST",
3215
+ path: "/api/scheduled-tasks/:taskId/resume",
3216
+ params: scheduledTaskParam,
3217
+ request: NoRequestBodySchema,
3218
+ response: ScheduledTaskSchema,
3219
+ error: HostApiErrorSchema
3220
+ }),
3221
+ runScheduledTask: defineContract({
3222
+ invalidatesSnapshot: true,
3223
+ method: "POST",
3224
+ path: "/api/scheduled-tasks/:taskId/run",
3225
+ params: scheduledTaskParam,
3226
+ request: NoRequestBodySchema,
3227
+ /** `woke: false` when the owning extension's due-job handler let this run pass without waking the agent. */
3228
+ response: z.object({
3229
+ task: ScheduledTaskSchema,
3230
+ woke: z.boolean()
3231
+ }).strict(),
3232
+ error: HostApiErrorSchema
3233
+ }),
3234
+ deleteScheduledTask: defineContract({
3235
+ invalidatesSnapshot: true,
3236
+ method: "DELETE",
3237
+ path: "/api/scheduled-tasks/:taskId",
3238
+ params: scheduledTaskParam,
3239
+ request: NoRequestBodySchema,
3240
+ response: z.object({ deleted: z.literal(true) }).strict(),
3241
+ error: HostApiErrorSchema
3242
+ }),
3243
+ listClientNotifications: defineContract({
3244
+ method: "GET",
3245
+ path: "/api/client-notifications",
3246
+ params: z.object({ cursor: z.number().int().nonnegative().optional() }).strict(),
3247
+ request: NoRequestBodySchema,
3248
+ response: ClientNotificationFeedResponseSchema,
3249
+ error: HostApiErrorSchema
3250
+ }),
3251
+ updateNotificationSettings: defineContract({
3252
+ invalidatesSnapshot: true,
3253
+ method: "PUT",
3254
+ path: "/api/settings/notifications",
3255
+ params: EmptyParamsSchema,
3256
+ request: UpdateNotificationSettingsRequestSchema,
3257
+ response: NotificationSettingsViewSchema,
3258
+ error: HostApiErrorSchema
3259
+ }),
3260
+ testBarkNotification: defineContract({
3261
+ method: "POST",
3262
+ path: "/api/settings/notifications/test",
3263
+ params: EmptyParamsSchema,
3264
+ request: TestBarkNotificationRequestSchema,
3265
+ response: z.object({ sent: z.literal(true) }).strict(),
3266
+ error: HostApiErrorSchema
3267
+ }),
3268
+ testSystemNotification: defineContract({
3269
+ method: "POST",
3270
+ path: "/api/settings/notifications/test-system",
3271
+ params: EmptyParamsSchema,
3272
+ request: NoRequestBodySchema,
3273
+ response: z.object({ published: z.literal(true) }).strict(),
3274
+ error: HostApiErrorSchema
3275
+ }),
3276
+ listPlatformUsers: defineContract({
3277
+ method: "GET",
3278
+ path: "/api/platform-users",
3279
+ params: z.object({
3280
+ query: z.string().trim().max(80).optional(),
3281
+ adapterKey: z.string().trim().min(1).max(120).optional(),
3282
+ connectionId: ConnectionIdSchema.optional(),
3283
+ cursor: PlatformIdentityIdSchema.optional(),
3284
+ limit: z.number().int().min(1).max(100).default(50)
3285
+ }).strict(),
3286
+ request: NoRequestBodySchema,
3287
+ response: PlatformUserListResponseSchema,
3288
+ error: HostApiErrorSchema
3289
+ }),
3290
+ listConnectionEvents: defineContract({
3291
+ method: "GET",
3292
+ path: "/api/connections/:connectionId/events",
3293
+ params: z.object({
3294
+ connectionId: ConnectionIdSchema,
3295
+ beforeReceivedAt: z.number().int().safe().nonnegative().optional(),
3296
+ beforeId: ConnectionEventIdSchema.optional(),
3297
+ limit: z.number().int().min(1).max(100).default(50)
3298
+ }).strict(),
3299
+ request: NoRequestBodySchema,
3300
+ response: z.object({
3301
+ events: z.array(HostConnectionEventSchema),
3302
+ hasMore: z.boolean()
3303
+ }).strict(),
3304
+ error: HostApiErrorSchema
3305
+ }),
3306
+ createAgent: defineContract({
3307
+ invalidatesSnapshot: true,
3308
+ method: "POST",
3309
+ path: "/api/agents",
3310
+ params: EmptyParamsSchema,
3311
+ request: CreateAgentRequestSchema,
3312
+ response: z.object({
3313
+ agentId: AgentIdSchema,
3314
+ channelId: ChannelIdSchema,
3315
+ connectionId: ConnectionIdSchema
3316
+ }).strict(),
3317
+ error: HostApiErrorSchema
3318
+ }),
3319
+ reviseAgent: defineContract({
3320
+ invalidatesSnapshot: true,
3321
+ method: "POST",
3322
+ path: "/api/agents/:agentId/revision",
3323
+ params: agentParam,
3324
+ request: ReviseAgentRequestSchema,
3325
+ response: z.object({ currentRevisionId: AgentRevisionIdSchema }).strict(),
3326
+ error: HostApiErrorSchema
3327
+ }),
3328
+ updateAgentCapabilities: defineContract({
3329
+ invalidatesSnapshot: true,
3330
+ method: "POST",
3331
+ path: "/api/agents/:agentId/capabilities",
3332
+ params: agentParam,
3333
+ request: UpdateAgentCapabilitiesRequestSchema,
3334
+ response: z.object({
3335
+ currentRevisionId: AgentRevisionIdSchema,
3336
+ capabilities: AgentCapabilitiesSchema
3337
+ }).strict(),
3338
+ error: HostApiErrorSchema
3339
+ }),
3340
+ deleteAgent: defineContract({
3341
+ invalidatesSnapshot: true,
3342
+ method: "DELETE",
3343
+ path: "/api/agents/:agentId",
3344
+ params: agentParam,
3345
+ request: z.object({
3346
+ expectedCurrentRevisionId: AgentRevisionIdSchema,
3347
+ confirmationName: z.string().min(1).max(80),
3348
+ deleteAutoCreatedBuiltInChannels: z.boolean().default(true),
3349
+ /** Also remove `workspaces/<agentId>/` (files, development shell output, creation candidates). */
3350
+ deleteWorkspace: z.boolean().default(false)
3351
+ }).strict(),
3352
+ response: z.object({
3353
+ agentId: AgentIdSchema,
3354
+ deleted: z.literal(true),
3355
+ unboundChannelIds: z.array(ChannelIdSchema),
3356
+ deletedChannelIds: z.array(ChannelIdSchema)
3357
+ }).strict(),
3358
+ error: HostApiErrorSchema
3359
+ }),
3360
+ createInternalChannel: defineContract({
3361
+ invalidatesSnapshot: true,
3362
+ method: "POST",
3363
+ path: "/api/channels",
3364
+ params: EmptyParamsSchema,
3365
+ request: z.object({ displayName: z.string().trim().min(1).max(120) }).strict(),
3366
+ response: z.object({
3367
+ channelId: ChannelIdSchema,
3368
+ connectionId: ConnectionIdSchema
3369
+ }).strict(),
3370
+ error: HostApiErrorSchema
3371
+ }),
3372
+ deleteChannel: defineContract({
3373
+ invalidatesSnapshot: true,
3374
+ method: "DELETE",
3375
+ path: "/api/channels/:channelId",
3376
+ params: channelParam,
3377
+ request: z.object({ expectedBoundAgentId: AgentIdSchema.nullable() }).strict(),
3378
+ response: z.object({
3379
+ channelId: ChannelIdSchema,
3380
+ deleted: z.literal(true)
3381
+ }).strict(),
3382
+ error: HostApiErrorSchema
3383
+ }),
3384
+ createBinding: defineContract({
3385
+ invalidatesSnapshot: true,
3386
+ method: "POST",
3387
+ path: "/api/bindings",
3388
+ params: EmptyParamsSchema,
3389
+ request: z.object({
3390
+ agentId: AgentIdSchema,
3391
+ channelId: ChannelIdSchema,
3392
+ triggerPolicy: TriggerPolicySchema,
3393
+ processingFeedback: z.enum(["auto", "off"]).optional(),
3394
+ activityTriggerOverrides: ActivityTriggerOverridesSchema.optional()
3395
+ }).strict(),
3396
+ response: z.object({
3397
+ channelId: ChannelIdSchema,
3398
+ agentId: AgentIdSchema,
3399
+ triggerPolicy: TriggerPolicySchema,
3400
+ processingFeedback: z.enum(["auto", "off"]).default("auto"),
3401
+ activityTriggerOverrides: ActivityTriggerOverridesSchema.default({}),
3402
+ boundAt: z.number().int().safe().nonnegative()
3403
+ }).strict(),
3404
+ error: HostApiErrorSchema
3405
+ }),
3406
+ clearBinding: defineContract({
3407
+ invalidatesSnapshot: true,
3408
+ method: "DELETE",
3409
+ path: "/api/bindings/:channelId",
3410
+ params: channelParam,
3411
+ request: NoRequestBodySchema,
3412
+ response: z.object({
3413
+ channelId: ChannelIdSchema,
3414
+ cleared: z.literal(true)
3415
+ }).strict(),
3416
+ error: HostApiErrorSchema
3417
+ }),
3418
+ putWorkTreeOrder: defineContract({
3419
+ invalidatesSnapshot: true,
3420
+ method: "PUT",
3421
+ path: "/api/work-tree-order",
3422
+ params: EmptyParamsSchema,
3423
+ request: WorkTreeOrderSchema,
3424
+ response: WorkTreeOrderSchema,
3425
+ error: HostApiErrorSchema
3426
+ }),
3427
+ listChannelMessages: defineContract({
3428
+ method: "GET",
3429
+ path: "/api/channels/:channelId/messages",
3430
+ params: z.object({
3431
+ channelId: ChannelIdSchema,
3432
+ limit: z.number().int().min(1).max(100),
3433
+ beforeOccurredAt: z.number().int().safe().nonnegative().optional(),
3434
+ beforeSourceId: NonEmptyStringSchema.optional()
3435
+ }).strict().refine((value) => value.beforeOccurredAt === void 0 === (value.beforeSourceId === void 0), "频道历史游标必须完整提供。"),
3436
+ request: NoRequestBodySchema,
3437
+ response: z.object({
3438
+ messages: z.array(HostSnapshotMessageSchema),
3439
+ hasMore: z.boolean(),
3440
+ cursor: HostSyncCursorSchema
3441
+ }).strict(),
3442
+ error: HostApiErrorSchema
3443
+ }),
3444
+ sendChannelMessage: defineContract({
3445
+ method: "POST",
3446
+ path: "/api/channels/:channelId/messages",
3447
+ params: channelParam,
3448
+ request: SendChannelMessageRequestSchema,
3449
+ response: z.object({
3450
+ inserted: z.boolean(),
3451
+ channelEventId: ChannelEventIdSchema.optional(),
3452
+ outboundIntentId: OutboundIntentIdSchema.optional()
3453
+ }).strict(),
3454
+ error: HostApiErrorSchema
3455
+ }),
3456
+ renameChannel: defineContract({
3457
+ invalidatesSnapshot: true,
3458
+ method: "POST",
3459
+ path: "/api/channels/:channelId/display-name",
3460
+ params: channelParam,
3461
+ request: z.object({ displayName: z.string().trim().min(1).max(120) }).strict(),
3462
+ response: z.object({
3463
+ channelId: ChannelIdSchema,
3464
+ displayName: z.string().trim().min(1).max(120)
3465
+ }).strict(),
3466
+ error: HostApiErrorSchema
3467
+ }),
3468
+ getChannelRuntime: defineContract({
3469
+ method: "GET",
3470
+ path: "/api/channels/:channelId/runtime",
3471
+ params: channelParam,
3472
+ request: NoRequestBodySchema,
3473
+ response: ChannelRuntimeProjectionSchema.extend({ cursor: HostSyncCursorSchema }),
3474
+ error: HostApiErrorSchema
3475
+ }),
3476
+ getChannelToolCall: defineContract({
3477
+ method: "GET",
3478
+ path: "/api/channels/:channelId/runtime/tools/:callId",
3479
+ params: z.object({
3480
+ channelId: ChannelIdSchema,
3481
+ callId: z.string().trim().min(1).max(200)
3482
+ }).strict(),
3483
+ request: NoRequestBodySchema,
3484
+ response: z.object({
3485
+ callId: z.string(),
3486
+ available: z.boolean(),
3487
+ name: z.string().optional(),
3488
+ input: z.string().optional(),
3489
+ result: z.string().optional(),
3490
+ inputTruncated: z.boolean(),
3491
+ resultTruncated: z.boolean()
3492
+ }).strict(),
3493
+ error: HostApiErrorSchema
3494
+ }),
3495
+ resetChannelContext: defineContract({
3496
+ invalidatesSnapshot: true,
3497
+ method: "POST",
3498
+ path: "/api/channels/:channelId/context-reset",
3499
+ params: channelParam,
3500
+ request: z.object({
3501
+ mode: z.enum(["clear", "compact"]),
3502
+ expectedEpisodeId: EpisodeIdSchema
3503
+ }).strict(),
3504
+ response: z.object({
3505
+ mode: z.enum(["clear", "compact"]),
3506
+ closedEpisodeId: EpisodeIdSchema,
3507
+ nextEpisodeId: EpisodeIdSchema.optional()
3508
+ }).strict(),
3509
+ error: HostApiErrorSchema
3510
+ }),
3511
+ createConnection: defineContract({
3512
+ invalidatesSnapshot: true,
3513
+ method: "POST",
3514
+ path: "/api/connections",
3515
+ params: EmptyParamsSchema,
3516
+ request: z.object({
3517
+ adapterKey: NonEmptyStringSchema,
3518
+ alias: ConnectionAliasInputSchema.optional(),
3519
+ configuration: z.record(z.string(), JsonValueSchema).default({}),
3520
+ credentials: z.record(z.string(), z.string().max(16 * 1024)).default({})
3521
+ }).strict(),
3522
+ response: z.object({
3523
+ connectionId: ConnectionIdSchema,
3524
+ adapterKey: NonEmptyStringSchema
3525
+ }).strict(),
3526
+ error: HostApiErrorSchema
3527
+ }),
3528
+ startConnectionLogin: defineContract({
3529
+ method: "POST",
3530
+ path: "/api/connection-logins",
3531
+ params: EmptyParamsSchema,
3532
+ request: z.object({
3533
+ adapterKey: NonEmptyStringSchema,
3534
+ alias: ConnectionAliasInputSchema.optional(),
3535
+ connectionId: ConnectionIdSchema.optional()
3536
+ }).strict(),
3537
+ response: z.object({
3538
+ loginId: NonEmptyStringSchema,
3539
+ adapterKey: NonEmptyStringSchema,
3540
+ status: z.enum([
3541
+ "pending",
3542
+ "scanned",
3543
+ "confirmed",
3544
+ "expired",
3545
+ "failed",
3546
+ "cancelled"
3547
+ ]),
3548
+ qrCodeUrl: NonEmptyStringSchema,
3549
+ message: z.string().optional()
3550
+ }).strict(),
3551
+ error: HostApiErrorSchema
3552
+ }),
3553
+ getConnectionLogin: defineContract({
3554
+ method: "GET",
3555
+ path: "/api/connection-logins/:loginId",
3556
+ params: z.object({ loginId: NonEmptyStringSchema }).strict(),
3557
+ request: NoRequestBodySchema,
3558
+ response: z.object({
3559
+ loginId: NonEmptyStringSchema,
3560
+ status: z.enum([
3561
+ "pending",
3562
+ "scanned",
3563
+ "confirmed",
3564
+ "expired",
3565
+ "failed",
3566
+ "cancelled"
3567
+ ]),
3568
+ qrCodeUrl: NonEmptyStringSchema.optional(),
3569
+ connectionId: ConnectionIdSchema.optional(),
3570
+ adapterKey: NonEmptyStringSchema,
3571
+ message: z.string().optional()
3572
+ }).strict(),
3573
+ error: HostApiErrorSchema
3574
+ }),
3575
+ cancelConnectionLogin: defineContract({
3576
+ method: "DELETE",
3577
+ path: "/api/connection-logins/:loginId",
3578
+ params: z.object({ loginId: NonEmptyStringSchema }).strict(),
3579
+ request: NoRequestBodySchema,
3580
+ response: z.object({
3581
+ loginId: NonEmptyStringSchema,
3582
+ status: z.literal("cancelled")
3583
+ }).strict(),
3584
+ error: HostApiErrorSchema
3585
+ }),
3586
+ updateConnectionAlias: defineContract({
3587
+ invalidatesSnapshot: true,
3588
+ method: "POST",
3589
+ path: "/api/connections/:connectionId/alias",
3590
+ params: connectionParam,
3591
+ request: z.object({ alias: z.string().trim().max(80) }).strict(),
3592
+ response: z.object({
3593
+ connectionId: ConnectionIdSchema,
3594
+ alias: ConnectionAliasOutputSchema.optional()
3595
+ }).strict(),
3596
+ error: HostApiErrorSchema
3597
+ }),
3598
+ updateConnectionActivityTriggerDefaults: defineContract({
3599
+ invalidatesSnapshot: true,
3600
+ method: "POST",
3601
+ path: "/api/connections/:connectionId/activity-trigger-defaults",
3602
+ params: connectionParam,
3603
+ request: z.object({ activityKeys: z.array(AdapterActivityKeySchema) }).strict(),
3604
+ response: z.object({
3605
+ connectionId: ConnectionIdSchema,
3606
+ activityKeys: z.array(AdapterActivityKeySchema)
3607
+ }).strict(),
3608
+ error: HostApiErrorSchema
3609
+ }),
3610
+ updateConnectionConfiguration: defineContract({
3611
+ invalidatesSnapshot: true,
3612
+ method: "POST",
3613
+ path: "/api/connections/:connectionId/configuration",
3614
+ params: connectionParam,
3615
+ request: z.object({ configuration: z.record(z.string(), z.union([
3616
+ z.string(),
3617
+ z.number(),
3618
+ z.boolean()
3619
+ ])) }).strict(),
3620
+ response: z.object({
3621
+ connectionId: ConnectionIdSchema,
3622
+ configuration: z.record(z.string(), z.union([
3623
+ z.string(),
3624
+ z.number(),
3625
+ z.boolean()
3626
+ ]))
3627
+ }).strict(),
3628
+ error: HostApiErrorSchema
3629
+ }),
3630
+ deleteConnection: defineContract({
3631
+ invalidatesSnapshot: true,
3632
+ method: "DELETE",
3633
+ path: "/api/connections/:connectionId",
3634
+ params: connectionParam,
3635
+ request: z.object({ deleteChannelData: z.boolean() }).strict(),
3636
+ response: z.object({
3637
+ connectionId: ConnectionIdSchema,
3638
+ archived: z.boolean()
3639
+ }).strict(),
3640
+ error: HostApiErrorSchema
3641
+ }),
3642
+ restoreConnection: defineContract({
3643
+ invalidatesSnapshot: true,
3644
+ method: "POST",
3645
+ path: "/api/connections/:connectionId/restore",
3646
+ params: connectionParam,
3647
+ request: NoRequestBodySchema,
3648
+ response: z.object({
3649
+ connectionId: ConnectionIdSchema,
3650
+ restored: z.literal(true)
3651
+ }).strict(),
3652
+ error: HostApiErrorSchema
3653
+ }),
3654
+ dshPlugins: defineContract({
3655
+ method: "GET",
3656
+ path: "/api/dsh/plugins",
3657
+ params: EmptyParamsSchema,
3658
+ request: NoRequestBodySchema,
3659
+ response: z.object({ plugins: z.array(DshPluginCatalogEntrySchema) }).strict(),
3660
+ error: HostApiErrorSchema
3661
+ }),
3662
+ inspectDshPluginTarball: defineContract({
3663
+ method: "POST",
3664
+ timeoutMs: 3e5,
3665
+ path: "/api/dsh/plugin-installs/inspect-tarball",
3666
+ params: EmptyParamsSchema,
3667
+ request: BinaryUploadRequestSchema,
3668
+ encodeRequest: encodeBinaryUpload,
3669
+ response: DshPluginInstallInspectionSchema,
3670
+ error: HostApiErrorSchema
3671
+ }),
3672
+ exportExtensionRevision: defineContract({
3673
+ method: "GET",
3674
+ timeoutMs: 3e5,
3675
+ path: "/api/extensions/:extensionId/revisions/:revisionId/export",
3676
+ params: extensionRevisionParam,
3677
+ request: NoRequestBodySchema,
3678
+ responseFormat: "bytes",
3679
+ response: z.instanceof(Uint8Array),
3680
+ error: HostApiErrorSchema
3681
+ }),
3682
+ inspectDshPluginInstall: defineContract({
3683
+ timeoutMs: 3e5,
3684
+ method: "POST",
3685
+ path: "/api/dsh/plugin-installs/inspect",
3686
+ params: EmptyParamsSchema,
3687
+ request: z.object({
3688
+ spec: NonEmptyStringSchema.max(500),
3689
+ operationId: z.string().uuid().optional()
3690
+ }).strict(),
3691
+ response: DshPluginInstallInspectionSchema,
3692
+ error: HostApiErrorSchema
3693
+ }),
3694
+ commitDshPluginInstall: defineContract({
3695
+ invalidatesSnapshot: true,
3696
+ timeoutMs: 3e5,
3697
+ method: "POST",
3698
+ path: "/api/dsh/plugin-installs",
3699
+ params: EmptyParamsSchema,
3700
+ request: z.object({
3701
+ token: NonEmptyStringSchema,
3702
+ approvedBuilds: z.array(NonEmptyStringSchema).default([]),
3703
+ operationId: z.string().uuid().optional()
3704
+ }).strict(),
3705
+ response: z.object({
3706
+ packageId: DshPluginPackageIdSchema,
3707
+ operationId: z.string().uuid().optional()
3708
+ }).strict(),
3709
+ error: HostApiErrorSchema
3710
+ }),
3711
+ inspectDshPluginEntryConfig: defineContract({
3712
+ method: "POST",
3713
+ path: "/api/dsh/plugin-entries/:entryId/config/inspect",
3714
+ params: dshPluginEntryParam,
3715
+ request: NoRequestBodySchema,
3716
+ response: z.discriminatedUnion("mode", [
3717
+ z.object({
3718
+ mode: z.literal("schema"),
3719
+ schema: JsonValueSchema
3720
+ }).strict(),
3721
+ z.object({ mode: z.literal("json") }).strict(),
3722
+ z.object({
3723
+ mode: z.literal("incompatible"),
3724
+ reason: NonEmptyStringSchema
3725
+ }).strict()
3726
+ ]),
3727
+ error: HostApiErrorSchema
3728
+ }),
3729
+ activateDshPluginEntry: defineContract({
3730
+ method: "PUT",
3731
+ path: "/api/dsh/plugin-entries/:entryId/activation",
3732
+ params: dshPluginEntryParam,
3733
+ request: z.object({
3734
+ target: z.enum(["host", "agent"]),
3735
+ agentId: AgentIdSchema.optional(),
3736
+ config: JsonValueSchema,
3737
+ permissionApproval: z.object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) }).strict().optional()
3738
+ }).strict(),
3739
+ response: z.object({ targetKey: NonEmptyStringSchema }).strict(),
3740
+ error: HostApiErrorSchema
3741
+ }),
3742
+ deactivateDshPluginEntry: defineContract({
3743
+ method: "DELETE",
3744
+ path: "/api/dsh/plugin-entries/:entryId/activation",
3745
+ params: dshPluginEntryParam,
3746
+ request: z.object({ targetKey: NonEmptyStringSchema }).strict(),
3747
+ response: z.object({ disabled: z.literal(true) }).strict(),
3748
+ error: HostApiErrorSchema
3749
+ }),
3750
+ removeDshPluginPackage: defineContract({
3751
+ invalidatesSnapshot: true,
3752
+ method: "DELETE",
3753
+ path: "/api/dsh/plugin-installs/:packageId",
3754
+ params: dshPluginPackageParam,
3755
+ request: NoRequestBodySchema,
3756
+ response: z.object({ removed: z.literal(true) }).strict(),
3757
+ error: HostApiErrorSchema
3758
+ }),
3759
+ inspectExtensionImport: defineContract({
3760
+ timeoutMs: 3e5,
3761
+ method: "POST",
3762
+ path: "/api/extensions/imports/inspect",
3763
+ params: EmptyParamsSchema,
3764
+ request: BinaryUploadRequestSchema,
3765
+ encodeRequest: encodeBinaryUpload,
3766
+ response: ExtensionImportInspectionSchema,
3767
+ error: HostApiErrorSchema
3768
+ }),
3769
+ /**
3770
+ * Management-edge endpoints: they exist only when the Server is reached through its management edge (a management
3771
+ * key is set); clients tell that from the edge's CSRF cookie.
3772
+ */
3773
+ listManagementDevices: defineContract({
3774
+ method: "GET",
3775
+ path: "/api/management/devices",
3776
+ params: EmptyParamsSchema,
3777
+ request: NoRequestBodySchema,
3778
+ response: z.object({ devices: z.array(ManagementDeviceViewSchema) }).strict(),
3779
+ error: HostApiErrorSchema
3780
+ }),
3781
+ revokeManagementDevice: defineContract({
3782
+ method: "DELETE",
3783
+ path: "/api/management/devices/:deviceId",
3784
+ params: z.object({ deviceId: ManagementDeviceIdSchema }).strict(),
3785
+ request: NoRequestBodySchema,
3786
+ response: z.object({ revoked: z.boolean() }).strict(),
3787
+ error: HostApiErrorSchema
3788
+ }),
3789
+ managementLogout: defineContract({
3790
+ method: "DELETE",
3791
+ path: "/api/management/session",
3792
+ params: EmptyParamsSchema,
3793
+ request: NoRequestBodySchema,
3794
+ response: z.object({ authenticated: z.literal(false) }).strict(),
3795
+ error: HostApiErrorSchema
3796
+ }),
3797
+ getCommunityStatus: defineContract({
3798
+ method: "GET",
3799
+ path: "/api/community/status",
3800
+ params: EmptyParamsSchema,
3801
+ request: NoRequestBodySchema,
3802
+ response: CommunityStatusSchema,
3803
+ error: HostApiErrorSchema
3804
+ }),
3805
+ startCommunityLogin: defineContract({
3806
+ method: "POST",
3807
+ path: "/api/community/login",
3808
+ params: EmptyParamsSchema,
3809
+ /** 浏览器当前访问本实例使用的来源;社区授权完成后回到 `<returnOrigin>/community/callback`。 */
3810
+ request: z.object({ returnOrigin: z.string().url().max(300) }).strict(),
3811
+ response: z.object({ authorizeUrl: z.string().url() }).strict(),
3812
+ error: HostApiErrorSchema
3813
+ }),
3814
+ communityLogout: defineContract({
3815
+ method: "DELETE",
3816
+ path: "/api/community/login",
3817
+ params: EmptyParamsSchema,
3818
+ request: NoRequestBodySchema,
3819
+ response: CommunityStatusSchema,
3820
+ error: HostApiErrorSchema
3821
+ }),
3822
+ listCommunityExtensions: defineContract({
3823
+ timeoutMs: 3e4,
3824
+ method: "GET",
3825
+ path: "/api/community/extensions",
3826
+ params: z.object({
3827
+ query: z.string().trim().max(80).optional(),
3828
+ scope: z.enum([
3829
+ "agent",
3830
+ "host-adapter",
3831
+ "host-ui"
3832
+ ]).optional(),
3833
+ cursor: z.string().max(200).optional()
3834
+ }).strict(),
3835
+ request: NoRequestBodySchema,
3836
+ response: z.object({
3837
+ items: z.array(CommunityExtensionSummarySchema),
3838
+ nextCursor: z.string().nullable()
3839
+ }).strict(),
3840
+ error: HostApiErrorSchema
3841
+ }),
3842
+ getCommunityExtension: defineContract({
3843
+ timeoutMs: 3e4,
3844
+ method: "GET",
3845
+ path: "/api/community/extensions/:extensionId",
3846
+ params: z.object({ extensionId: ExtensionIdSchema }).strict(),
3847
+ request: NoRequestBodySchema,
3848
+ response: CommunityExtensionDetailSchema,
3849
+ error: HostApiErrorSchema
3850
+ }),
3851
+ /** 下载社区发布并按包摘要校验,结果与本地文件导入的检查相同,再经 `commitExtensionImport` 确认。 */
3852
+ getCommunityEndpoint: defineContract({
3853
+ method: "GET",
3854
+ path: "/api/community/endpoint",
3855
+ params: EmptyParamsSchema,
3856
+ request: NoRequestBodySchema,
3857
+ response: CommunityEndpointSchema,
3858
+ error: HostApiErrorSchema
3859
+ }),
3860
+ /** 修改社区地址;`url: null` 恢复为环境变量或默认地址。非加密的局域网地址需要确认风险。 */
3861
+ updateCommunityEndpoint: defineContract({
3862
+ method: "PUT",
3863
+ path: "/api/community/endpoint",
3864
+ params: EmptyParamsSchema,
3865
+ request: z.object({
3866
+ url: z.string().max(300).nullable(),
3867
+ acknowledgeInsecure: z.boolean()
3868
+ }).strict(),
3869
+ response: CommunityEndpointSchema,
3870
+ error: HostApiErrorSchema
3871
+ }),
3872
+ testCommunityEndpoint: defineContract({
3873
+ timeoutMs: 3e4,
3874
+ method: "POST",
3875
+ path: "/api/community/endpoint/test",
3876
+ params: EmptyParamsSchema,
3877
+ request: z.object({
3878
+ url: z.string().max(300),
3879
+ acknowledgeInsecure: z.boolean()
3880
+ }).strict(),
3881
+ response: z.object({
3882
+ ok: z.boolean(),
3883
+ message: z.string(),
3884
+ name: z.string().optional(),
3885
+ environment: z.enum([
3886
+ "production",
3887
+ "staging",
3888
+ "development"
3889
+ ]).optional()
3890
+ }).strict(),
3891
+ error: HostApiErrorSchema
3892
+ }),
3893
+ listCommunityInstalled: defineContract({
3894
+ timeoutMs: 3e4,
3895
+ method: "GET",
3896
+ path: "/api/community/installed",
3897
+ params: z.object({ refresh: z.enum(["1"]).optional() }).strict(),
3898
+ request: NoRequestBodySchema,
3899
+ response: CommunityInstalledSchema,
3900
+ error: HostApiErrorSchema
3901
+ }),
3902
+ listCommunityMine: defineContract({
3903
+ timeoutMs: 3e4,
3904
+ method: "GET",
3905
+ path: "/api/community/mine",
3906
+ params: EmptyParamsSchema,
3907
+ request: NoRequestBodySchema,
3908
+ response: z.object({ items: z.array(CommunityMyExtensionSchema) }).strict(),
3909
+ error: HostApiErrorSchema
3910
+ }),
3911
+ getCommunityReleaseReview: defineContract({
3912
+ timeoutMs: 3e4,
3913
+ method: "GET",
3914
+ path: "/api/community/releases/:releaseId/review",
3915
+ params: z.object({ releaseId: CommunityReleaseIdSchema }).strict(),
3916
+ request: NoRequestBodySchema,
3917
+ response: CommunityReviewReportSchema,
3918
+ error: HostApiErrorSchema
3919
+ }),
3920
+ requestCommunityReview: defineContract({
3921
+ timeoutMs: 3e4,
3922
+ method: "POST",
3923
+ path: "/api/community/releases/:releaseId/review",
3924
+ params: z.object({ releaseId: CommunityReleaseIdSchema }).strict(),
3925
+ request: NoRequestBodySchema,
3926
+ response: z.object({ ok: z.literal(true) }).strict(),
3927
+ error: HostApiErrorSchema
3928
+ }),
3929
+ withdrawCommunityRelease: defineContract({
3930
+ timeoutMs: 3e4,
3931
+ method: "POST",
3932
+ path: "/api/community/releases/:releaseId/withdraw",
3933
+ params: z.object({ releaseId: CommunityReleaseIdSchema }).strict(),
3934
+ request: NoRequestBodySchema,
3935
+ response: z.object({ ok: z.literal(true) }).strict(),
3936
+ error: HostApiErrorSchema
3937
+ }),
3938
+ importCommunityRelease: defineContract({
3939
+ timeoutMs: 12e4,
3940
+ method: "POST",
3941
+ path: "/api/community/releases/:releaseId/import",
3942
+ params: z.object({ releaseId: CommunityReleaseIdSchema }).strict(),
3943
+ request: NoRequestBodySchema,
3944
+ response: ExtensionImportInspectionSchema,
3945
+ error: HostApiErrorSchema
3946
+ }),
3947
+ publishToCommunity: defineContract({
3948
+ timeoutMs: 12e4,
3949
+ method: "POST",
3950
+ path: "/api/community/publish",
3951
+ params: EmptyParamsSchema,
3952
+ request: z.object({
3953
+ extensionId: ExtensionIdSchema,
3954
+ revisionId: ExtensionRevisionIdSchema,
3955
+ notes: z.string().max(2e3)
3956
+ }).strict(),
3957
+ response: z.object({
3958
+ releaseId: CommunityReleaseIdSchema,
3959
+ reviewStatus: CommunityReviewStatusSchema,
3960
+ pageUrl: z.string().url(),
3961
+ reportUrl: z.string().url(),
3962
+ findings: z.array(z.object({
3963
+ severity: z.string(),
3964
+ title: z.string()
3965
+ }).strict())
3966
+ }).strict(),
3967
+ error: HostApiErrorSchema
3968
+ }),
3969
+ testMcpServer: defineContract({
3970
+ timeoutMs: 3e4,
3971
+ method: "POST",
3972
+ path: "/api/mcp-servers/test",
3973
+ params: EmptyParamsSchema,
3974
+ request: z.object({ server: McpServerFormSchema }).strict(),
3975
+ response: z.object({
3976
+ ok: z.boolean(),
3977
+ message: z.string(),
3978
+ serverName: z.string().optional(),
3979
+ tools: z.array(z.object({
3980
+ name: z.string(),
3981
+ description: z.string().optional()
3982
+ }).strict())
3983
+ }).strict(),
3984
+ error: HostApiErrorSchema
3985
+ }),
3986
+ createMcpExtension: defineContract({
3987
+ invalidatesSnapshot: true,
3988
+ timeoutMs: 12e4,
3989
+ method: "POST",
3990
+ path: "/api/mcp-servers",
3991
+ params: EmptyParamsSchema,
3992
+ request: z.object({
3993
+ displayName: z.string().trim().min(1).max(80),
3994
+ description: z.string().trim().max(500).default(""),
3995
+ server: McpServerFormSchema
3996
+ }).strict(),
3997
+ response: z.object({
3998
+ extensionId: ExtensionIdSchema,
3999
+ revisionId: ExtensionRevisionIdSchema,
4000
+ /** Credential config fields created for the form's secret rows, by row name. */
4001
+ secretFields: z.array(z.object({
4002
+ key: z.string(),
4003
+ name: z.string()
4004
+ }).strict())
4005
+ }).strict(),
4006
+ error: HostApiErrorSchema
4007
+ }),
4008
+ commitExtensionImport: defineContract({
4009
+ invalidatesSnapshot: true,
4010
+ timeoutMs: 3e5,
4011
+ method: "POST",
4012
+ path: "/api/extensions/imports/:token/commit",
4013
+ params: z.object({ token: NonEmptyStringSchema }).strict(),
4014
+ request: z.object({ localSlug: z.string().trim().min(3).max(64).optional() }).strict(),
4015
+ response: z.object({
4016
+ extensionId: ExtensionIdSchema,
4017
+ revisionId: ExtensionRevisionIdSchema,
4018
+ idempotent: z.boolean()
4019
+ }).strict(),
4020
+ error: HostApiErrorSchema
4021
+ }),
4022
+ dshSettings: defineContract({
4023
+ method: "GET",
4024
+ path: "/api/dsh/settings",
4025
+ params: EmptyParamsSchema,
4026
+ request: NoRequestBodySchema,
4027
+ response: z.object({ namespaces: z.array(DshSettingsNamespaceSchema) }).strict(),
4028
+ error: HostApiErrorSchema
4029
+ }),
4030
+ dshSettingsMutate: defineContract({
4031
+ invalidatesSnapshot: true,
4032
+ method: "POST",
4033
+ path: "/api/dsh/settings/:namespace/mutate",
4034
+ params: dshSettingsParam,
4035
+ request: DshSettingsMutationRequestSchema,
4036
+ response: DshSettingsNamespaceSchema,
4037
+ error: HostApiErrorSchema
4038
+ }),
4039
+ dshCredentialsDescribe: defineContract({
4040
+ method: "POST",
4041
+ path: "/api/dsh/credentials/describe",
4042
+ params: EmptyParamsSchema,
4043
+ request: z.object({ refs: z.array(DshCredentialRefSchema).max(64) }).strict(),
4044
+ response: z.object({ credentials: z.record(z.string(), DshCredentialViewSchema) }).strict(),
4045
+ error: HostApiErrorSchema
4046
+ }),
4047
+ dshCredentialSet: defineContract({
4048
+ invalidatesSnapshot: true,
4049
+ method: "PUT",
4050
+ path: "/api/dsh/credentials/:ref",
4051
+ params: dshCredentialParam,
4052
+ request: z.object({ value: z.string().min(1).max(64 * 1024) }).strict(),
4053
+ response: DshCredentialViewSchema,
4054
+ error: HostApiErrorSchema
4055
+ }),
4056
+ dshCredentialUnset: defineContract({
4057
+ invalidatesSnapshot: true,
4058
+ method: "DELETE",
4059
+ path: "/api/dsh/credentials/:ref",
4060
+ params: dshCredentialParam,
4061
+ request: NoRequestBodySchema,
4062
+ response: DshCredentialViewSchema,
4063
+ error: HostApiErrorSchema
4064
+ }),
4065
+ llmProviders: defineContract({
4066
+ method: "GET",
4067
+ path: "/api/llm/providers",
4068
+ params: EmptyParamsSchema,
4069
+ request: NoRequestBodySchema,
4070
+ response: LlmProviderSettingsSchema,
4071
+ error: HostApiErrorSchema
4072
+ }),
4073
+ llmDiscoverModels: defineContract({
4074
+ method: "POST",
4075
+ path: "/api/llm/discover-models",
4076
+ params: EmptyParamsSchema,
4077
+ request: z.object({
4078
+ provider: NonEmptyStringSchema.optional(),
4079
+ settingsNs: NonEmptyStringSchema.optional(),
4080
+ baseURL: z.url().optional(),
4081
+ api: NonEmptyStringSchema.optional(),
4082
+ apiKey: z.string().min(1).max(64 * 1024).optional()
4083
+ }).strict(),
4084
+ response: z.object({ models: z.array(LlmDiscoveredModelSchema) }).strict(),
4085
+ error: HostApiErrorSchema
4086
+ }),
4087
+ llmTestProvider: defineContract({
4088
+ method: "POST",
4089
+ path: "/api/llm/test-provider",
4090
+ params: EmptyParamsSchema,
4091
+ request: z.object({
4092
+ provider: NonEmptyStringSchema,
4093
+ model: NonEmptyStringSchema,
4094
+ settingsNs: NonEmptyStringSchema.optional(),
4095
+ apiKey: z.string().min(1).max(64 * 1024).optional(),
4096
+ baseURL: z.url().optional(),
4097
+ api: NonEmptyStringSchema.optional(),
4098
+ models: z.array(LlmDiscoveredModelSchema).optional()
4099
+ }).strict(),
4100
+ response: z.object({
4101
+ provider: NonEmptyStringSchema,
4102
+ model: NonEmptyStringSchema
4103
+ }).strict(),
4104
+ error: HostApiErrorSchema
4105
+ }),
4106
+ llmProviderRemovalImpact: defineContract({
4107
+ method: "GET",
4108
+ path: "/api/llm/providers/:provider/removal-impact",
4109
+ params: llmProviderParam,
4110
+ request: NoRequestBodySchema,
4111
+ response: z.object({
4112
+ provider: NonEmptyStringSchema,
4113
+ displayName: NonEmptyStringSchema,
4114
+ declared: z.boolean(),
4115
+ expectedRevision: z.number().int().nonnegative(),
4116
+ models: z.array(NonEmptyStringSchema),
4117
+ blockedReason: z.string(),
4118
+ references: z.array(z.object({
4119
+ agentId: AgentIdSchema,
4120
+ displayName: NonEmptyStringSchema,
4121
+ model: NonEmptyStringSchema,
4122
+ role: z.enum(["primary", "vision"]),
4123
+ scope: z.enum(["configuration", "context"]),
4124
+ channelId: ChannelIdSchema.optional(),
4125
+ channelName: z.string().optional(),
4126
+ episodeStatus: z.enum(["opening", "active"]).optional()
4127
+ }).strict())
4128
+ }).strict(),
4129
+ error: HostApiErrorSchema
4130
+ }),
4131
+ llmRemoveProvider: defineContract({
4132
+ invalidatesSnapshot: true,
4133
+ method: "DELETE",
4134
+ path: "/api/llm/providers/:provider",
4135
+ params: llmProviderParam,
4136
+ request: z.object({ expectedRevision: z.number().int().nonnegative() }).strict(),
4137
+ response: LlmProviderSettingsSchema,
4138
+ error: HostApiErrorSchema
4139
+ }),
4140
+ llmRestoreProviderModels: defineContract({
4141
+ invalidatesSnapshot: true,
4142
+ method: "POST",
4143
+ path: "/api/llm/providers/:provider/restore-models",
4144
+ params: llmProviderParam,
4145
+ request: z.object({ expectedRevision: z.number().int().nonnegative() }).strict(),
4146
+ response: LlmProviderSettingsSchema,
4147
+ error: HostApiErrorSchema
4148
+ }),
4149
+ llmSaveProvider: defineContract({
4150
+ invalidatesSnapshot: true,
4151
+ method: "POST",
4152
+ path: "/api/llm/providers/:provider",
4153
+ params: llmProviderParam,
4154
+ request: z.object({
4155
+ expectedRevision: z.number().int().nonnegative(),
4156
+ apiKey: z.string().min(1).max(64 * 1024).optional(),
4157
+ displayName: z.string().trim().min(1).max(120).optional(),
4158
+ baseURL: z.url().optional(),
4159
+ api: NonEmptyStringSchema.optional(),
4160
+ models: z.array(LlmDiscoveredModelSchema).optional()
4161
+ }).strict(),
4162
+ response: LlmProviderSettingsSchema,
4163
+ error: HostApiErrorSchema
4164
+ }),
4165
+ testConnection: defineContract({
4166
+ invalidatesSnapshot: true,
4167
+ method: "POST",
4168
+ path: "/api/connections/:connectionId/test",
4169
+ params: connectionParam,
4170
+ request: z.object({
4171
+ direction: z.enum(["send", "receive"]),
4172
+ channelId: ChannelIdSchema.optional()
4173
+ }).strict(),
4174
+ response: ConnectionTestResultSchema,
4175
+ error: HostApiErrorSchema
4176
+ }),
4177
+ dynamicInventory: defineContract({
4178
+ method: "POST",
4179
+ path: "/api/dynamic/:agentId/inventory",
4180
+ params: agentParam,
4181
+ request: z.object({ episodeId: EpisodeIdSchema }).strict(),
4182
+ response: z.object({ rows: z.array(DynamicInventoryRowSchema) }).strict(),
4183
+ error: HostApiErrorSchema
4184
+ }),
4185
+ dynamicApprove: defineContract({
4186
+ invalidatesSnapshot: true,
4187
+ method: "POST",
4188
+ path: "/api/dynamic/:agentId/approve",
4189
+ params: agentParam,
4190
+ request: z.object({
4191
+ episodeId: EpisodeIdSchema,
4192
+ requestId: DynamicIdSchema,
4193
+ pluginRunId: DynamicIdSchema.optional()
4194
+ }).strict(),
4195
+ response: z.object({ accepted: z.boolean() }).strict(),
4196
+ error: HostApiErrorSchema
4197
+ }),
4198
+ dynamicDecline: defineContract({
4199
+ invalidatesSnapshot: true,
4200
+ method: "POST",
4201
+ path: "/api/dynamic/:agentId/decline",
4202
+ params: agentParam,
4203
+ request: z.object({
4204
+ episodeId: EpisodeIdSchema,
4205
+ requestId: DynamicIdSchema,
4206
+ pluginRunId: DynamicIdSchema.optional()
4207
+ }).strict(),
4208
+ response: z.object({ accepted: z.boolean() }).strict(),
4209
+ error: HostApiErrorSchema
4210
+ }),
4211
+ dynamicInvoke: defineContract({
4212
+ method: "POST",
4213
+ path: "/api/dynamic/:agentId/invoke",
4214
+ params: agentParam,
4215
+ request: z.object({
4216
+ episodeId: EpisodeIdSchema,
4217
+ pluginId: DynamicIdSchema,
4218
+ pluginRunId: DynamicIdSchema,
4219
+ method: NonEmptyStringSchema,
4220
+ args: JsonValueSchema.optional()
4221
+ }).strict(),
4222
+ response: z.discriminatedUnion("ok", [z.object({
4223
+ ok: z.literal(true),
4224
+ value: JsonValueSchema
4225
+ }).strict(), z.object({
4226
+ ok: z.literal(false),
4227
+ message: z.string()
4228
+ }).strict()]),
4229
+ error: HostApiErrorSchema
4230
+ }),
4231
+ dynamicRunHostHalf: defineContract({
4232
+ method: "POST",
4233
+ path: "/api/dynamic/:agentId/run-host-half",
4234
+ params: agentParam,
4235
+ request: z.object({
4236
+ episodeId: EpisodeIdSchema,
4237
+ pluginId: DynamicIdSchema,
4238
+ packageId: DynamicIdSchema,
4239
+ mode: z.enum(["run", "update"]),
4240
+ requestId: DynamicIdSchema.nullable().optional(),
4241
+ approveFutureVersions: z.boolean().default(false)
4242
+ }).strict(),
4243
+ response: z.discriminatedUnion("ok", [z.object({
4244
+ ok: z.literal(true),
4245
+ pluginId: DynamicIdSchema,
4246
+ packageId: DynamicIdSchema,
4247
+ pluginRunId: DynamicIdSchema,
4248
+ waitingFor: z.array(z.string()),
4249
+ startedHere: z.boolean()
4250
+ }).strict(), DynamicErrorDetailsSchema.extend({ ok: z.literal(false) })]),
4251
+ error: HostApiErrorSchema
4252
+ }),
4253
+ dynamicSettleUserRun: defineContract({
4254
+ method: "POST",
4255
+ path: "/api/dynamic/:agentId/settle-user-run",
4256
+ params: agentParam,
4257
+ request: z.object({
4258
+ episodeId: EpisodeIdSchema,
4259
+ pluginId: DynamicIdSchema,
4260
+ resolution: DynamicRunResolutionSchema
4261
+ }).strict(),
4262
+ response: DynamicRunResponseSchema,
4263
+ error: HostApiErrorSchema
4264
+ }),
4265
+ dynamicGetClientCode: defineContract({
4266
+ method: "POST",
4267
+ path: "/api/dynamic/:agentId/get-client-code",
4268
+ params: agentParam,
4269
+ request: z.object({
4270
+ episodeId: EpisodeIdSchema,
4271
+ pluginId: DynamicIdSchema,
4272
+ pluginRunId: DynamicIdSchema
4273
+ }).strict(),
4274
+ response: z.object({
4275
+ code: z.string(),
4276
+ name: z.string(),
4277
+ pluginId: DynamicIdSchema,
4278
+ packageId: DynamicIdSchema,
4279
+ pluginRunId: DynamicIdSchema,
4280
+ /** What the candidate declared; preview data hooks enforce exactly what the saved Revision will. */
4281
+ permissions: HostUiPermissionDeclarationSchema.default({
4282
+ permissions: [],
4283
+ networkOrigins: []
4284
+ })
4285
+ }).strict(),
4286
+ error: HostApiErrorSchema
4287
+ }),
4288
+ dynamicReportRenderFailure: defineContract({
4289
+ method: "POST",
4290
+ path: "/api/dynamic/:agentId/report-render-failure",
4291
+ params: agentParam,
4292
+ request: z.object({
4293
+ episodeId: EpisodeIdSchema,
4294
+ pluginId: DynamicIdSchema,
4295
+ pluginRunId: DynamicIdSchema,
4296
+ failure: DynamicRenderFailureSchema
4297
+ }).strict(),
4298
+ response: z.object({ ok: z.literal(true) }).strict(),
4299
+ error: HostApiErrorSchema
4300
+ }),
4301
+ dynamicReportGuardFailure: defineContract({
4302
+ method: "POST",
4303
+ path: "/api/dynamic/:agentId/report-guard-failure",
4304
+ params: agentParam,
4305
+ request: z.object({
4306
+ episodeId: EpisodeIdSchema,
4307
+ pluginId: DynamicIdSchema,
4308
+ pluginRunId: DynamicIdSchema,
4309
+ message: z.string().min(1).max(4096),
4310
+ stack: z.string().max(16 * 1024).optional()
4311
+ }).strict(),
4312
+ response: z.object({ ok: z.literal(true) }).strict(),
4313
+ error: HostApiErrorSchema
4314
+ }),
4315
+ dynamicReportClientVerification: defineContract({
4316
+ method: "POST",
4317
+ path: "/api/dynamic/:agentId/report-client-verification",
4318
+ params: agentParam,
4319
+ request: z.object({
4320
+ episodeId: EpisodeIdSchema,
4321
+ pluginId: DynamicIdSchema,
4322
+ packageId: DynamicIdSchema,
4323
+ pluginRunId: DynamicIdSchema,
4324
+ renderedPanels: z.array(PanelContributionSchema).max(16).default([]),
4325
+ renderedToolViews: z.array(z.string().trim().min(1).max(64)).max(32).default([]),
4326
+ renderedMessageRenderers: z.array(RichKindSchema).max(32).default([]),
4327
+ renderedPages: z.array(HostPageContributionSchema).max(8).default([]),
4328
+ usedUiComponents: z.array(HostUiKitComponentNameSchema).max(HostUiKitComponentNameSchema.options.length).default([]),
4329
+ pageGeometry: z.array(HostUiPageGeometryEvidenceSchema).max(8).default([]),
4330
+ navigationEntries: z.array(z.string().trim().min(1).max(64)).max(8).default([])
4331
+ }).strict().refine((value) => value.renderedPanels.length > 0 || value.renderedToolViews.length > 0 || value.renderedMessageRenderers.length > 0 || value.renderedPages.length > 0, { message: "动态 Client 必须真实渲染至少一个面板、工具视图、富消息渲染器或页面。" }),
4332
+ response: z.object({ ok: z.literal(true) }).strict(),
4333
+ error: HostApiErrorSchema
4334
+ }),
4335
+ saveExtensionFromDynamic: defineContract({
4336
+ invalidatesSnapshot: true,
4337
+ timeoutMs: 3e5,
4338
+ method: "POST",
4339
+ path: "/api/extensions/save-from-dynamic",
4340
+ params: EmptyParamsSchema,
4341
+ request: z.union([z.object({
4342
+ taskId: AuthoringTaskIdSchema,
4343
+ attemptId: AuthoringAttemptIdSchema,
4344
+ displayName: z.string().trim().min(1).max(80),
4345
+ slug: z.string().trim().regex(/^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/u),
4346
+ description: z.string().max(500).default(""),
4347
+ targetExtensionId: ExtensionIdSchema.optional()
4348
+ }).strict(), z.object({
4349
+ agentId: AgentIdSchema,
4350
+ episodeId: EpisodeIdSchema,
4351
+ pluginId: DynamicIdSchema,
4352
+ packageId: DynamicIdSchema,
4353
+ displayName: z.string().trim().min(1).max(80),
4354
+ slug: z.string().trim().regex(/^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/u),
4355
+ description: z.string().max(500).default(""),
4356
+ targetExtensionId: ExtensionIdSchema.optional()
4357
+ }).strict()]),
4358
+ response: z.object({
4359
+ extensionId: ExtensionIdSchema,
4360
+ revisionId: ExtensionRevisionIdSchema,
4361
+ activation: z.literal("inactive"),
4362
+ installation: z.literal("uninstalled").optional()
4363
+ }).strict(),
4364
+ error: HostApiErrorSchema
4365
+ }),
4366
+ extensionClientCall: defineContract({
4367
+ method: "POST",
4368
+ path: "/api/extensions/:extensionId/revisions/:revisionId/call",
4369
+ params: extensionRevisionParam,
4370
+ request: z.object({
4371
+ agentId: AgentIdSchema,
4372
+ method: NonEmptyStringSchema,
4373
+ input: JsonValueSchema.optional()
4374
+ }).strict(),
4375
+ response: z.object({ value: JsonValueSchema }).strict(),
4376
+ error: HostApiErrorSchema
4377
+ }),
4378
+ extensionClientDiagnostic: defineContract({
4379
+ method: "POST",
4380
+ path: "/api/extensions/:extensionId/revisions/:revisionId/client-diagnostic",
4381
+ params: extensionRevisionParam,
4382
+ request: z.object({
4383
+ agentId: AgentIdSchema,
4384
+ status: z.enum(["loaded", "failed"]),
4385
+ message: z.string().max(4096).optional()
4386
+ }).strict(),
4387
+ response: z.object({ accepted: z.literal(true) }).strict(),
4388
+ error: HostApiErrorSchema
4389
+ }),
4390
+ hostExtensionClientDiagnostic: defineContract({
4391
+ method: "POST",
4392
+ path: "/api/extensions/:extensionId/revisions/:revisionId/host-client-diagnostic",
4393
+ params: extensionRevisionParam,
4394
+ request: z.object({
4395
+ status: z.enum(["loaded", "failed"]),
4396
+ message: z.string().max(4096).optional()
4397
+ }).strict(),
4398
+ response: z.object({ accepted: z.literal(true) }).strict(),
4399
+ error: HostApiErrorSchema
4400
+ }),
4401
+ activateExtension: defineContract({
4402
+ invalidatesSnapshot: true,
4403
+ method: "POST",
4404
+ path: "/api/agents/:agentId/extensions/:extensionId/activation",
4405
+ params: agentExtensionParam,
4406
+ request: z.object({
4407
+ revisionId: ExtensionRevisionIdSchema,
4408
+ permissionApproval: z.object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) }).strict().optional()
4409
+ }).strict(),
4410
+ response: z.object({ activation: z.object({
4411
+ agentId: AgentIdSchema,
4412
+ extensionId: ExtensionIdSchema,
4413
+ extensionRevisionId: ExtensionRevisionIdSchema,
4414
+ config: JsonValueSchema,
4415
+ configuredSecrets: z.array(z.string()).optional(),
4416
+ activatedAt: z.number().int().safe().nonnegative()
4417
+ }).strict() }).strict(),
4418
+ error: HostApiErrorSchema
4419
+ }),
4420
+ deactivateExtension: defineContract({
4421
+ invalidatesSnapshot: true,
4422
+ method: "DELETE",
4423
+ path: "/api/agents/:agentId/extensions/:extensionId/activation",
4424
+ params: agentExtensionParam,
4425
+ request: NoRequestBodySchema,
4426
+ response: z.object({ disabled: z.literal(true) }).strict(),
4427
+ error: HostApiErrorSchema
4428
+ }),
4429
+ updateExtensionActivationConfig: defineContract({
4430
+ invalidatesSnapshot: true,
4431
+ method: "PUT",
4432
+ path: "/api/agents/:agentId/extensions/:extensionId/activation/config",
4433
+ params: agentExtensionParam,
4434
+ request: z.object({
4435
+ config: JsonValueSchema,
4436
+ /** Write-only credential drafts keyed by secret field; an absent or empty draft keeps the stored one. */
4437
+ secrets: z.record(z.string(), z.string().max(8192)).optional()
4438
+ }).strict(),
4439
+ response: z.object({
4440
+ config: JsonValueSchema,
4441
+ configuredSecrets: z.array(z.string()).optional()
4442
+ }).strict(),
4443
+ error: HostApiErrorSchema
4444
+ }),
4445
+ updateHostExtensionConfig: defineContract({
4446
+ invalidatesSnapshot: true,
4447
+ timeoutMs: 3e5,
4448
+ method: "PUT",
4449
+ path: "/api/extensions/:extensionId/installation/config",
4450
+ params: extensionParam,
4451
+ request: z.object({ config: JsonValueSchema }).strict(),
4452
+ response: z.object({ config: JsonValueSchema }).strict(),
4453
+ error: HostApiErrorSchema
4454
+ }),
4455
+ installHostExtension: defineContract({
4456
+ invalidatesSnapshot: true,
4457
+ timeoutMs: 3e5,
4458
+ method: "PUT",
4459
+ path: "/api/extensions/:extensionId/installation",
4460
+ params: extensionParam,
4461
+ request: z.object({
4462
+ revisionId: ExtensionRevisionIdSchema,
4463
+ permissionApproval: z.object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) }).strict().optional()
4464
+ }).strict(),
4465
+ response: z.object({ installation: z.object({
4466
+ extensionId: ExtensionIdSchema,
4467
+ extensionRevisionId: ExtensionRevisionIdSchema,
4468
+ installedAt: z.number().int().safe().nonnegative(),
4469
+ config: JsonValueSchema
4470
+ }).strict() }).strict(),
4471
+ error: HostApiErrorSchema
4472
+ }),
4473
+ uninstallHostExtension: defineContract({
4474
+ invalidatesSnapshot: true,
4475
+ timeoutMs: 3e5,
4476
+ method: "DELETE",
4477
+ path: "/api/extensions/:extensionId/installation",
4478
+ params: extensionParam,
4479
+ request: NoRequestBodySchema,
4480
+ response: z.object({ uninstalled: z.literal(true) }).strict(),
4481
+ error: HostApiErrorSchema
4482
+ }),
4483
+ updateHostUiPagePreferences: defineContract({
4484
+ invalidatesSnapshot: true,
4485
+ method: "PUT",
4486
+ path: "/api/host-ui/page-preferences",
4487
+ params: EmptyParamsSchema,
4488
+ request: z.object({
4489
+ expectedRevision: z.number().int().nonnegative(),
4490
+ entries: z.array(z.object({
4491
+ pageInstanceId: HostUiPageInstanceIdSchema,
4492
+ visible: z.boolean()
4493
+ }).strict())
4494
+ }).strict(),
4495
+ response: z.object({ revision: z.number().int().positive() }).strict(),
4496
+ error: HostApiErrorSchema
4497
+ }),
4498
+ callHostUiPage: defineContract({
4499
+ method: "POST",
4500
+ path: "/api/host-ui/pages/:pageInstanceId/call",
4501
+ params: z.object({ pageInstanceId: HostUiPageInstanceIdSchema }).strict(),
4502
+ request: z.object({
4503
+ method: NonEmptyStringSchema,
4504
+ input: JsonValueSchema.default({})
4505
+ }).strict(),
4506
+ response: z.object({ value: JsonValueSchema }).strict(),
4507
+ error: HostApiErrorSchema
4508
+ }),
4509
+ reportHostUiPageDiagnostic: defineContract({
4510
+ method: "POST",
4511
+ path: "/api/host-ui/pages/:pageInstanceId/diagnostic",
4512
+ params: z.object({ pageInstanceId: HostUiPageInstanceIdSchema }).strict(),
4513
+ request: z.object({
4514
+ status: z.enum([
4515
+ "ready",
4516
+ "load-failed",
4517
+ "navigation-failed",
4518
+ "rpc-failed"
4519
+ ]),
4520
+ message: z.string().max(2e3).optional()
4521
+ }).strict(),
4522
+ response: z.object({ recorded: z.literal(true) }).strict(),
4523
+ error: HostApiErrorSchema
4524
+ }),
4525
+ markChannelRead: defineContract({
4526
+ method: "POST",
4527
+ path: "/api/channels/:channelId/read",
4528
+ params: channelParam,
4529
+ request: z.object({
4530
+ /** Defaults to the newest inbound fact visible now. */
4531
+ upTo: z.object({
4532
+ occurredAt: z.number().int().safe().nonnegative(),
4533
+ sourceId: ChannelEventIdSchema
4534
+ }).strict().optional() }).strict(),
4535
+ response: z.object({
4536
+ channelId: ChannelIdSchema,
4537
+ activity: ChannelActivitySummarySchema
4538
+ }).strict(),
4539
+ error: HostApiErrorSchema
4540
+ }),
4541
+ listAttention: defineContract({
4542
+ method: "GET",
4543
+ path: "/api/attention",
4544
+ params: EmptyParamsSchema,
4545
+ request: NoRequestBodySchema,
4546
+ response: AttentionListSchema,
4547
+ error: HostApiErrorSchema
4548
+ }),
4549
+ dismissAttention: defineContract({
4550
+ method: "POST",
4551
+ path: "/api/attention/:attentionId/dismiss",
4552
+ params: z.object({ attentionId: z.string().min(1).max(200) }).strict(),
4553
+ request: NoRequestBodySchema,
4554
+ response: z.object({
4555
+ dismissed: z.literal(true),
4556
+ revision: z.string().min(1)
4557
+ }).strict(),
4558
+ error: HostApiErrorSchema
4559
+ }),
4560
+ getChannelPending: defineContract({
4561
+ method: "GET",
4562
+ path: "/api/channels/:channelId/pending",
4563
+ params: channelParam,
4564
+ request: NoRequestBodySchema,
4565
+ response: ChannelPendingContextSchema,
4566
+ error: HostApiErrorSchema
4567
+ }),
4568
+ stopChannelTask: defineContract({
4569
+ method: "POST",
4570
+ path: "/api/channels/:channelId/stop",
4571
+ params: channelParam,
4572
+ request: z.object({ expectedEpisodeId: EpisodeIdSchema.optional() }).strict(),
4573
+ response: z.object({
4574
+ result: z.enum(["stopped", "idle"]),
4575
+ episodeId: EpisodeIdSchema.optional(),
4576
+ /** Admitted messages that were not yet consumed and remain queued for the next turn. */
4577
+ retainedPending: z.number().int().nonnegative()
4578
+ }).strict(),
4579
+ error: HostApiErrorSchema
4580
+ }),
4581
+ resolveOutbound: defineContract({
4582
+ method: "POST",
4583
+ path: "/api/outbound/:outboundId/resolve",
4584
+ params: z.object({ outboundId: OutboundIntentIdSchema }).strict(),
4585
+ request: z.object({ action: z.enum(["retry", "confirm-delivered"]) }).strict(),
4586
+ response: z.object({
4587
+ outboundId: OutboundIntentIdSchema,
4588
+ action: z.enum(["retry", "confirm-delivered"]),
4589
+ deliveryState: z.enum([
4590
+ "planned",
4591
+ "sending",
4592
+ "sent",
4593
+ "partially-sent",
4594
+ "failed",
4595
+ "unknown"
4596
+ ]),
4597
+ resolvedAt: z.number().int().safe().nonnegative()
4598
+ }).strict(),
4599
+ error: HostApiErrorSchema
4600
+ }),
4601
+ getChannelActivity: defineContract({
4602
+ method: "GET",
4603
+ path: "/api/activity",
4604
+ params: ActivityQuerySchema,
4605
+ request: NoRequestBodySchema,
4606
+ response: ChannelActivitySeriesSchema,
4607
+ error: HostApiErrorSchema
4608
+ }),
4609
+ listAgentRevisions: defineContract({
4610
+ method: "GET",
4611
+ path: "/api/agents/:agentId/revisions",
4612
+ params: agentParam,
4613
+ request: NoRequestBodySchema,
4614
+ response: AgentRevisionHistorySchema,
4615
+ error: HostApiErrorSchema
4616
+ }),
4617
+ restoreAgentRevision: defineContract({
4618
+ invalidatesSnapshot: true,
4619
+ method: "POST",
4620
+ path: "/api/agents/:agentId/revisions/:revisionId/restore",
4621
+ params: agentRevisionParam,
4622
+ request: z.object({ expectedCurrentRevisionId: AgentRevisionIdSchema }).strict(),
4623
+ response: z.object({ currentRevisionId: AgentRevisionIdSchema }).strict(),
4624
+ error: HostApiErrorSchema
4625
+ }),
4626
+ updateAgentAppearance: defineContract({
4627
+ invalidatesSnapshot: true,
4628
+ method: "PATCH",
4629
+ path: "/api/agents/:agentId/appearance",
4630
+ params: agentParam,
4631
+ request: z.object({
4632
+ hue: z.number().int().min(0).max(359).nullable().optional(),
4633
+ /** `null` removes the avatar; uploading uses `uploadAgentAvatar`. */
4634
+ avatarAssetId: z.null().optional()
4635
+ }).strict(),
4636
+ response: z.object({
4637
+ agentId: AgentIdSchema,
4638
+ appearance: AgentAppearanceSchema
4639
+ }).strict(),
4640
+ error: HostApiErrorSchema
4641
+ }),
4642
+ uploadAgentAvatar: defineContract({
4643
+ invalidatesSnapshot: true,
4644
+ method: "POST",
4645
+ path: "/api/agents/:agentId/avatar",
4646
+ params: agentParam,
4647
+ request: BinaryUploadRequestSchema,
4648
+ encodeRequest: encodeBinaryUpload,
4649
+ response: z.object({
4650
+ agentId: AgentIdSchema,
4651
+ appearance: AgentAppearanceSchema
4652
+ }).strict(),
4653
+ error: HostApiErrorSchema
4654
+ }),
4655
+ deleteLocalExtension: defineContract({
4656
+ invalidatesSnapshot: true,
4657
+ method: "DELETE",
4658
+ path: "/api/extensions/:extensionId",
4659
+ params: extensionParam,
4660
+ request: NoRequestBodySchema,
4661
+ response: z.object({ deleted: z.literal(true) }).strict(),
4662
+ error: HostApiErrorSchema
4663
+ })
4664
+ };
4665
+ const pathParameterPattern = /:([A-Za-z][A-Za-z0-9]*)/gu;
4666
+ /** Build the transport URL only after all path/query parameters pass the shared schema. */
4667
+ const buildValidatedHostApiPath = (contract, input) => {
4668
+ const params = z.record(z.string(), z.unknown()).parse(contract.params.parse(input));
4669
+ const consumed = /* @__PURE__ */ new Set();
4670
+ const pathname = contract.path.replace(pathParameterPattern, (_placeholder, key) => {
4671
+ const value = params[key];
4672
+ if (typeof value !== "string") throw new TypeError(`Host API path parameter ${key} must be a string.`);
4673
+ consumed.add(key);
4674
+ return encodeURIComponent(value);
4675
+ });
4676
+ const query = new URLSearchParams();
4677
+ for (const [key, value] of Object.entries(params)) {
4678
+ if (consumed.has(key) || value === void 0) continue;
4679
+ if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") throw new TypeError(`Host API query parameter ${key} must be a string, number, or boolean.`);
4680
+ query.set(key, String(value));
4681
+ }
4682
+ const suffix = query.toString();
4683
+ return suffix ? `${pathname}?${suffix}` : pathname;
4684
+ };
4685
+ function buildHostApiContractPath(contract, input) {
4686
+ return buildValidatedHostApiPath(contract, input);
4687
+ }
4688
+ function buildHostApiPath(name, input) {
4689
+ return buildValidatedHostApiPath(HostApiContracts[name], input);
4690
+ }
4691
+ //#endregion
4692
+ export { ACTIVITY_MAX_BUCKETS, ACTIVITY_MAX_WINDOW_MS, ACTIVITY_MIN_BUCKET_MS, ADAPTER_PANEL_ANCHORS, AGENT_PANEL_ANCHORS, ActivityQuerySchema, AdapterActivityKeySchema, AdmissionIdSchema, AgentAppearanceSchema, AgentIdSchema, AgentRevisionChangedFieldSchema, AgentRevisionHistorySchema, AgentRevisionIdSchema, AssetIdSchema, AttentionItemSchema, AttentionListSchema, AuthoringAttemptIdSchema, AuthoringTaskIdSchema, CHANNEL_UNREAD_COUNT_CAP, COMMUNITY_OFFICIAL_HANDLE, COMMUNITY_REVIEW_DIMENSIONS, COMMUNITY_REVIEW_DIMENSION_LABELS, COMMUNITY_REVIEW_STATUSES, CONFIG_SCHEMA_MAX_BYTES, ChannelActivitySeriesSchema, ChannelActivitySummarySchema, ChannelEventIdSchema, ChannelFactSseDataSchema, ChannelFactSseItemSchema, ChannelIdSchema, ChannelMemberIdSchema, ChannelPendingContextSchema, ChannelRuntimeCacheSampleSchema, ChannelRuntimeCacheSchema, ChannelRuntimeOccupancySchema, ChannelRuntimePerformanceSampleSchema, ChannelRuntimePerformanceSchema, ChannelRuntimePhaseSchema, ChannelRuntimeProjectionSchema, ChannelRuntimeSseDataSchema, ChannelRuntimeStepSchema, ChannelRuntimeToolSchema, ChannelRuntimeTurnSchema, ChannelRuntimeUsageSchema, ClientNotificationFeedResponseSchema, ClientNotificationSchema, CommunityAccountSchema, CommunityEndpointSchema, CommunityEnvironmentSchema, CommunityExtensionDetailSchema, CommunityExtensionSummarySchema, CommunityGradeSchema, CommunityInstalledItemSchema, CommunityInstalledSchema, CommunityMyExtensionSchema, CommunityPermissionItemSchema, CommunityReleaseIdSchema, CommunityReleaseSchema, CommunityReviewReportSchema, CommunityReviewStatusSchema, CommunitySourceSchema, CommunityStatusSchema, ConfigSchemaDocumentSchema, ConfigSchemaMetaSchema, ConfigSchemaNodeSchema, ConnectionEventIdSchema, ConnectionIdSchema, ConnectionPanelRoleSchema, ConnectionTestResultSchema, DshCredentialRefSchema, DshCredentialViewSchema, DshCredentialsChangedSseDataSchema, DshNxtHostUiSchema, DshPluginCatalogEntrySchema, DshPluginEntryIdSchema, DshPluginOperationSseDataSchema, DshPluginPackageIdSchema, DshSettingsChangedSseDataSchema, DshSettingsMutationRequestSchema, DshSettingsNamespaceSchema, DshSettingsPathOperationSchema, DshSettingsPathSchema, DynamicChangedSseDataSchema, DynamicClientApprovalPolicySchema, EMPTY_CONFIG_SCHEMA, EMPTY_EXTENSION_UI_CONTRIBUTIONS, EXTENSION_CONTEXT_DYNAMIC_MAX_CHARS, EXTENSION_CONTEXT_STATIC_MAX_CHARS, EXTENSION_DATA_HOOK_PERMISSIONS, EXTENSION_INBOUND_HOOK_MAX_TIMEOUT_MS, EXTENSION_JOB_MAX_RUNTIME, EXTENSION_LLM_MAX_CALLS_PER_TURN, EXTENSION_LLM_MAX_OUTPUT_TOKENS, EXTENSION_SDK_LEVEL, EXTENSION_STORAGE_DEFAULT_QUOTA_BYTES, EXTENSION_STORAGE_MAX_QUOTA_BYTES, EXTENSION_STORAGE_SCOPES, EpisodeHandoffIdSchema, EpisodeIdSchema, ExtensionCapabilitiesSchema, ExtensionConfigDeclarationSchema, ExtensionContextContributionSchema, ExtensionDeclaredJobSchema, ExtensionIdSchema, ExtensionImportInspectionSchema, ExtensionInboundHookCapabilitySchema, ExtensionJobsCapabilitySchema, ExtensionLlmCapabilitySchema, ExtensionMcpCapabilitySchema, ExtensionMcpServerNameSchema, ExtensionMcpServerSchema, ExtensionMcpValueSchema, ExtensionNetworkCapabilitySchema, ExtensionNetworkDomainSchema, ExtensionPanelAnchorSchema, ExtensionPanelDeclarationSchema, ExtensionPlatformCapabilitySchema, ExtensionRequiresSchema, ExtensionRevisionIdSchema, ExtensionStorageCapabilitySchema, ExtensionStorageScopeSchema, ExtensionUiContributionsSchema, HOST_UI_KIT_COMPONENT_NAMES, HostApiContracts, HostApiErrorSchema, HostConnectionEventSchema, HostIconNameSchema, HostPageContributionSchema, HostPageIconSchema, HostSnapshotMessageSchema, HostSnapshotSchema, HostSseEventSchema, HostSseStatusDataSchema, HostSyncCursorSchema, HostUiKitComponentNameSchema, HostUiNavigationGroupSchema, HostUiNavigationItemSchema, HostUiNavigationModelSchema, HostUiNetworkOriginSchema, HostUiOwnerSchema, HostUiPageEntrySchema, HostUiPageGeometryEvidenceSchema, HostUiPageInstanceIdSchema, HostUiPagePreferencesSchema, HostUiPermissionDeclarationSchema, HostUiPermissionSchema, HostUpgradeSummarySchema, INSECURE_HTTP_MANAGEMENT_PAIR_PROOF_PREFIX, ImageUnderstandingPolicyApiSchema, InsecureHttpManagementChallengeResponseSchema, InstanceDescriptorSchema, InstanceDescriptorWireSchema, JsonValueSchema, LlmDiscoveredModelSchema, LlmModelInputModalitiesSchema, LlmProviderCredentialSchema, LlmProviderModelSchema, LlmProviderSettingsSchema, LlmProviderViewSchema, LogicalMessageIdSchema, MANAGEMENT_PAIR_PROOF_PREFIX, ManagementChallengeResponseSchema, ManagementDeviceEnrollmentRequestSchema, ManagementDeviceEnrollmentResponseSchema, ManagementDeviceIdSchema, ManagementDeviceViewSchema, ManagementSessionRequestSchema, ManagementSessionResponseSchema, McpServerFormSchema, MessagePartSchema, MessagePartsSchema, MessageRendererContributionSchema, NonEmptyMessagePartsSchema, NotificationEventKeySchema, NotificationSettingsViewSchema, OutboundIntentIdSchema, PROMPT_DOCUMENT_MAX_PLAIN_TEXT_LENGTH, PROMPT_DOCUMENT_MAX_REFERENCES, PanelContributionSchema, PanelDensitySchema, PhysicalDeliveryIdSchema, PlatformIdentityIdSchema, PlatformUserListResponseSchema, PromptDocumentV1Schema, PromptSegmentSchema, RICH_EXTENSION_MAX_BYTES, RichExtensionSchema, RichKindSchema, RichTargetUrlSchema, RuntimeCompatibilityDiagnosticSchema, ScheduledTaskIdSchema, ScheduledTaskSchema, ServerInstanceIdSchema, TestBarkNotificationRequestSchema, ToolViewContributionSchema, ToolViewDensitySchema, UpdateNotificationSettingsRequestSchema, WorkTreeOrderSchema, activityDurationMs, buildHostApiContractPath, buildHostApiPath, communityPublisherLabel, communityReviewLabel, configDescription, configFieldKind, configFields, configSchema, configSecretKeys, extensionCapabilitiesExpand, insecureHttpManagementPairProofMessage, managementPairProofMessage, mcpSecretFields, messagePartAssetId, messagePartAssetIds, messagePartsSearchText, normalizePromptDocument, parseConfigValue, parseJsonValue, parseMessageParts, promptDocumentFromText, promptDocumentPlainText, richPartContextText, summarizeExtensionCapabilities, validateConfigValue };
4693
+
4694
+ //# sourceMappingURL=index.mjs.map