@nekro-nxt/contracts 0.0.0-stage → 0.1.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,4475 @@
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 CommunityStatusSchema = z.object({
1301
+ communityUrl: z.string().url(),
1302
+ account: CommunityAccountSchema.nullable(),
1303
+ signedInAt: z.number().int().nullable()
1304
+ }).strict();
1305
+ const CommunityPermissionItemSchema = z.object({
1306
+ key: z.string().max(120),
1307
+ level: z.enum([
1308
+ "normal",
1309
+ "elevated",
1310
+ "high"
1311
+ ]),
1312
+ label: z.string().max(200),
1313
+ detail: z.string().max(2e3).optional()
1314
+ }).strict();
1315
+ const CommunityReleaseSchema = z.object({
1316
+ id: CommunityReleaseIdSchema,
1317
+ reviewStatus: CommunityReviewStatusSchema,
1318
+ grade: CommunityGradeSchema.nullable(),
1319
+ permissions: z.array(CommunityPermissionItemSchema).max(64),
1320
+ packageSize: z.number().int().nonnegative(),
1321
+ requiresSdk: z.number().int().positive().nullable(),
1322
+ notes: z.string().max(2e3),
1323
+ createdAt: z.number().int()
1324
+ }).strict();
1325
+ const CommunityExtensionSummarySchema = z.object({
1326
+ id: ExtensionIdSchema,
1327
+ scope: z.enum([
1328
+ "agent",
1329
+ "host-adapter",
1330
+ "host-ui"
1331
+ ]),
1332
+ displayName: z.string().max(200),
1333
+ summary: z.string().max(1e3),
1334
+ tags: z.array(z.string().max(40)).max(16),
1335
+ publisher: CommunityAccountSchema,
1336
+ latest: CommunityReleaseSchema.nullable(),
1337
+ downloads: z.number().int().nonnegative(),
1338
+ updatedAt: z.number().int(),
1339
+ pageUrl: z.string().url()
1340
+ }).strict();
1341
+ const CommunityExtensionDetailSchema = CommunityExtensionSummarySchema.extend({
1342
+ description: z.string().max(2e4),
1343
+ sourceUrl: z.string().url().nullable(),
1344
+ review: z.object({
1345
+ status: CommunityReviewStatusSchema,
1346
+ grade: CommunityGradeSchema.nullable(),
1347
+ summary: z.string().max(2e3).nullable(),
1348
+ highlights: z.array(z.object({
1349
+ severity: z.string().max(20),
1350
+ title: z.string().max(200)
1351
+ }).strict()).max(16)
1352
+ }).strict().nullable()
1353
+ }).strict();
1354
+ /** 安装者看到的审查标签:只描述审查发现,不做「安全」担保。 */
1355
+ const communityReviewLabel = (status) => {
1356
+ switch (status) {
1357
+ case "passed": return {
1358
+ tone: "ok",
1359
+ label: "审查通过"
1360
+ };
1361
+ case "passed_with_notes": return {
1362
+ tone: "accent",
1363
+ label: "审查通过,有建议"
1364
+ };
1365
+ case "flagged": return {
1366
+ tone: "warn",
1367
+ label: "有风险,待复审"
1368
+ };
1369
+ case "risk_confirmed": return {
1370
+ tone: "warn",
1371
+ label: "有风险"
1372
+ };
1373
+ case "held": return {
1374
+ tone: "bad",
1375
+ label: "暂停公开,待复审"
1376
+ };
1377
+ case "rejected": return {
1378
+ tone: "bad",
1379
+ label: "未通过"
1380
+ };
1381
+ case "pending":
1382
+ case "reviewing":
1383
+ case "incomplete": return {
1384
+ tone: "neutral",
1385
+ label: "风险未知"
1386
+ };
1387
+ }
1388
+ };
1389
+ //#endregion
1390
+ //#region src/host-api.ts
1391
+ const EmptyParamsSchema = z.object({}).strict();
1392
+ const NoRequestBodySchema = z.undefined();
1393
+ const NonEmptyStringSchema = z.string().trim().min(1);
1394
+ const DynamicIdSchema = NonEmptyStringSchema;
1395
+ const DynamicAttemptStatusSchema = z.enum([
1396
+ "awaiting-approval",
1397
+ "starting-host",
1398
+ "client-pending",
1399
+ "running",
1400
+ "waiting",
1401
+ "rejected",
1402
+ "failed",
1403
+ "cancelled",
1404
+ "stopped"
1405
+ ]);
1406
+ const DynamicHalfStateSchema = z.object({
1407
+ status: z.enum([
1408
+ "absent",
1409
+ "pending",
1410
+ "stopped",
1411
+ "running",
1412
+ "waiting",
1413
+ "failed"
1414
+ ]),
1415
+ waitingFor: z.array(z.string()),
1416
+ error: z.string().optional()
1417
+ }).strict();
1418
+ const DynamicAttemptErrorSchema = z.object({
1419
+ phase: z.enum([
1420
+ "approval",
1421
+ "host-load",
1422
+ "host-apply",
1423
+ "client-load",
1424
+ "client-apply",
1425
+ "client-render"
1426
+ ]),
1427
+ message: z.string(),
1428
+ stack: z.string().optional(),
1429
+ pluginId: DynamicIdSchema,
1430
+ packageId: DynamicIdSchema,
1431
+ pluginRunId: DynamicIdSchema
1432
+ }).strict();
1433
+ const DynamicLatestRunSchema = z.object({
1434
+ pluginRunId: DynamicIdSchema,
1435
+ packageId: DynamicIdSchema,
1436
+ mode: z.enum(["run", "update"]),
1437
+ status: DynamicAttemptStatusSchema,
1438
+ approvalRequestId: DynamicIdSchema.optional(),
1439
+ requiresApproval: z.boolean().optional(),
1440
+ host: DynamicHalfStateSchema,
1441
+ client: DynamicHalfStateSchema,
1442
+ error: DynamicAttemptErrorSchema.optional()
1443
+ }).strict();
1444
+ const AuthoringTaskStatusSchema = z.enum([
1445
+ "working",
1446
+ "awaiting-approval",
1447
+ "running",
1448
+ "ready",
1449
+ "repairing",
1450
+ "failed",
1451
+ "interrupted",
1452
+ "stopped",
1453
+ "completed"
1454
+ ]);
1455
+ const AuthoringAttemptStateSchema = z.enum([
1456
+ "drafting",
1457
+ "preflight-failed",
1458
+ "awaiting-approval",
1459
+ "starting-host",
1460
+ "loading-client",
1461
+ "verifying",
1462
+ "active",
1463
+ "failed",
1464
+ "rejected",
1465
+ "stopped"
1466
+ ]);
1467
+ const AuthoringAttemptSummarySchema = z.object({
1468
+ id: AuthoringAttemptIdSchema,
1469
+ ordinal: z.number().int().positive(),
1470
+ name: z.string(),
1471
+ purpose: z.string(),
1472
+ state: AuthoringAttemptStateSchema,
1473
+ riskDigest: z.string().regex(/^[a-f0-9]{64}$/u),
1474
+ host: DynamicHalfStateSchema,
1475
+ client: DynamicHalfStateSchema,
1476
+ error: z.object({
1477
+ phase: z.enum([
1478
+ "preflight",
1479
+ "approval",
1480
+ "host-load",
1481
+ "host-apply",
1482
+ "client-load",
1483
+ "client-apply",
1484
+ "client-render",
1485
+ "verification",
1486
+ "settlement",
1487
+ "restore"
1488
+ ]),
1489
+ message: z.string(),
1490
+ repairable: z.boolean()
1491
+ }).strict().optional(),
1492
+ createdAt: z.number().int().nonnegative(),
1493
+ settledAt: z.number().int().nonnegative().optional()
1494
+ }).strict();
1495
+ const AuthoringTaskSummarySchema = z.object({
1496
+ id: AuthoringTaskIdSchema,
1497
+ agentId: AgentIdSchema,
1498
+ channelId: ChannelIdSchema,
1499
+ episodeId: EpisodeIdSchema,
1500
+ title: z.string(),
1501
+ requirementSummary: z.string(),
1502
+ status: AuthoringTaskStatusSchema,
1503
+ approvalPolicy: z.enum(["risk-stable", "fully-automatic"]),
1504
+ approvedRiskDigest: z.string().regex(/^[a-f0-9]{64}$/u).optional(),
1505
+ revision: z.number().int().positive(),
1506
+ activeAttempt: AuthoringAttemptSummarySchema.optional(),
1507
+ candidateAttempt: AuthoringAttemptSummarySchema.optional(),
1508
+ /** Latest attempt that still carries product verification evidence; it can be restored as the candidate. */
1509
+ verifiedAttempt: AuthoringAttemptSummarySchema.optional(),
1510
+ createdAt: z.number().int().nonnegative(),
1511
+ updatedAt: z.number().int().nonnegative()
1512
+ }).strict();
1513
+ const ConnectionAliasInputSchema = z.string().trim().max(80).transform((value) => value || void 0);
1514
+ const ConnectionAliasOutputSchema = z.string().trim().min(1).max(80);
1515
+ const HostApiErrorSchema = z.object({ error: z.object({
1516
+ code: NonEmptyStringSchema,
1517
+ message: z.string()
1518
+ }).strict() }).strict();
1519
+ const AgentModelSchema = z.object({
1520
+ provider: NonEmptyStringSchema,
1521
+ model: NonEmptyStringSchema,
1522
+ reasoningEffort: NonEmptyStringSchema.optional()
1523
+ }).strict();
1524
+ const ImageUnderstandingPolicyApiSchema = z.object({
1525
+ history: z.object({
1526
+ mode: z.literal("persistent-distinct"),
1527
+ detail: z.enum([
1528
+ "low",
1529
+ "auto",
1530
+ "high"
1531
+ ]),
1532
+ restoreAfterCompaction: z.object({
1533
+ recentMessages: z.number().int().min(1).max(100),
1534
+ maxImages: z.number().int().min(1).max(50)
1535
+ }).strict()
1536
+ }).strict(),
1537
+ textModel: z.discriminatedUnion("mode", [z.object({ mode: z.literal("disabled") }).strict(), z.object({
1538
+ mode: z.literal("auxiliary"),
1539
+ model: AgentModelSchema,
1540
+ maxTokens: z.number().int().min(256).max(8192)
1541
+ }).strict()])
1542
+ }).strict();
1543
+ const AgentCapabilitiesSchema = z.object({
1544
+ subagents: z.boolean(),
1545
+ fileTools: z.boolean(),
1546
+ webSearch: z.boolean(),
1547
+ dynamicCreation: z.boolean(),
1548
+ developmentShell: z.boolean(),
1549
+ unrestrictedFileAccess: z.boolean(),
1550
+ /** Absent in older clients means on. */
1551
+ scheduledTasks: z.boolean().default(true)
1552
+ }).strict();
1553
+ const DynamicClientApprovalPolicySchema = z.enum(["manual", "automatic"]);
1554
+ const NotificationEventKeySchema = z.enum(["dynamic-client-approval-requested"]);
1555
+ const NotificationSettingsViewSchema = z.object({
1556
+ revision: z.number().int().positive().optional(),
1557
+ system: z.object({ enabled: z.boolean() }).strict(),
1558
+ bark: z.object({
1559
+ enabled: z.boolean(),
1560
+ serverUrl: z.url(),
1561
+ deviceKeyConfigured: z.boolean()
1562
+ }).strict(),
1563
+ events: z.record(NotificationEventKeySchema, z.boolean())
1564
+ }).strict();
1565
+ const UpdateNotificationSettingsRequestSchema = z.object({
1566
+ expectedRevision: z.number().int().positive().optional(),
1567
+ system: z.object({ enabled: z.boolean() }).strict(),
1568
+ bark: z.object({
1569
+ enabled: z.boolean(),
1570
+ serverUrl: z.url(),
1571
+ deviceKey: z.string().trim().min(1).max(2048).optional(),
1572
+ clearDeviceKey: z.boolean().optional()
1573
+ }).strict(),
1574
+ events: z.record(NotificationEventKeySchema, z.boolean())
1575
+ }).strict().refine((value) => !(value.bark.deviceKey !== void 0 && value.bark.clearDeviceKey === true), {
1576
+ message: "不能同时更新并清除 Bark Device Key。",
1577
+ path: ["bark"]
1578
+ });
1579
+ const TestBarkNotificationRequestSchema = z.object({
1580
+ serverUrl: z.url(),
1581
+ deviceKey: z.string().trim().min(1).max(2048).optional()
1582
+ }).strict();
1583
+ const ClientNotificationFeedResponseSchema = z.object({
1584
+ cursor: z.number().int().nonnegative(),
1585
+ notifications: z.array(ClientNotificationSchema)
1586
+ }).strict();
1587
+ const AgentRevisionRequestContentSchema = z.object({
1588
+ displayName: z.string().trim().min(1).max(80),
1589
+ persona: z.string().max(64 * 1024).default(""),
1590
+ personaDocument: PromptDocumentV1Schema.optional(),
1591
+ model: AgentModelSchema,
1592
+ imagePolicy: ImageUnderstandingPolicyApiSchema.optional(),
1593
+ dynamicClientApprovalPolicy: DynamicClientApprovalPolicySchema.optional()
1594
+ }).strict();
1595
+ const validatePersonaDocumentProjection = (value, context) => {
1596
+ if (value.personaDocument !== void 0 && promptDocumentPlainText(value.personaDocument) !== value.persona) context.addIssue({
1597
+ code: "custom",
1598
+ message: "人设文本必须与结构化人设文档一致。",
1599
+ path: ["personaDocument"],
1600
+ input: value
1601
+ });
1602
+ };
1603
+ const CreateAgentRequestSchema = AgentRevisionRequestContentSchema.extend({ capabilities: AgentCapabilitiesSchema.optional() }).superRefine((value, context) => {
1604
+ validatePersonaDocumentProjection(value, context);
1605
+ });
1606
+ const ReviseAgentRequestSchema = AgentRevisionRequestContentSchema.extend({ expectedCurrentRevisionId: AgentRevisionIdSchema }).superRefine((value, context) => {
1607
+ validatePersonaDocumentProjection(value, context);
1608
+ });
1609
+ const UpdateAgentCapabilitiesRequestSchema = AgentCapabilitiesSchema.partial().extend({ scheduledTasks: z.boolean().optional() }).strict().refine((value) => Object.values(value).some((entry) => entry !== void 0), "至少提供一个能力。");
1610
+ const TriggerPolicySchema = z.enum([
1611
+ "always",
1612
+ "mentioned-or-replied",
1613
+ "command",
1614
+ "observe-only"
1615
+ ]);
1616
+ const WorkTreeOrderSchema = z.object({
1617
+ agentIds: z.array(AgentIdSchema),
1618
+ channelIdsByAgent: z.record(AgentIdSchema, z.array(ChannelIdSchema)),
1619
+ unboundChannelIds: z.array(ChannelIdSchema)
1620
+ }).strict();
1621
+ const SnapshotMessagePartSchema = z.discriminatedUnion("type", [
1622
+ z.object({
1623
+ type: z.literal("text"),
1624
+ text: z.string()
1625
+ }).strict(),
1626
+ z.object({
1627
+ type: z.literal("mention"),
1628
+ memberId: ChannelMemberIdSchema,
1629
+ displayName: z.string().optional()
1630
+ }).strict(),
1631
+ z.object({
1632
+ type: z.literal("image"),
1633
+ assetId: AssetIdSchema,
1634
+ alt: z.string().optional()
1635
+ }).strict(),
1636
+ z.object({
1637
+ type: z.literal("file"),
1638
+ assetId: AssetIdSchema,
1639
+ name: z.string().optional()
1640
+ }).strict(),
1641
+ z.object({
1642
+ type: z.literal("audio"),
1643
+ assetId: AssetIdSchema
1644
+ }).strict(),
1645
+ z.object({
1646
+ type: z.literal("quote"),
1647
+ messageId: LogicalMessageIdSchema
1648
+ }).strict(),
1649
+ z.object({
1650
+ type: z.literal("rich"),
1651
+ adapterKey: z.string().trim().min(1).max(64),
1652
+ kind: z.string().trim().min(1).max(64),
1653
+ summary: z.string().trim().min(1).max(500),
1654
+ title: z.string().trim().min(1).max(200).optional(),
1655
+ source: z.string().trim().min(1).max(80).optional(),
1656
+ targetUrl: RichTargetUrlSchema.optional(),
1657
+ previewAssetId: AssetIdSchema.optional(),
1658
+ extension: RichExtensionSchema.optional()
1659
+ }).strict()
1660
+ ]);
1661
+ const HostSnapshotMessageSchema = z.object({
1662
+ id: z.union([ChannelEventIdSchema, OutboundIntentIdSchema]),
1663
+ channelId: ChannelIdSchema,
1664
+ role: z.enum([
1665
+ "member",
1666
+ "agent",
1667
+ "system"
1668
+ ]),
1669
+ parts: z.array(SnapshotMessagePartSchema),
1670
+ sender: z.object({
1671
+ memberId: ChannelMemberIdSchema,
1672
+ displayName: z.string().optional()
1673
+ }).strict().optional(),
1674
+ mentionedConnectionAccount: z.boolean().optional(),
1675
+ activityKey: AdapterActivityKeySchema.optional(),
1676
+ targetLogicalMessageId: LogicalMessageIdSchema.optional(),
1677
+ occurredAt: z.number().finite(),
1678
+ deliveryState: z.enum([
1679
+ "planned",
1680
+ "sending",
1681
+ "sent",
1682
+ "partially-sent",
1683
+ "failed",
1684
+ "unknown"
1685
+ ]).optional(),
1686
+ /** Latest administrator resolution of an unsettled delivery; history keeps the original receipt state. */
1687
+ deliveryResolution: z.object({
1688
+ action: z.enum(["retry", "confirm-delivered"]),
1689
+ resolvedAt: z.number().int().safe().nonnegative()
1690
+ }).strict().optional(),
1691
+ origin: z.enum(["admin-console"]).optional(),
1692
+ /** What the agent's inbound hooks decided for this message, when anything differs from the default. */
1693
+ inboundHook: z.object({
1694
+ trigger: z.enum([
1695
+ "default",
1696
+ "suppress",
1697
+ "force"
1698
+ ]),
1699
+ hidden: z.boolean(),
1700
+ annotation: z.string().optional(),
1701
+ extensions: z.array(z.string()),
1702
+ problems: z.array(z.string()).optional()
1703
+ }).strict().optional(),
1704
+ /** A scheduled task came due: a Host fact shown as a notice, not a member message. */
1705
+ scheduledTask: z.object({
1706
+ label: z.string(),
1707
+ extensionName: z.string().optional(),
1708
+ note: z.string().optional()
1709
+ }).strict().optional()
1710
+ }).strict();
1711
+ const HostConnectionEventSchema = z.object({
1712
+ id: ConnectionEventIdSchema,
1713
+ connectionId: ConnectionIdSchema,
1714
+ activityKey: AdapterActivityKeySchema,
1715
+ summary: z.string(),
1716
+ actor: z.object({
1717
+ identityId: PlatformIdentityIdSchema,
1718
+ displayName: z.string().optional()
1719
+ }).strict().optional(),
1720
+ subject: z.object({
1721
+ identityId: PlatformIdentityIdSchema,
1722
+ displayName: z.string().optional()
1723
+ }).strict().optional(),
1724
+ occurredAt: z.number().int().safe().nonnegative()
1725
+ }).strict();
1726
+ const PlatformUserChannelPreviewSchema = z.object({
1727
+ id: ChannelIdSchema,
1728
+ displayName: z.string().trim().min(1).max(120).optional(),
1729
+ kind: z.enum([
1730
+ "internal",
1731
+ "direct",
1732
+ "group"
1733
+ ])
1734
+ }).strict();
1735
+ const PlatformUserFacetAdapterSchema = z.object({
1736
+ key: NonEmptyStringSchema,
1737
+ displayName: NonEmptyStringSchema,
1738
+ userCount: z.number().int().nonnegative()
1739
+ }).strict();
1740
+ const PlatformUserFacetConnectionSchema = z.object({
1741
+ id: ConnectionIdSchema,
1742
+ adapterKey: NonEmptyStringSchema,
1743
+ displayName: NonEmptyStringSchema,
1744
+ userCount: z.number().int().nonnegative()
1745
+ }).strict();
1746
+ const PlatformUserListResponseSchema = z.object({
1747
+ total: z.number().int().nonnegative(),
1748
+ items: z.array(z.object({
1749
+ identityId: PlatformIdentityIdSchema,
1750
+ displayName: z.string().trim().min(1).max(120).optional(),
1751
+ adapter: z.object({
1752
+ key: NonEmptyStringSchema,
1753
+ displayName: NonEmptyStringSchema
1754
+ }).strict(),
1755
+ connection: z.object({
1756
+ id: ConnectionIdSchema,
1757
+ displayName: NonEmptyStringSchema
1758
+ }).strict(),
1759
+ activeChannelCount: z.number().int().nonnegative(),
1760
+ channelPreview: z.array(PlatformUserChannelPreviewSchema).max(3),
1761
+ historicalOnly: z.boolean()
1762
+ }).strict()),
1763
+ facets: z.object({
1764
+ adapters: z.array(PlatformUserFacetAdapterSchema),
1765
+ connections: z.array(PlatformUserFacetConnectionSchema)
1766
+ }).strict(),
1767
+ nextCursor: PlatformIdentityIdSchema.optional()
1768
+ }).strict();
1769
+ const ChannelFactSseItemSchema = z.object({
1770
+ kind: z.enum(["inbound", "outbound"]),
1771
+ sourceId: z.union([ChannelEventIdSchema, OutboundIntentIdSchema]),
1772
+ message: HostSnapshotMessageSchema
1773
+ }).strict();
1774
+ const ChannelFactSseDataSchema = z.object({
1775
+ channelId: ChannelIdSchema,
1776
+ revision: z.number().int().positive(),
1777
+ items: z.array(ChannelFactSseItemSchema).min(1)
1778
+ }).strict();
1779
+ const ChannelRuntimePhaseSchema = z.enum([
1780
+ "idle",
1781
+ "thinking",
1782
+ "using-tool",
1783
+ "waiting-input",
1784
+ "unavailable"
1785
+ ]);
1786
+ const ChannelRuntimeUsageSchema = z.object({
1787
+ inputTokens: z.number().int().nonnegative(),
1788
+ outputTokens: z.number().int().nonnegative(),
1789
+ totalTokens: z.number().int().nonnegative().optional(),
1790
+ cacheReadTokens: z.number().int().nonnegative().optional(),
1791
+ cacheWriteTokens: z.number().int().nonnegative().optional(),
1792
+ reasoningTokens: z.number().int().nonnegative().optional()
1793
+ }).strict();
1794
+ const ChannelRuntimeToolSchema = z.object({
1795
+ callId: NonEmptyStringSchema,
1796
+ name: NonEmptyStringSchema,
1797
+ displayName: NonEmptyStringSchema,
1798
+ state: z.enum([
1799
+ "running",
1800
+ "succeeded",
1801
+ "failed"
1802
+ ]),
1803
+ inputPreview: z.string().optional(),
1804
+ resultPreview: z.string().optional(),
1805
+ wroteToChannel: z.boolean().optional(),
1806
+ deliveryState: z.enum([
1807
+ "sent",
1808
+ "partially-sent",
1809
+ "failed",
1810
+ "unknown"
1811
+ ]).optional(),
1812
+ durationMs: z.number().int().nonnegative().optional()
1813
+ }).strict();
1814
+ const ChannelRuntimeStepSchema = z.object({
1815
+ step: z.number().int().nonnegative(),
1816
+ tools: z.array(ChannelRuntimeToolSchema),
1817
+ internalOutput: z.object({
1818
+ kind: z.literal("internal-output"),
1819
+ text: z.string().optional(),
1820
+ reasoning: z.string().optional()
1821
+ }).strict().optional(),
1822
+ durationMs: z.number().int().nonnegative().optional(),
1823
+ firstTokenMs: z.number().int().nonnegative().optional(),
1824
+ usage: ChannelRuntimeUsageSchema.optional()
1825
+ }).strict();
1826
+ const ChannelRuntimeTurnSchema = z.object({
1827
+ turn: z.number().int().nonnegative(),
1828
+ state: z.enum([
1829
+ "in-progress",
1830
+ "completed",
1831
+ "unreplied",
1832
+ "aborted",
1833
+ "error",
1834
+ "max-tokens",
1835
+ "interrupted"
1836
+ ]),
1837
+ producedReply: z.boolean(),
1838
+ responseState: z.enum([
1839
+ "not-required",
1840
+ "pending",
1841
+ "sent",
1842
+ "finished",
1843
+ "protocol-failed",
1844
+ "interrupted"
1845
+ ]),
1846
+ error: z.object({
1847
+ code: NonEmptyStringSchema,
1848
+ message: z.string()
1849
+ }).strict().optional(),
1850
+ steps: z.array(ChannelRuntimeStepSchema),
1851
+ durationMs: z.number().int().nonnegative().optional(),
1852
+ /** Session log time the turn opened. */
1853
+ startedAt: z.number().int().safe().nonnegative().optional(),
1854
+ /** Session log time the turn closed; absent while it is still running. */
1855
+ endedAt: z.number().int().safe().nonnegative().optional(),
1856
+ /** Newest Channel Event of the admission that opened this turn; absent for non-channel turns. */
1857
+ triggerEventId: ChannelEventIdSchema.optional()
1858
+ }).strict();
1859
+ const ChannelRuntimeOccupancySchema = z.object({
1860
+ projectedTokens: z.number().int().nonnegative(),
1861
+ contextWindow: z.number().int().positive(),
1862
+ breakdown: z.object({
1863
+ systemTokens: z.number().int().nonnegative(),
1864
+ toolsTokens: z.number().int().nonnegative(),
1865
+ messageTokens: z.number().int().nonnegative()
1866
+ }).strict().optional()
1867
+ }).strict();
1868
+ const ChannelRuntimeCacheSampleSchema = z.object({
1869
+ turn: z.number().int().nonnegative(),
1870
+ step: z.number().int().nonnegative(),
1871
+ at: z.number().nonnegative().optional(),
1872
+ uncachedInputTokens: z.number().int().nonnegative(),
1873
+ cacheReadTokens: z.number().int().nonnegative().optional(),
1874
+ cacheWriteTokens: z.number().int().nonnegative().optional()
1875
+ }).strict();
1876
+ const ChannelRuntimeCacheSchema = z.object({
1877
+ scope: z.literal("episode"),
1878
+ aggregate: z.object({
1879
+ usageRequestCount: z.number().int().nonnegative(),
1880
+ observedRequestCount: z.number().int().nonnegative(),
1881
+ shareRequestCount: z.number().int().nonnegative(),
1882
+ hitRequestCount: z.number().int().nonnegative(),
1883
+ uncachedInputTokens: z.number().int().nonnegative(),
1884
+ cacheReadTokens: z.number().int().nonnegative(),
1885
+ cacheWriteTokens: z.number().int().nonnegative(),
1886
+ averageRequestReadShare: z.number().min(0).max(1).optional()
1887
+ }).strict(),
1888
+ recent: z.object({
1889
+ windowSize: z.number().int().positive(),
1890
+ samples: z.array(ChannelRuntimeCacheSampleSchema)
1891
+ }).strict()
1892
+ }).strict();
1893
+ const ChannelRuntimePerformanceSampleSchema = z.object({
1894
+ turn: z.number().int().nonnegative(),
1895
+ step: z.number().int().nonnegative(),
1896
+ at: z.number().nonnegative().optional(),
1897
+ firstTokenMs: z.number().int().nonnegative().optional(),
1898
+ decodeMs: z.number().int().nonnegative().optional(),
1899
+ outputTokens: z.number().int().nonnegative().optional()
1900
+ }).strict();
1901
+ const ChannelRuntimePerformanceSchema = z.object({
1902
+ scope: z.literal("episode"),
1903
+ aggregate: z.object({
1904
+ steps: z.number().int().nonnegative(),
1905
+ llmMs: z.number().nonnegative(),
1906
+ toolMs: z.number().nonnegative(),
1907
+ ttftMs: z.number().nonnegative(),
1908
+ ttftSteps: z.number().int().nonnegative(),
1909
+ decodeMs: z.number().nonnegative(),
1910
+ decodeTokens: z.number().int().nonnegative(),
1911
+ decodeSteps: z.number().int().nonnegative(),
1912
+ retryCount: z.number().int().nonnegative(),
1913
+ retryDelayMs: z.number().nonnegative()
1914
+ }).strict(),
1915
+ recent: z.object({
1916
+ windowSize: z.number().int().positive(),
1917
+ samples: z.array(ChannelRuntimePerformanceSampleSchema)
1918
+ }).strict()
1919
+ }).strict();
1920
+ const ChannelRuntimeProjectionSchema = z.object({
1921
+ channelId: ChannelIdSchema,
1922
+ agentId: AgentIdSchema.optional(),
1923
+ episodeId: EpisodeIdSchema.optional(),
1924
+ phase: ChannelRuntimePhaseSchema,
1925
+ summary: z.string(),
1926
+ pendingInjectCount: z.number().int().nonnegative(),
1927
+ occupancy: ChannelRuntimeOccupancySchema.optional(),
1928
+ cache: ChannelRuntimeCacheSchema.optional(),
1929
+ performance: ChannelRuntimePerformanceSchema.optional(),
1930
+ turns: z.array(ChannelRuntimeTurnSchema)
1931
+ }).strict();
1932
+ const ChannelRuntimeSseDataSchema = ChannelRuntimeProjectionSchema.extend({
1933
+ revision: z.number().int().positive(),
1934
+ truncated: z.boolean().optional()
1935
+ }).strict();
1936
+ const AdapterConnectionCreationSchema = z.object({
1937
+ mode: z.enum(["schema-form", "qr-login"]),
1938
+ actionLabel: z.string().trim().min(1).optional(),
1939
+ pendingLabel: z.string().trim().min(1).optional()
1940
+ }).strict();
1941
+ const AdapterConnectionDescriptorSchema = z.object({
1942
+ key: NonEmptyStringSchema,
1943
+ displayName: z.string(),
1944
+ description: z.string(),
1945
+ provisioning: z.enum(["user-created", "system-singleton"]),
1946
+ aliasEditable: z.boolean(),
1947
+ channelDiscovery: z.enum(["host-created", "adapter-observed"]),
1948
+ channelKinds: z.array(z.enum([
1949
+ "internal",
1950
+ "direct",
1951
+ "group"
1952
+ ])).min(1),
1953
+ activities: z.array(z.object({
1954
+ key: AdapterActivityKeySchema,
1955
+ scope: z.enum(["channel", "connection"]),
1956
+ displayName: z.string().trim().min(1),
1957
+ description: z.string().trim().min(1),
1958
+ icon: HostIconNameSchema.optional(),
1959
+ triggerable: z.boolean(),
1960
+ channelKinds: z.array(z.enum([
1961
+ "internal",
1962
+ "direct",
1963
+ "group"
1964
+ ])).optional()
1965
+ }).strict()),
1966
+ features: z.object({ processingFeedback: z.object({ channelKinds: z.array(z.enum(["direct", "group"])).min(1) }).strict().optional() }).strict(),
1967
+ diagnostics: z.object({
1968
+ receive: z.boolean(),
1969
+ send: z.boolean()
1970
+ }).strict(),
1971
+ creation: AdapterConnectionCreationSchema.optional(),
1972
+ /** Typed platform actions the Adapter offers to agent extensions (`ctx.nxt.platform`). */
1973
+ platformActions: z.array(z.object({
1974
+ name: z.string().regex(/^[a-z0-9_]{1,64}$/u),
1975
+ title: z.string(),
1976
+ description: z.string(),
1977
+ risk: z.enum(["low", "admin"]),
1978
+ channelKinds: z.array(z.enum(["direct", "group"])).min(1),
1979
+ parameters: z.object({
1980
+ type: z.literal("object"),
1981
+ properties: z.record(z.string(), JsonValueSchema),
1982
+ required: z.array(z.string()).optional()
1983
+ }).strict()
1984
+ }).strict()).optional(),
1985
+ rawApi: z.object({ description: z.string() }).strict().optional(),
1986
+ configSchema: ConfigSchemaDocumentSchema
1987
+ }).strict();
1988
+ const AdapterCapabilityStateSchema = z.object({
1989
+ state: z.enum([
1990
+ "available",
1991
+ "disabled",
1992
+ "unsupported",
1993
+ "degraded",
1994
+ "unknown"
1995
+ ]),
1996
+ reason: z.string().optional()
1997
+ }).strict();
1998
+ const ActivityTriggerOverridesSchema = z.record(AdapterActivityKeySchema, z.boolean());
1999
+ const HostSyncCursorSchema = z.object({
2000
+ epoch: z.string().regex(/^[a-zA-Z0-9_-]{1,100}$/u),
2001
+ sequence: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER)
2002
+ }).strict();
2003
+ const AgentAppearanceSchema = z.object({
2004
+ hue: z.number().int().min(0).max(359).optional(),
2005
+ avatarAssetId: AssetIdSchema.optional()
2006
+ }).strict();
2007
+ /** Upper bound of a reported unread count; `unreadCapped` marks that more exist. */
2008
+ const CHANNEL_UNREAD_COUNT_CAP = 99;
2009
+ const ChannelActivitySummarySchema = z.object({
2010
+ lastActivityAt: z.number().int().safe().nonnegative().optional(),
2011
+ lastMessage: z.object({
2012
+ role: z.enum([
2013
+ "member",
2014
+ "agent",
2015
+ "admin",
2016
+ "system"
2017
+ ]),
2018
+ author: z.string().max(120),
2019
+ preview: z.string().max(160),
2020
+ occurredAt: z.number().int().safe().nonnegative()
2021
+ }).strict().optional(),
2022
+ unreadCount: z.number().int().nonnegative().max(99),
2023
+ unreadCapped: z.boolean()
2024
+ }).strict();
2025
+ const AttentionItemSchema = z.object({
2026
+ /** Stable fingerprint; a recurrence of the same condition gets a new fingerprint. */
2027
+ id: z.string().min(1).max(200),
2028
+ kind: z.enum([
2029
+ "delivery-unconfirmed",
2030
+ "delivery-failed",
2031
+ "turn-failed",
2032
+ "authoring-approval",
2033
+ "connection-unhealthy",
2034
+ "agent-model-unavailable",
2035
+ "agent-vision-unavailable"
2036
+ ]),
2037
+ severity: z.enum([
2038
+ "critical",
2039
+ "warning",
2040
+ "info"
2041
+ ]),
2042
+ subject: z.object({
2043
+ kind: z.enum([
2044
+ "outbound",
2045
+ "channel",
2046
+ "authoring-task",
2047
+ "connection",
2048
+ "agent"
2049
+ ]),
2050
+ id: NonEmptyStringSchema
2051
+ }).strict(),
2052
+ related: z.object({
2053
+ channelId: ChannelIdSchema.optional(),
2054
+ agentId: AgentIdSchema.optional(),
2055
+ connectionId: ConnectionIdSchema.optional(),
2056
+ taskId: AuthoringTaskIdSchema.optional(),
2057
+ outboundId: OutboundIntentIdSchema.optional()
2058
+ }).strict(),
2059
+ title: z.string().min(1).max(120),
2060
+ detail: z.string().max(400),
2061
+ action: z.object({
2062
+ kind: z.enum([
2063
+ "open-channel",
2064
+ "resolve-delivery",
2065
+ "open-authoring-task",
2066
+ "open-connection",
2067
+ "open-agent"
2068
+ ]),
2069
+ label: z.string().min(1).max(40)
2070
+ }).strict(),
2071
+ occurredAt: z.number().int().safe().nonnegative()
2072
+ }).strict();
2073
+ const AttentionListSchema = z.object({
2074
+ revision: z.string().min(1),
2075
+ items: z.array(AttentionItemSchema).max(200)
2076
+ }).strict();
2077
+ const ChannelPendingContextSchema = z.object({
2078
+ channelId: ChannelIdSchema,
2079
+ episodeId: EpisodeIdSchema.optional(),
2080
+ items: z.array(z.object({
2081
+ admissionId: NonEmptyStringSchema,
2082
+ /** `next-step`: injected at the next safe step boundary; `next-turn`: waits for a later turn. */
2083
+ target: z.enum(["next-step", "next-turn"]),
2084
+ events: z.array(z.object({
2085
+ eventId: ChannelEventIdSchema,
2086
+ author: z.string().max(120),
2087
+ preview: z.string().max(160),
2088
+ receivedAt: z.number().int().safe().nonnegative()
2089
+ }).strict())
2090
+ }).strict())
2091
+ }).strict();
2092
+ const ACTIVITY_MAX_WINDOW_MS = 1440 * 60 * 1e3;
2093
+ const ACTIVITY_MIN_BUCKET_MS = 60 * 1e3;
2094
+ const ACTIVITY_MAX_BUCKETS = 288;
2095
+ const ActivityDurationSchema = z.string().regex(/^[1-9][0-9]{0,4}[mh]$/u);
2096
+ const activityDurationMs = (value) => {
2097
+ const amount = Number(value.slice(0, -1));
2098
+ return value.endsWith("h") ? amount * 60 * 60 * 1e3 : amount * 60 * 1e3;
2099
+ };
2100
+ const ActivityQuerySchema = z.object({
2101
+ window: ActivityDurationSchema.default("2h"),
2102
+ bucket: ActivityDurationSchema.default("5m")
2103
+ }).strict().superRefine((value, context) => {
2104
+ const window = activityDurationMs(value.window);
2105
+ const bucket = activityDurationMs(value.bucket);
2106
+ if (window > 864e5) context.addIssue({
2107
+ code: "custom",
2108
+ path: ["window"],
2109
+ message: "统计窗口不能超过 24 小时。"
2110
+ });
2111
+ if (bucket < 6e4) context.addIssue({
2112
+ code: "custom",
2113
+ path: ["bucket"],
2114
+ message: "统计间隔不能小于 1 分钟。"
2115
+ });
2116
+ if (bucket > window) context.addIssue({
2117
+ code: "custom",
2118
+ path: ["bucket"],
2119
+ message: "统计间隔不能大于统计窗口。"
2120
+ });
2121
+ if (window / bucket > 288) context.addIssue({
2122
+ code: "custom",
2123
+ path: ["bucket"],
2124
+ message: `统计桶不能超过 288 个。`
2125
+ });
2126
+ });
2127
+ const ChannelActivitySeriesSchema = z.object({
2128
+ from: z.number().int().safe().nonnegative(),
2129
+ to: z.number().int().safe().nonnegative(),
2130
+ bucketMs: z.number().int().positive(),
2131
+ channels: z.array(z.object({
2132
+ channelId: ChannelIdSchema,
2133
+ counts: z.array(z.number().int().nonnegative()).max(288),
2134
+ total: z.number().int().nonnegative()
2135
+ }).strict())
2136
+ }).strict();
2137
+ const ScheduledTaskIdSchema = z.string().regex(/^job_[0-9A-Za-z]+$/u);
2138
+ /**
2139
+ * One scheduled task of an agent in one channel. `chat` tasks come from the agent's scheduling tools; `declared` and
2140
+ * `runtime` tasks belong to an extension (Manifest plan or `ctx.nxt.jobs`).
2141
+ */
2142
+ const ScheduledTaskSchema = z.object({
2143
+ id: ScheduledTaskIdSchema,
2144
+ agentId: AgentIdSchema,
2145
+ channelId: ChannelIdSchema,
2146
+ source: z.enum([
2147
+ "chat",
2148
+ "declared",
2149
+ "runtime"
2150
+ ]),
2151
+ extensionId: ExtensionIdSchema.optional(),
2152
+ extensionName: z.string().optional(),
2153
+ label: z.string(),
2154
+ note: z.string().optional(),
2155
+ schedule: z.discriminatedUnion("kind", [z.object({
2156
+ kind: z.literal("once"),
2157
+ at: z.number().int().safe()
2158
+ }).strict(), z.object({
2159
+ kind: z.literal("cron"),
2160
+ cron: z.string(),
2161
+ timezone: z.string()
2162
+ }).strict()]),
2163
+ /** `inactive`: the owning extension is disabled for this agent, so the task stays silent. */
2164
+ state: z.enum([
2165
+ "scheduled",
2166
+ "paused",
2167
+ "finished",
2168
+ "inactive"
2169
+ ]),
2170
+ nextRunAt: z.number().int().safe().optional(),
2171
+ lastFiredAt: z.number().int().safe().optional(),
2172
+ createdAt: z.number().int().safe()
2173
+ }).strict();
2174
+ const HostSnapshotSchema = z.object({
2175
+ upgrade: HostUpgradeSummarySchema.optional(),
2176
+ cursor: HostSyncCursorSchema,
2177
+ diagnosticsSampledAt: z.number().int().nonnegative(),
2178
+ productMetadata: z.object({
2179
+ displayName: NonEmptyStringSchema,
2180
+ organizationName: NonEmptyStringSchema,
2181
+ version: NonEmptyStringSchema,
2182
+ releaseId: NonEmptyStringSchema,
2183
+ repositoryUrl: z.url(),
2184
+ licenseSpdx: NonEmptyStringSchema.nullable(),
2185
+ dshVersion: NonEmptyStringSchema.optional()
2186
+ }).strict().optional(),
2187
+ models: z.array(z.object({
2188
+ provider: NonEmptyStringSchema,
2189
+ providerName: NonEmptyStringSchema,
2190
+ id: NonEmptyStringSchema,
2191
+ name: z.string(),
2192
+ description: z.string().optional(),
2193
+ inputModalities: z.array(z.string()).optional()
2194
+ }).strict()),
2195
+ capabilityAvailability: z.object({
2196
+ subagents: z.object({ available: z.boolean() }).strict(),
2197
+ webSearch: z.object({
2198
+ provider: z.literal("deepseek-official"),
2199
+ available: z.boolean(),
2200
+ credentialConfigured: z.boolean(),
2201
+ credentialReference: NonEmptyStringSchema,
2202
+ maxUsesPerCall: z.number().int().nonnegative(),
2203
+ maxResultsPerCall: z.number().int().nonnegative(),
2204
+ timeoutMs: z.number().int().nonnegative()
2205
+ }).strict()
2206
+ }).strict(),
2207
+ connectionAdapters: z.array(AdapterConnectionDescriptorSchema),
2208
+ notificationSettings: NotificationSettingsViewSchema,
2209
+ agents: z.array(z.object({
2210
+ id: AgentIdSchema,
2211
+ displayName: z.string(),
2212
+ persona: z.string(),
2213
+ personaDocument: PromptDocumentV1Schema,
2214
+ model: AgentModelSchema,
2215
+ capabilities: AgentCapabilitiesSchema,
2216
+ imagePolicy: ImageUnderstandingPolicyApiSchema,
2217
+ dynamicClientApprovalPolicy: DynamicClientApprovalPolicySchema,
2218
+ imageDiagnostics: z.object({
2219
+ route: z.object({
2220
+ mode: z.enum([
2221
+ "direct",
2222
+ "delegated",
2223
+ "unavailable"
2224
+ ]),
2225
+ provider: z.string().optional(),
2226
+ model: z.string().optional()
2227
+ }).strict(),
2228
+ activeSessions: z.number().int().nonnegative(),
2229
+ residentImages: z.number().int().nonnegative(),
2230
+ duplicateImagesSkipped: z.number().int().nonnegative(),
2231
+ lastInspection: z.object({
2232
+ mode: z.enum(["direct", "delegated"]),
2233
+ imageCount: z.number().int().nonnegative(),
2234
+ provider: z.string().optional(),
2235
+ model: z.string().optional(),
2236
+ cacheHit: z.boolean(),
2237
+ usage: ChannelRuntimeUsageSchema.optional(),
2238
+ errorCode: z.string().optional()
2239
+ }).strict().optional(),
2240
+ lastRestoration: z.object({
2241
+ compactionId: z.string(),
2242
+ candidateCount: z.number().int().nonnegative(),
2243
+ restoredCount: z.number().int().nonnegative(),
2244
+ skippedCount: z.number().int().nonnegative(),
2245
+ error: z.string().optional()
2246
+ }).strict().optional(),
2247
+ blockers: z.array(z.string())
2248
+ }).strict(),
2249
+ currentRevisionId: AgentRevisionIdSchema,
2250
+ runtimeStatus: z.enum(["idle", "running"]),
2251
+ runtimePhase: ChannelRuntimePhaseSchema.default("idle"),
2252
+ createdAt: z.number().finite(),
2253
+ channels: z.array(ChannelIdSchema),
2254
+ appearance: AgentAppearanceSchema.default({})
2255
+ }).strict()),
2256
+ channels: z.array(z.object({
2257
+ id: ChannelIdSchema,
2258
+ connectionId: ConnectionIdSchema,
2259
+ platformChannelId: NonEmptyStringSchema,
2260
+ kind: z.enum([
2261
+ "internal",
2262
+ "group",
2263
+ "direct"
2264
+ ]),
2265
+ displayName: z.string().optional(),
2266
+ boundAgentId: AgentIdSchema.optional(),
2267
+ runtimePhase: ChannelRuntimePhaseSchema.default("idle"),
2268
+ activity: ChannelActivitySummarySchema.default({
2269
+ unreadCount: 0,
2270
+ unreadCapped: false
2271
+ }),
2272
+ bindings: z.array(z.object({
2273
+ channelId: ChannelIdSchema,
2274
+ agentId: AgentIdSchema,
2275
+ triggerPolicy: TriggerPolicySchema,
2276
+ processingFeedback: z.enum(["auto", "off"]).default("auto"),
2277
+ activityTriggerOverrides: ActivityTriggerOverridesSchema.default({}),
2278
+ boundAt: z.number().int().safe().nonnegative()
2279
+ }).strict())
2280
+ }).strict()),
2281
+ workTreeOrder: WorkTreeOrderSchema.default({
2282
+ agentIds: [],
2283
+ channelIdsByAgent: {},
2284
+ unboundChannelIds: []
2285
+ }),
2286
+ messages: z.array(HostSnapshotMessageSchema),
2287
+ connections: z.array(z.object({
2288
+ id: ConnectionIdSchema,
2289
+ adapterKey: NonEmptyStringSchema,
2290
+ alias: ConnectionAliasOutputSchema.optional(),
2291
+ activityTriggerDefaults: z.array(AdapterActivityKeySchema).default([]),
2292
+ status: z.object({
2293
+ state: z.enum([
2294
+ "stopped",
2295
+ "connecting",
2296
+ "connected",
2297
+ "reconnecting",
2298
+ "failed"
2299
+ ]),
2300
+ message: z.string().optional(),
2301
+ credentialConfigured: z.boolean(),
2302
+ proactiveSend: z.boolean(),
2303
+ accountReference: z.string().optional(),
2304
+ implementation: z.object({
2305
+ name: z.string().optional(),
2306
+ version: z.string().optional(),
2307
+ protocolVersion: z.string().optional()
2308
+ }).strict().optional(),
2309
+ optionalCapabilities: z.record(z.string(), z.enum([
2310
+ "unknown",
2311
+ "available",
2312
+ "unsupported",
2313
+ "degraded"
2314
+ ])).optional(),
2315
+ activities: z.record(z.string(), AdapterCapabilityStateSchema).default({}),
2316
+ processingFeedback: AdapterCapabilityStateSchema.optional()
2317
+ }).strict().default({
2318
+ state: "stopped",
2319
+ credentialConfigured: false,
2320
+ proactiveSend: false,
2321
+ activities: {}
2322
+ }),
2323
+ channelCount: z.number().int().nonnegative(),
2324
+ knownChannels: z.array(z.object({
2325
+ id: ChannelIdSchema,
2326
+ name: z.string(),
2327
+ kind: z.enum([
2328
+ "internal",
2329
+ "group",
2330
+ "direct"
2331
+ ])
2332
+ }).strict()),
2333
+ lastInbound: z.object({
2334
+ channelId: ChannelIdSchema,
2335
+ platformMessageId: NonEmptyStringSchema,
2336
+ receivedAt: z.number().int().safe().nonnegative()
2337
+ }).strict().optional(),
2338
+ receiveTest: z.lazy(() => ConnectionTestResultSchema).optional(),
2339
+ sendTest: z.lazy(() => ConnectionTestResultSchema).optional(),
2340
+ configuration: z.record(z.string(), z.union([
2341
+ z.string(),
2342
+ z.number(),
2343
+ z.boolean()
2344
+ ])).default({})
2345
+ }).strict()),
2346
+ archivedConnections: z.array(z.object({
2347
+ id: ConnectionIdSchema,
2348
+ adapterKey: NonEmptyStringSchema,
2349
+ alias: ConnectionAliasOutputSchema.optional(),
2350
+ channelCount: z.number().int().nonnegative(),
2351
+ archivedAt: z.number().int().safe().nonnegative()
2352
+ }).strict()).default([]),
2353
+ extensions: z.array(z.object({
2354
+ id: ExtensionIdSchema,
2355
+ scope: z.enum([
2356
+ "agent",
2357
+ "host-adapter",
2358
+ "host-ui"
2359
+ ]),
2360
+ slug: NonEmptyStringSchema,
2361
+ displayName: z.string(),
2362
+ description: z.string(),
2363
+ createdByAgentId: AgentIdSchema.optional(),
2364
+ revisions: z.array(z.object({
2365
+ id: ExtensionRevisionIdSchema,
2366
+ revisionNumber: z.number().int().positive(),
2367
+ format: z.enum(["current", "unavailable"]).optional(),
2368
+ ui: ExtensionUiContributionsSchema.default(EMPTY_EXTENSION_UI_CONTRIBUTIONS),
2369
+ configSchema: ConfigSchemaDocumentSchema.optional(),
2370
+ createdAt: z.number().int().safe().nonnegative(),
2371
+ scope: z.enum([
2372
+ "agent",
2373
+ "host-adapter",
2374
+ "host-ui"
2375
+ ]),
2376
+ contributions: z.array(z.string()),
2377
+ verification: z.object({
2378
+ verifiedAt: z.number().int().nonnegative(),
2379
+ dshVersion: z.string(),
2380
+ contractVersion: z.string(),
2381
+ hostBuilt: z.boolean(),
2382
+ clientBuilt: z.boolean(),
2383
+ buildKey: z.string(),
2384
+ toolInvocationCount: z.number().int().nonnegative(),
2385
+ rpcMethods: z.array(z.string()),
2386
+ renderedPanels: z.array(z.string()).default([]),
2387
+ renderedToolViews: z.array(z.string()).default([]),
2388
+ renderedMessageRenderers: z.array(z.string()).default([]),
2389
+ renderedPages: z.array(HostPageContributionSchema).max(8).optional(),
2390
+ usedUiComponents: z.array(HostUiKitComponentNameSchema).optional(),
2391
+ pageGeometry: z.array(HostUiPageGeometryEvidenceSchema).max(8).optional(),
2392
+ permissions: HostUiPermissionDeclarationSchema.optional(),
2393
+ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u).optional(),
2394
+ permissionApprovalRequired: z.boolean().optional(),
2395
+ adapter: z.object({
2396
+ apiVersion: z.literal(2),
2397
+ key: NonEmptyStringSchema,
2398
+ descriptorDigest: z.string().regex(/^[a-f0-9]{64}$/u),
2399
+ registered: z.boolean(),
2400
+ started: z.boolean(),
2401
+ stopped: z.boolean(),
2402
+ inboundCommitted: z.boolean(),
2403
+ outboundReceipt: z.enum([
2404
+ "sent",
2405
+ "failed",
2406
+ "unknown"
2407
+ ])
2408
+ }).strict().optional()
2409
+ }).strict().optional()
2410
+ }).strict()),
2411
+ activations: z.array(z.object({
2412
+ agentId: AgentIdSchema,
2413
+ extensionRevisionId: ExtensionRevisionIdSchema,
2414
+ /** Secret fields are removed; `configuredSecrets` lists those the Host stores. */
2415
+ config: JsonValueSchema,
2416
+ configuredSecrets: z.array(z.string()).optional(),
2417
+ activatedAt: z.number().int().safe().nonnegative(),
2418
+ runtime: z.object({
2419
+ status: z.enum([
2420
+ "active",
2421
+ "restore-failed",
2422
+ "dispose-failed"
2423
+ ]),
2424
+ message: z.string().optional(),
2425
+ observedAt: z.number().int().safe().nonnegative()
2426
+ }).optional(),
2427
+ /** Latest connection attempt of each MCP server this Activation declares. */
2428
+ mcpServers: z.array(z.object({
2429
+ name: z.string(),
2430
+ state: z.enum([
2431
+ "connecting",
2432
+ "connected",
2433
+ "unavailable",
2434
+ "missing-credentials"
2435
+ ]),
2436
+ toolCount: z.number().int().nonnegative().optional(),
2437
+ missing: z.array(z.string()).optional(),
2438
+ message: z.string().optional(),
2439
+ observedAt: z.number().int().safe().nonnegative()
2440
+ }).strict()).optional()
2441
+ }).strict()),
2442
+ installation: z.object({
2443
+ extensionRevisionId: ExtensionRevisionIdSchema,
2444
+ installedAt: z.number().int().safe().nonnegative(),
2445
+ config: JsonValueSchema.default({}),
2446
+ runtime: z.object({
2447
+ status: z.enum([
2448
+ "active",
2449
+ "restore-failed",
2450
+ "dispose-failed"
2451
+ ]),
2452
+ message: z.string().optional(),
2453
+ observedAt: z.number().int().safe().nonnegative()
2454
+ }).optional()
2455
+ }).strict().optional(),
2456
+ hostUiPermission: z.object({
2457
+ declaration: HostUiPermissionDeclarationSchema,
2458
+ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u),
2459
+ approvalRequired: z.boolean()
2460
+ }).strict().optional(),
2461
+ hostClientDiagnostic: z.object({
2462
+ revisionId: ExtensionRevisionIdSchema,
2463
+ status: z.enum(["loaded", "failed"]),
2464
+ message: z.string().optional(),
2465
+ observedAt: z.number().int().safe().nonnegative()
2466
+ }).strict().optional(),
2467
+ clientDiagnostics: z.array(z.object({
2468
+ agentId: AgentIdSchema,
2469
+ revisionId: ExtensionRevisionIdSchema,
2470
+ status: z.enum(["loaded", "failed"]),
2471
+ message: z.string().optional(),
2472
+ observedAt: z.number().int().nonnegative()
2473
+ }).strict())
2474
+ }).strict()),
2475
+ hostUi: z.object({
2476
+ preferencesRevision: z.number().int().nonnegative(),
2477
+ pages: z.array(HostUiPageEntrySchema)
2478
+ }).strict().default({
2479
+ preferencesRevision: 0,
2480
+ pages: []
2481
+ }),
2482
+ dynamic: z.array(z.object({
2483
+ agentId: AgentIdSchema,
2484
+ episodeId: EpisodeIdSchema,
2485
+ pluginId: DynamicIdSchema,
2486
+ packageId: DynamicIdSchema.optional(),
2487
+ currentPackageId: DynamicIdSchema.optional(),
2488
+ nextPackageId: DynamicIdSchema.optional(),
2489
+ approvalRequestId: DynamicIdSchema.optional(),
2490
+ status: DynamicAttemptStatusSchema,
2491
+ activeRun: z.object({
2492
+ pluginRunId: DynamicIdSchema,
2493
+ packageId: DynamicIdSchema
2494
+ }).strict().optional(),
2495
+ latestRun: DynamicLatestRunSchema.optional(),
2496
+ packages: z.array(z.object({
2497
+ packageId: DynamicIdSchema,
2498
+ name: z.string(),
2499
+ purpose: z.string(),
2500
+ hasHostHalf: z.boolean(),
2501
+ hasClientHalf: z.boolean()
2502
+ }).strict()),
2503
+ policy: z.object({
2504
+ turn: z.number().int().nonnegative(),
2505
+ primaryPluginId: DynamicIdSchema.optional(),
2506
+ consecutiveFailures: z.number().int().nonnegative(),
2507
+ repeatedFingerprintCount: z.number().int().nonnegative(),
2508
+ lastErrorFingerprint: z.string().optional(),
2509
+ blockedReason: z.string().optional()
2510
+ }).strict()
2511
+ }).strict()),
2512
+ authoringTasks: z.array(AuthoringTaskSummarySchema).default([]),
2513
+ scheduledTasks: z.array(ScheduledTaskSchema).default([])
2514
+ }).strict();
2515
+ const MessageInputPartSchema = z.discriminatedUnion("type", [z.object({
2516
+ type: z.literal("text"),
2517
+ text: z.string().trim().min(1)
2518
+ }).strict(), z.object({
2519
+ type: z.literal("mention"),
2520
+ memberId: ChannelMemberIdSchema
2521
+ }).strict()]);
2522
+ const SendChannelMessageRequestSchema = z.object({
2523
+ parts: z.array(MessageInputPartSchema).min(1),
2524
+ clientEventId: NonEmptyStringSchema.optional(),
2525
+ senderMemberId: ChannelMemberIdSchema.optional()
2526
+ }).strict().refine((body) => body.parts.every((part) => part.type !== "text" || [...part.text].length <= 64 * 1024), "Message text must not exceed 64 KiB.");
2527
+ const DynamicErrorDetailsSchema = z.object({
2528
+ message: z.string(),
2529
+ stack: z.string().optional()
2530
+ }).strict();
2531
+ const DynamicRenderFailureSchema = z.object({
2532
+ slot: NonEmptyStringSchema,
2533
+ message: z.string(),
2534
+ stack: z.string().optional(),
2535
+ abdicated: z.boolean()
2536
+ }).strict();
2537
+ const DynamicRunResolutionSchema = z.discriminatedUnion("ok", [z.object({
2538
+ ok: z.literal(true),
2539
+ pluginRunId: DynamicIdSchema,
2540
+ waitingFor: z.array(z.string()).optional()
2541
+ }).strict(), z.object({
2542
+ ok: z.literal(false),
2543
+ reason: z.enum([
2544
+ "rejected",
2545
+ "host-half-failed",
2546
+ "client-half-failed"
2547
+ ]),
2548
+ pluginRunId: DynamicIdSchema.optional(),
2549
+ startedHere: z.boolean().optional(),
2550
+ message: z.string().optional(),
2551
+ stack: z.string().optional()
2552
+ }).strict()]);
2553
+ const DynamicRunResponseSchema = z.discriminatedUnion("ok", [z.object({
2554
+ ok: z.literal(true),
2555
+ status: z.enum([
2556
+ "awaiting-approval",
2557
+ "starting",
2558
+ "running"
2559
+ ]),
2560
+ pluginId: DynamicIdSchema,
2561
+ packageId: DynamicIdSchema,
2562
+ pluginRunId: DynamicIdSchema,
2563
+ waitingFor: z.array(z.string()),
2564
+ clientWaitingFor: z.array(z.string()).optional(),
2565
+ currentPackageId: DynamicIdSchema.optional(),
2566
+ nextPackageId: DynamicIdSchema.optional(),
2567
+ mode: z.enum(["run", "update"])
2568
+ }).strict(), z.object({
2569
+ ok: z.literal(false),
2570
+ reason: z.enum([
2571
+ "plugin-missing",
2572
+ "package-missing",
2573
+ "invalid-mode",
2574
+ "transition-in-flight",
2575
+ "host-half-failed",
2576
+ "client-half-failed",
2577
+ "rejected",
2578
+ "cancelled",
2579
+ "not-running"
2580
+ ]),
2581
+ message: z.string(),
2582
+ stack: z.string().optional()
2583
+ }).strict()]);
2584
+ const DynamicInventoryRowSchema = z.object({
2585
+ pluginId: DynamicIdSchema,
2586
+ agentId: NonEmptyStringSchema,
2587
+ packages: z.array(z.object({
2588
+ packageId: DynamicIdSchema,
2589
+ name: z.string(),
2590
+ purpose: z.string(),
2591
+ hasHostHalf: z.boolean(),
2592
+ hasClientHalf: z.boolean()
2593
+ }).strict()),
2594
+ currentPackageId: DynamicIdSchema.optional(),
2595
+ nextPackageId: DynamicIdSchema.optional(),
2596
+ activeRun: z.object({
2597
+ pluginRunId: DynamicIdSchema,
2598
+ packageId: DynamicIdSchema
2599
+ }).strict().optional(),
2600
+ latestRun: DynamicLatestRunSchema.optional()
2601
+ }).strict();
2602
+ const DshPluginCatalogEntrySchema = z.object({
2603
+ packageName: NonEmptyStringSchema,
2604
+ packageVersion: NonEmptyStringSchema,
2605
+ origin: z.enum([
2606
+ "builtin",
2607
+ "profile",
2608
+ "dynamic",
2609
+ "installed"
2610
+ ]),
2611
+ settingsNamespaces: z.array(NonEmptyStringSchema),
2612
+ loadError: z.object({
2613
+ code: NonEmptyStringSchema,
2614
+ message: NonEmptyStringSchema
2615
+ }).strict().optional(),
2616
+ packageId: DshPluginPackageIdSchema.optional(),
2617
+ installSource: z.enum([
2618
+ "registry",
2619
+ "tarball",
2620
+ "imported"
2621
+ ]).optional(),
2622
+ installedAt: z.number().int().safe().nonnegative().optional(),
2623
+ clientUiDetected: z.boolean().optional(),
2624
+ hostUi: DshNxtHostUiSchema.optional(),
2625
+ approvedBuilds: z.array(NonEmptyStringSchema).optional(),
2626
+ entries: z.array(z.object({
2627
+ id: DshPluginEntryIdSchema,
2628
+ entryKey: NonEmptyStringSchema,
2629
+ moduleName: NonEmptyStringSchema,
2630
+ suggestedScope: z.enum(["host", "agent"]),
2631
+ selectedScope: z.enum(["host", "agent"]).optional(),
2632
+ config: JsonValueSchema,
2633
+ activations: z.array(z.object({
2634
+ targetKey: NonEmptyStringSchema,
2635
+ target: z.enum(["host", "agent"]),
2636
+ agentId: AgentIdSchema.optional(),
2637
+ activatedAt: z.number().int().safe().nonnegative(),
2638
+ diagnostic: z.object({
2639
+ status: z.enum([
2640
+ "active",
2641
+ "load-failed",
2642
+ "restore-failed",
2643
+ "dispose-failed"
2644
+ ]),
2645
+ phase: z.enum([
2646
+ "import",
2647
+ "apply",
2648
+ "update",
2649
+ "dispose",
2650
+ "restore"
2651
+ ]),
2652
+ message: z.string().optional(),
2653
+ observedAt: z.number().int().safe().nonnegative()
2654
+ }).optional()
2655
+ }).strict())
2656
+ }).strict()).optional()
2657
+ }).strict();
2658
+ const DshSettingsNamespaceSchema = z.object({
2659
+ ns: NonEmptyStringSchema,
2660
+ schema: JsonValueSchema,
2661
+ resolved: JsonValueSchema,
2662
+ base: JsonValueSchema.optional(),
2663
+ user: JsonValueSchema.optional(),
2664
+ applies: z.enum(["live", "restart"]),
2665
+ secrets: z.array(z.object({
2666
+ path: z.array(z.string()),
2667
+ set: z.boolean()
2668
+ }).strict()),
2669
+ revision: z.number().int().nonnegative(),
2670
+ writable: z.boolean(),
2671
+ owner: z.object({
2672
+ packageName: NonEmptyStringSchema,
2673
+ packageVersion: NonEmptyStringSchema
2674
+ }).strict().optional()
2675
+ }).strict();
2676
+ const DshSettingsPathSchema = z.array(z.string().min(1).max(200)).min(1).max(32);
2677
+ const DshSettingsPathOperationSchema = z.discriminatedUnion("op", [z.object({
2678
+ op: z.literal("set"),
2679
+ path: DshSettingsPathSchema,
2680
+ value: JsonValueSchema
2681
+ }).strict(), z.object({
2682
+ op: z.literal("unset"),
2683
+ path: DshSettingsPathSchema
2684
+ }).strict()]);
2685
+ const DshSettingsMutationRequestSchema = z.object({
2686
+ expectedRevision: z.number().int().nonnegative(),
2687
+ ops: z.array(DshSettingsPathOperationSchema).min(1).max(128)
2688
+ }).strict();
2689
+ const DshCredentialRefSchema = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/u).max(200);
2690
+ const DshCredentialViewSchema = z.object({
2691
+ configured: z.boolean(),
2692
+ source: z.string().optional(),
2693
+ writable: z.boolean()
2694
+ }).strict();
2695
+ const DshSettingsChangedSseDataSchema = z.object({
2696
+ namespace: NonEmptyStringSchema,
2697
+ revision: z.number().int().nonnegative()
2698
+ }).strict();
2699
+ const DshCredentialsChangedSseDataSchema = z.object({ ref: DshCredentialRefSchema }).strict();
2700
+ const DynamicChangedSseDataSchema = z.object({ agentId: AgentIdSchema }).strict();
2701
+ const HostSseStatusDataSchema = z.object({
2702
+ ok: z.boolean(),
2703
+ message: z.string(),
2704
+ replay: z.enum([
2705
+ "none",
2706
+ "complete",
2707
+ "expired"
2708
+ ]).optional()
2709
+ }).strict();
2710
+ const DshPluginOperationSseDataSchema = z.object({
2711
+ operationId: z.string().uuid(),
2712
+ kind: z.enum(["inspect", "install"]),
2713
+ phase: z.enum([
2714
+ "download",
2715
+ "dependencies",
2716
+ "build-scripts",
2717
+ "validation",
2718
+ "publish"
2719
+ ]),
2720
+ status: z.enum([
2721
+ "running",
2722
+ "done",
2723
+ "failed"
2724
+ ]),
2725
+ message: z.string()
2726
+ }).strict();
2727
+ const HostSseEventSchema = z.discriminatedUnion("event", [
2728
+ z.object({
2729
+ event: z.literal("snapshot-changed"),
2730
+ data: z.object({ changed: z.literal(true) }).strict()
2731
+ }).strict(),
2732
+ z.object({
2733
+ event: z.literal("channel-fact"),
2734
+ data: ChannelFactSseDataSchema
2735
+ }).strict(),
2736
+ z.object({
2737
+ event: z.literal("connection-fact"),
2738
+ data: HostConnectionEventSchema
2739
+ }).strict(),
2740
+ z.object({
2741
+ event: z.literal("runtime"),
2742
+ data: ChannelRuntimeSseDataSchema
2743
+ }).strict(),
2744
+ z.object({
2745
+ event: z.literal("extensions-changed"),
2746
+ data: z.object({ changed: z.literal(true) }).strict()
2747
+ }).strict(),
2748
+ z.object({
2749
+ event: z.literal("dsh-plugins-changed"),
2750
+ data: z.object({ changed: z.literal(true) }).strict()
2751
+ }).strict(),
2752
+ z.object({
2753
+ event: z.literal("dsh-plugin-operation"),
2754
+ data: DshPluginOperationSseDataSchema
2755
+ }).strict(),
2756
+ z.object({
2757
+ event: z.literal("dynamic-changed"),
2758
+ data: DynamicChangedSseDataSchema
2759
+ }).strict(),
2760
+ z.object({
2761
+ event: z.literal("dsh-settings-changed"),
2762
+ data: DshSettingsChangedSseDataSchema
2763
+ }).strict(),
2764
+ z.object({
2765
+ event: z.literal("dsh-credentials-changed"),
2766
+ data: DshCredentialsChangedSseDataSchema
2767
+ }).strict(),
2768
+ z.object({
2769
+ event: z.literal("status"),
2770
+ data: HostSseStatusDataSchema
2771
+ }).strict(),
2772
+ z.object({
2773
+ event: z.literal("attention-changed"),
2774
+ data: z.object({ revision: z.string().min(1) }).strict()
2775
+ }).strict(),
2776
+ z.object({
2777
+ event: z.literal("binding-change"),
2778
+ data: z.object({
2779
+ operationId: NonEmptyStringSchema,
2780
+ channelId: ChannelIdSchema,
2781
+ kind: z.enum([
2782
+ "bind",
2783
+ "replace",
2784
+ "clear"
2785
+ ]),
2786
+ step: NonEmptyStringSchema,
2787
+ status: z.enum([
2788
+ "running",
2789
+ "skipped",
2790
+ "done",
2791
+ "failed"
2792
+ ]),
2793
+ message: z.string()
2794
+ }).strict()
2795
+ }).strict()
2796
+ ]);
2797
+ /** Request content a model accepts; `image` enables native vision for agents using the model. */
2798
+ const LlmModelInputModalitiesSchema = z.array(z.enum(["text", "image"])).min(1);
2799
+ const LlmProviderModelSchema = z.object({
2800
+ id: NonEmptyStringSchema,
2801
+ name: NonEmptyStringSchema,
2802
+ contextWindow: z.number().int().positive().optional(),
2803
+ maxTokens: z.number().int().positive().optional(),
2804
+ inputModalities: LlmModelInputModalitiesSchema.optional()
2805
+ }).strict();
2806
+ const LlmDiscoveredModelSchema = z.object({
2807
+ id: NonEmptyStringSchema,
2808
+ name: NonEmptyStringSchema.optional(),
2809
+ contextWindow: z.number().int().positive().optional(),
2810
+ maxTokens: z.number().int().positive().optional(),
2811
+ inputModalities: LlmModelInputModalitiesSchema.optional()
2812
+ }).strict();
2813
+ const LlmProviderCredentialSchema = z.object({
2814
+ configured: z.boolean(),
2815
+ source: z.string().optional(),
2816
+ writable: z.boolean()
2817
+ }).strict();
2818
+ const LlmProviderViewSchema = z.object({
2819
+ provider: NonEmptyStringSchema,
2820
+ displayName: z.string(),
2821
+ settingsNs: NonEmptyStringSchema,
2822
+ settingsPath: z.array(NonEmptyStringSchema),
2823
+ settingsRevision: z.number().int().nonnegative(),
2824
+ declared: z.boolean(),
2825
+ active: z.boolean(),
2826
+ configured: z.boolean(),
2827
+ baseURL: z.string().optional(),
2828
+ api: NonEmptyStringSchema.optional(),
2829
+ credential: LlmProviderCredentialSchema.optional(),
2830
+ models: z.array(LlmProviderModelSchema),
2831
+ /** The model list was edited on this host; built-in providers can restore their own catalog. */
2832
+ modelsCustomized: z.boolean(),
2833
+ /** The provider's adapter can list the models its endpoint offers. */
2834
+ discoverable: z.boolean()
2835
+ }).strict();
2836
+ const LlmProviderSettingsSchema = z.object({
2837
+ writable: z.boolean(),
2838
+ protocols: z.array(NonEmptyStringSchema),
2839
+ providers: z.array(LlmProviderViewSchema)
2840
+ }).strict();
2841
+ const ConnectionTestResultSchema = z.discriminatedUnion("status", [
2842
+ z.object({
2843
+ status: z.literal("received"),
2844
+ channelId: ChannelIdSchema,
2845
+ platformMessageId: NonEmptyStringSchema
2846
+ }).strict(),
2847
+ z.object({
2848
+ status: z.literal("sent"),
2849
+ channelId: ChannelIdSchema,
2850
+ platformMessageId: NonEmptyStringSchema.optional()
2851
+ }).strict(),
2852
+ z.object({
2853
+ status: z.enum([
2854
+ "waiting-for-message",
2855
+ "needs-channel",
2856
+ "needs-target",
2857
+ "not-connected"
2858
+ ]),
2859
+ message: z.string()
2860
+ }).strict(),
2861
+ z.object({
2862
+ status: z.literal("failed"),
2863
+ kind: NonEmptyStringSchema,
2864
+ message: z.string(),
2865
+ retryAfterMs: z.number().int().nonnegative().optional()
2866
+ }).strict()
2867
+ ]);
2868
+ /** 扩展包导入检查的结果:本地文件与社区下载共用同一确认步骤。 */
2869
+ const ExtensionImportInspectionSchema = z.object({
2870
+ token: NonEmptyStringSchema,
2871
+ extensionId: ExtensionIdSchema,
2872
+ revisionId: ExtensionRevisionIdSchema,
2873
+ slug: NonEmptyStringSchema,
2874
+ displayName: NonEmptyStringSchema,
2875
+ scope: z.enum([
2876
+ "agent",
2877
+ "host-adapter",
2878
+ "host-ui"
2879
+ ]),
2880
+ idempotent: z.boolean(),
2881
+ slugConflict: z.boolean()
2882
+ }).strict();
2883
+ const defineContract = (contract) => ({
2884
+ ...contract,
2885
+ parseParams: (input) => contract.params.parse(input),
2886
+ parseRequest: (input) => contract.request.parse(input),
2887
+ parseResponse: (input) => contract.response.parse(input),
2888
+ parseError: (input) => contract.error.parse(input)
2889
+ });
2890
+ const agentParam = z.object({ agentId: AgentIdSchema }).strict();
2891
+ const agentRevisionParam = z.object({
2892
+ agentId: AgentIdSchema,
2893
+ revisionId: AgentRevisionIdSchema
2894
+ }).strict();
2895
+ const AgentRevisionChangedFieldSchema = z.enum([
2896
+ "name",
2897
+ "persona",
2898
+ "model",
2899
+ "capabilities",
2900
+ "imagePolicy",
2901
+ "approvalPolicy"
2902
+ ]);
2903
+ const AgentRevisionHistorySchema = z.object({
2904
+ agentId: AgentIdSchema,
2905
+ currentRevisionId: AgentRevisionIdSchema,
2906
+ /** Newest first. `changedFields` compares each Revision with the one numbered just before it. */
2907
+ revisions: z.array(z.object({
2908
+ id: AgentRevisionIdSchema,
2909
+ revision: z.number().int().positive(),
2910
+ createdAt: z.number().int().nonnegative(),
2911
+ displayName: z.string(),
2912
+ model: z.object({
2913
+ provider: z.string(),
2914
+ model: z.string()
2915
+ }).strict(),
2916
+ changedFields: z.array(AgentRevisionChangedFieldSchema),
2917
+ current: z.boolean()
2918
+ }).strict())
2919
+ }).strict();
2920
+ const channelParam = z.object({ channelId: ChannelIdSchema }).strict();
2921
+ const connectionParam = z.object({ connectionId: ConnectionIdSchema }).strict();
2922
+ const agentExtensionParam = z.object({
2923
+ agentId: AgentIdSchema,
2924
+ extensionId: ExtensionIdSchema
2925
+ }).strict();
2926
+ const extensionParam = z.object({ extensionId: ExtensionIdSchema }).strict();
2927
+ const dshPluginPackageParam = z.object({ packageId: DshPluginPackageIdSchema }).strict();
2928
+ const dshPluginEntryParam = z.object({ entryId: DshPluginEntryIdSchema }).strict();
2929
+ const extensionRevisionParam = z.object({
2930
+ extensionId: ExtensionIdSchema,
2931
+ revisionId: ExtensionRevisionIdSchema
2932
+ }).strict();
2933
+ const dshSettingsParam = z.object({ namespace: NonEmptyStringSchema }).strict();
2934
+ const dshCredentialParam = z.object({ ref: DshCredentialRefSchema }).strict();
2935
+ const llmProviderParam = z.object({ provider: NonEmptyStringSchema }).strict();
2936
+ const authoringTaskParam = z.object({ taskId: AuthoringTaskIdSchema }).strict();
2937
+ const scheduledTaskParam = z.object({ taskId: ScheduledTaskIdSchema }).strict();
2938
+ const authoringAttemptParam = z.object({
2939
+ taskId: AuthoringTaskIdSchema,
2940
+ attemptId: AuthoringAttemptIdSchema
2941
+ }).strict();
2942
+ const DshPluginInstallInspectionSchema = z.object({
2943
+ token: NonEmptyStringSchema,
2944
+ operationId: z.string().uuid().optional(),
2945
+ packageName: NonEmptyStringSchema,
2946
+ packageVersion: NonEmptyStringSchema,
2947
+ packageDigest: z.string().regex(/^[a-f0-9]{64}$/u),
2948
+ lockfileDigest: z.string().regex(/^[a-f0-9]{64}$/u),
2949
+ blockedBuilds: z.array(NonEmptyStringSchema),
2950
+ clientUiDetected: z.boolean(),
2951
+ hostUi: DshNxtHostUiSchema.optional(),
2952
+ entries: z.array(z.object({
2953
+ entryKey: NonEmptyStringSchema,
2954
+ moduleName: NonEmptyStringSchema,
2955
+ suggestedScope: z.enum(["host", "agent"])
2956
+ }).strict())
2957
+ }).strict();
2958
+ const BinaryUploadRequestSchema = z.object({
2959
+ bytes: z.instanceof(Uint8Array),
2960
+ fileName: z.string().max(255).optional(),
2961
+ operationId: z.string().uuid().optional()
2962
+ }).strict();
2963
+ const encodeBinaryUpload = (input) => ({
2964
+ body: input.bytes,
2965
+ headers: {
2966
+ "content-type": "application/octet-stream",
2967
+ ...input.fileName === void 0 ? {} : { "x-file-name": input.fileName },
2968
+ ...input.operationId === void 0 ? {} : { "x-operation-id": input.operationId }
2969
+ }
2970
+ });
2971
+ const HostApiContracts = {
2972
+ retryRuntimeCompatibility: defineContract({
2973
+ method: "POST",
2974
+ path: "/api/runtime/compatibility/retry",
2975
+ params: EmptyParamsSchema,
2976
+ request: z.object({
2977
+ objectKind: RuntimeCompatibilityDiagnosticSchema.shape.objectKind,
2978
+ objectId: z.string().min(1)
2979
+ }).strict(),
2980
+ response: z.object({ diagnostics: z.array(RuntimeCompatibilityDiagnosticSchema) }).strict(),
2981
+ error: HostApiErrorSchema,
2982
+ invalidatesSnapshot: true
2983
+ }),
2984
+ snapshot: defineContract({
2985
+ method: "GET",
2986
+ path: "/api/snapshot",
2987
+ params: EmptyParamsSchema,
2988
+ request: NoRequestBodySchema,
2989
+ response: HostSnapshotSchema,
2990
+ error: HostApiErrorSchema
2991
+ }),
2992
+ getAuthoringTask: defineContract({
2993
+ method: "GET",
2994
+ path: "/api/authoring/tasks/:taskId",
2995
+ params: authoringTaskParam,
2996
+ request: NoRequestBodySchema,
2997
+ response: z.object({
2998
+ task: AuthoringTaskSummarySchema,
2999
+ attempts: z.array(AuthoringAttemptSummarySchema),
3000
+ /** Secret fields of the latest candidate and which have a test value for this task's dynamic runs. */
3001
+ testSecrets: z.object({
3002
+ fields: z.array(z.object({
3003
+ key: z.string(),
3004
+ title: z.string()
3005
+ }).strict()),
3006
+ configured: z.array(z.string())
3007
+ }).strict().optional(),
3008
+ events: z.array(z.object({
3009
+ sequence: z.number().int().positive(),
3010
+ kind: z.string(),
3011
+ attemptId: AuthoringAttemptIdSchema.optional(),
3012
+ payload: JsonValueSchema,
3013
+ createdAt: z.number().int().nonnegative()
3014
+ }).strict())
3015
+ }).strict(),
3016
+ error: HostApiErrorSchema
3017
+ }),
3018
+ decideAuthoringAttempt: defineContract({
3019
+ invalidatesSnapshot: true,
3020
+ method: "POST",
3021
+ path: "/api/authoring/tasks/:taskId/attempts/:attemptId/decision",
3022
+ params: authoringAttemptParam,
3023
+ request: z.object({
3024
+ expectedRevision: z.number().int().positive(),
3025
+ approved: z.boolean(),
3026
+ approveRiskStable: z.boolean()
3027
+ }).strict(),
3028
+ response: z.object({
3029
+ accepted: z.boolean(),
3030
+ taskRevision: z.number().int().positive(),
3031
+ executionRequired: z.boolean()
3032
+ }).strict(),
3033
+ error: HostApiErrorSchema
3034
+ }),
3035
+ restoreAuthoringAttempt: defineContract({
3036
+ invalidatesSnapshot: true,
3037
+ method: "POST",
3038
+ path: "/api/authoring/tasks/:taskId/attempts/:attemptId/restore",
3039
+ params: authoringAttemptParam,
3040
+ request: z.object({ expectedRevision: z.number().int().positive() }).strict(),
3041
+ response: AuthoringTaskSummarySchema,
3042
+ error: HostApiErrorSchema
3043
+ }),
3044
+ stopAuthoringTask: defineContract({
3045
+ invalidatesSnapshot: true,
3046
+ method: "POST",
3047
+ path: "/api/authoring/tasks/:taskId/stop",
3048
+ params: authoringTaskParam,
3049
+ request: z.object({ expectedRevision: z.number().int().positive() }).strict(),
3050
+ response: AuthoringTaskSummarySchema,
3051
+ error: HostApiErrorSchema
3052
+ }),
3053
+ setAuthoringTestSecrets: defineContract({
3054
+ method: "PUT",
3055
+ path: "/api/authoring/tasks/:taskId/test-secrets",
3056
+ params: authoringTaskParam,
3057
+ request: z.object({ secrets: z.record(z.string(), z.string().max(8192)) }).strict(),
3058
+ response: z.object({ configured: z.array(z.string()) }).strict(),
3059
+ error: HostApiErrorSchema
3060
+ }),
3061
+ deleteAuthoringTask: defineContract({
3062
+ invalidatesSnapshot: true,
3063
+ method: "DELETE",
3064
+ path: "/api/authoring/tasks/:taskId",
3065
+ params: authoringTaskParam,
3066
+ request: NoRequestBodySchema,
3067
+ response: z.object({ deleted: z.literal(true) }).strict(),
3068
+ error: HostApiErrorSchema
3069
+ }),
3070
+ pauseScheduledTask: defineContract({
3071
+ invalidatesSnapshot: true,
3072
+ method: "POST",
3073
+ path: "/api/scheduled-tasks/:taskId/pause",
3074
+ params: scheduledTaskParam,
3075
+ request: NoRequestBodySchema,
3076
+ response: ScheduledTaskSchema,
3077
+ error: HostApiErrorSchema
3078
+ }),
3079
+ resumeScheduledTask: defineContract({
3080
+ invalidatesSnapshot: true,
3081
+ method: "POST",
3082
+ path: "/api/scheduled-tasks/:taskId/resume",
3083
+ params: scheduledTaskParam,
3084
+ request: NoRequestBodySchema,
3085
+ response: ScheduledTaskSchema,
3086
+ error: HostApiErrorSchema
3087
+ }),
3088
+ runScheduledTask: defineContract({
3089
+ invalidatesSnapshot: true,
3090
+ method: "POST",
3091
+ path: "/api/scheduled-tasks/:taskId/run",
3092
+ params: scheduledTaskParam,
3093
+ request: NoRequestBodySchema,
3094
+ /** `woke: false` when the owning extension's due-job handler let this run pass without waking the agent. */
3095
+ response: z.object({
3096
+ task: ScheduledTaskSchema,
3097
+ woke: z.boolean()
3098
+ }).strict(),
3099
+ error: HostApiErrorSchema
3100
+ }),
3101
+ deleteScheduledTask: defineContract({
3102
+ invalidatesSnapshot: true,
3103
+ method: "DELETE",
3104
+ path: "/api/scheduled-tasks/:taskId",
3105
+ params: scheduledTaskParam,
3106
+ request: NoRequestBodySchema,
3107
+ response: z.object({ deleted: z.literal(true) }).strict(),
3108
+ error: HostApiErrorSchema
3109
+ }),
3110
+ listClientNotifications: defineContract({
3111
+ method: "GET",
3112
+ path: "/api/client-notifications",
3113
+ params: z.object({ cursor: z.number().int().nonnegative().optional() }).strict(),
3114
+ request: NoRequestBodySchema,
3115
+ response: ClientNotificationFeedResponseSchema,
3116
+ error: HostApiErrorSchema
3117
+ }),
3118
+ updateNotificationSettings: defineContract({
3119
+ invalidatesSnapshot: true,
3120
+ method: "PUT",
3121
+ path: "/api/settings/notifications",
3122
+ params: EmptyParamsSchema,
3123
+ request: UpdateNotificationSettingsRequestSchema,
3124
+ response: NotificationSettingsViewSchema,
3125
+ error: HostApiErrorSchema
3126
+ }),
3127
+ testBarkNotification: defineContract({
3128
+ method: "POST",
3129
+ path: "/api/settings/notifications/test",
3130
+ params: EmptyParamsSchema,
3131
+ request: TestBarkNotificationRequestSchema,
3132
+ response: z.object({ sent: z.literal(true) }).strict(),
3133
+ error: HostApiErrorSchema
3134
+ }),
3135
+ testSystemNotification: defineContract({
3136
+ method: "POST",
3137
+ path: "/api/settings/notifications/test-system",
3138
+ params: EmptyParamsSchema,
3139
+ request: NoRequestBodySchema,
3140
+ response: z.object({ published: z.literal(true) }).strict(),
3141
+ error: HostApiErrorSchema
3142
+ }),
3143
+ listPlatformUsers: defineContract({
3144
+ method: "GET",
3145
+ path: "/api/platform-users",
3146
+ params: z.object({
3147
+ query: z.string().trim().max(80).optional(),
3148
+ adapterKey: z.string().trim().min(1).max(120).optional(),
3149
+ connectionId: ConnectionIdSchema.optional(),
3150
+ cursor: PlatformIdentityIdSchema.optional(),
3151
+ limit: z.number().int().min(1).max(100).default(50)
3152
+ }).strict(),
3153
+ request: NoRequestBodySchema,
3154
+ response: PlatformUserListResponseSchema,
3155
+ error: HostApiErrorSchema
3156
+ }),
3157
+ listConnectionEvents: defineContract({
3158
+ method: "GET",
3159
+ path: "/api/connections/:connectionId/events",
3160
+ params: z.object({
3161
+ connectionId: ConnectionIdSchema,
3162
+ beforeReceivedAt: z.number().int().safe().nonnegative().optional(),
3163
+ beforeId: ConnectionEventIdSchema.optional(),
3164
+ limit: z.number().int().min(1).max(100).default(50)
3165
+ }).strict(),
3166
+ request: NoRequestBodySchema,
3167
+ response: z.object({
3168
+ events: z.array(HostConnectionEventSchema),
3169
+ hasMore: z.boolean()
3170
+ }).strict(),
3171
+ error: HostApiErrorSchema
3172
+ }),
3173
+ createAgent: defineContract({
3174
+ invalidatesSnapshot: true,
3175
+ method: "POST",
3176
+ path: "/api/agents",
3177
+ params: EmptyParamsSchema,
3178
+ request: CreateAgentRequestSchema,
3179
+ response: z.object({
3180
+ agentId: AgentIdSchema,
3181
+ channelId: ChannelIdSchema,
3182
+ connectionId: ConnectionIdSchema
3183
+ }).strict(),
3184
+ error: HostApiErrorSchema
3185
+ }),
3186
+ reviseAgent: defineContract({
3187
+ invalidatesSnapshot: true,
3188
+ method: "POST",
3189
+ path: "/api/agents/:agentId/revision",
3190
+ params: agentParam,
3191
+ request: ReviseAgentRequestSchema,
3192
+ response: z.object({ currentRevisionId: AgentRevisionIdSchema }).strict(),
3193
+ error: HostApiErrorSchema
3194
+ }),
3195
+ updateAgentCapabilities: defineContract({
3196
+ invalidatesSnapshot: true,
3197
+ method: "POST",
3198
+ path: "/api/agents/:agentId/capabilities",
3199
+ params: agentParam,
3200
+ request: UpdateAgentCapabilitiesRequestSchema,
3201
+ response: z.object({
3202
+ currentRevisionId: AgentRevisionIdSchema,
3203
+ capabilities: AgentCapabilitiesSchema
3204
+ }).strict(),
3205
+ error: HostApiErrorSchema
3206
+ }),
3207
+ deleteAgent: defineContract({
3208
+ invalidatesSnapshot: true,
3209
+ method: "DELETE",
3210
+ path: "/api/agents/:agentId",
3211
+ params: agentParam,
3212
+ request: z.object({
3213
+ expectedCurrentRevisionId: AgentRevisionIdSchema,
3214
+ confirmationName: z.string().min(1).max(80),
3215
+ deleteAutoCreatedBuiltInChannels: z.boolean().default(true),
3216
+ /** Also remove `workspaces/<agentId>/` (files, development shell output, creation candidates). */
3217
+ deleteWorkspace: z.boolean().default(false)
3218
+ }).strict(),
3219
+ response: z.object({
3220
+ agentId: AgentIdSchema,
3221
+ deleted: z.literal(true),
3222
+ unboundChannelIds: z.array(ChannelIdSchema),
3223
+ deletedChannelIds: z.array(ChannelIdSchema)
3224
+ }).strict(),
3225
+ error: HostApiErrorSchema
3226
+ }),
3227
+ createInternalChannel: defineContract({
3228
+ invalidatesSnapshot: true,
3229
+ method: "POST",
3230
+ path: "/api/channels",
3231
+ params: EmptyParamsSchema,
3232
+ request: z.object({ displayName: z.string().trim().min(1).max(120) }).strict(),
3233
+ response: z.object({
3234
+ channelId: ChannelIdSchema,
3235
+ connectionId: ConnectionIdSchema
3236
+ }).strict(),
3237
+ error: HostApiErrorSchema
3238
+ }),
3239
+ deleteChannel: defineContract({
3240
+ invalidatesSnapshot: true,
3241
+ method: "DELETE",
3242
+ path: "/api/channels/:channelId",
3243
+ params: channelParam,
3244
+ request: z.object({ expectedBoundAgentId: AgentIdSchema.nullable() }).strict(),
3245
+ response: z.object({
3246
+ channelId: ChannelIdSchema,
3247
+ deleted: z.literal(true)
3248
+ }).strict(),
3249
+ error: HostApiErrorSchema
3250
+ }),
3251
+ createBinding: defineContract({
3252
+ invalidatesSnapshot: true,
3253
+ method: "POST",
3254
+ path: "/api/bindings",
3255
+ params: EmptyParamsSchema,
3256
+ request: z.object({
3257
+ agentId: AgentIdSchema,
3258
+ channelId: ChannelIdSchema,
3259
+ triggerPolicy: TriggerPolicySchema,
3260
+ processingFeedback: z.enum(["auto", "off"]).optional(),
3261
+ activityTriggerOverrides: ActivityTriggerOverridesSchema.optional()
3262
+ }).strict(),
3263
+ response: z.object({
3264
+ channelId: ChannelIdSchema,
3265
+ agentId: AgentIdSchema,
3266
+ triggerPolicy: TriggerPolicySchema,
3267
+ processingFeedback: z.enum(["auto", "off"]).default("auto"),
3268
+ activityTriggerOverrides: ActivityTriggerOverridesSchema.default({}),
3269
+ boundAt: z.number().int().safe().nonnegative()
3270
+ }).strict(),
3271
+ error: HostApiErrorSchema
3272
+ }),
3273
+ clearBinding: defineContract({
3274
+ invalidatesSnapshot: true,
3275
+ method: "DELETE",
3276
+ path: "/api/bindings/:channelId",
3277
+ params: channelParam,
3278
+ request: NoRequestBodySchema,
3279
+ response: z.object({
3280
+ channelId: ChannelIdSchema,
3281
+ cleared: z.literal(true)
3282
+ }).strict(),
3283
+ error: HostApiErrorSchema
3284
+ }),
3285
+ putWorkTreeOrder: defineContract({
3286
+ invalidatesSnapshot: true,
3287
+ method: "PUT",
3288
+ path: "/api/work-tree-order",
3289
+ params: EmptyParamsSchema,
3290
+ request: WorkTreeOrderSchema,
3291
+ response: WorkTreeOrderSchema,
3292
+ error: HostApiErrorSchema
3293
+ }),
3294
+ listChannelMessages: defineContract({
3295
+ method: "GET",
3296
+ path: "/api/channels/:channelId/messages",
3297
+ params: z.object({
3298
+ channelId: ChannelIdSchema,
3299
+ limit: z.number().int().min(1).max(100),
3300
+ beforeOccurredAt: z.number().int().safe().nonnegative().optional(),
3301
+ beforeSourceId: NonEmptyStringSchema.optional()
3302
+ }).strict().refine((value) => value.beforeOccurredAt === void 0 === (value.beforeSourceId === void 0), "频道历史游标必须完整提供。"),
3303
+ request: NoRequestBodySchema,
3304
+ response: z.object({
3305
+ messages: z.array(HostSnapshotMessageSchema),
3306
+ hasMore: z.boolean(),
3307
+ cursor: HostSyncCursorSchema
3308
+ }).strict(),
3309
+ error: HostApiErrorSchema
3310
+ }),
3311
+ sendChannelMessage: defineContract({
3312
+ method: "POST",
3313
+ path: "/api/channels/:channelId/messages",
3314
+ params: channelParam,
3315
+ request: SendChannelMessageRequestSchema,
3316
+ response: z.object({
3317
+ inserted: z.boolean(),
3318
+ channelEventId: ChannelEventIdSchema.optional(),
3319
+ outboundIntentId: OutboundIntentIdSchema.optional()
3320
+ }).strict(),
3321
+ error: HostApiErrorSchema
3322
+ }),
3323
+ renameChannel: defineContract({
3324
+ invalidatesSnapshot: true,
3325
+ method: "POST",
3326
+ path: "/api/channels/:channelId/display-name",
3327
+ params: channelParam,
3328
+ request: z.object({ displayName: z.string().trim().min(1).max(120) }).strict(),
3329
+ response: z.object({
3330
+ channelId: ChannelIdSchema,
3331
+ displayName: z.string().trim().min(1).max(120)
3332
+ }).strict(),
3333
+ error: HostApiErrorSchema
3334
+ }),
3335
+ getChannelRuntime: defineContract({
3336
+ method: "GET",
3337
+ path: "/api/channels/:channelId/runtime",
3338
+ params: channelParam,
3339
+ request: NoRequestBodySchema,
3340
+ response: ChannelRuntimeProjectionSchema.extend({ cursor: HostSyncCursorSchema }),
3341
+ error: HostApiErrorSchema
3342
+ }),
3343
+ getChannelToolCall: defineContract({
3344
+ method: "GET",
3345
+ path: "/api/channels/:channelId/runtime/tools/:callId",
3346
+ params: z.object({
3347
+ channelId: ChannelIdSchema,
3348
+ callId: z.string().trim().min(1).max(200)
3349
+ }).strict(),
3350
+ request: NoRequestBodySchema,
3351
+ response: z.object({
3352
+ callId: z.string(),
3353
+ available: z.boolean(),
3354
+ name: z.string().optional(),
3355
+ input: z.string().optional(),
3356
+ result: z.string().optional(),
3357
+ inputTruncated: z.boolean(),
3358
+ resultTruncated: z.boolean()
3359
+ }).strict(),
3360
+ error: HostApiErrorSchema
3361
+ }),
3362
+ resetChannelContext: defineContract({
3363
+ invalidatesSnapshot: true,
3364
+ method: "POST",
3365
+ path: "/api/channels/:channelId/context-reset",
3366
+ params: channelParam,
3367
+ request: z.object({
3368
+ mode: z.enum(["clear", "compact"]),
3369
+ expectedEpisodeId: EpisodeIdSchema
3370
+ }).strict(),
3371
+ response: z.object({
3372
+ mode: z.enum(["clear", "compact"]),
3373
+ closedEpisodeId: EpisodeIdSchema,
3374
+ nextEpisodeId: EpisodeIdSchema.optional()
3375
+ }).strict(),
3376
+ error: HostApiErrorSchema
3377
+ }),
3378
+ createConnection: defineContract({
3379
+ invalidatesSnapshot: true,
3380
+ method: "POST",
3381
+ path: "/api/connections",
3382
+ params: EmptyParamsSchema,
3383
+ request: z.object({
3384
+ adapterKey: NonEmptyStringSchema,
3385
+ alias: ConnectionAliasInputSchema.optional(),
3386
+ configuration: z.record(z.string(), JsonValueSchema).default({}),
3387
+ credentials: z.record(z.string(), z.string().max(16 * 1024)).default({})
3388
+ }).strict(),
3389
+ response: z.object({
3390
+ connectionId: ConnectionIdSchema,
3391
+ adapterKey: NonEmptyStringSchema
3392
+ }).strict(),
3393
+ error: HostApiErrorSchema
3394
+ }),
3395
+ startConnectionLogin: defineContract({
3396
+ method: "POST",
3397
+ path: "/api/connection-logins",
3398
+ params: EmptyParamsSchema,
3399
+ request: z.object({
3400
+ adapterKey: NonEmptyStringSchema,
3401
+ alias: ConnectionAliasInputSchema.optional(),
3402
+ connectionId: ConnectionIdSchema.optional()
3403
+ }).strict(),
3404
+ response: z.object({
3405
+ loginId: NonEmptyStringSchema,
3406
+ adapterKey: NonEmptyStringSchema,
3407
+ status: z.enum([
3408
+ "pending",
3409
+ "scanned",
3410
+ "confirmed",
3411
+ "expired",
3412
+ "failed",
3413
+ "cancelled"
3414
+ ]),
3415
+ qrCodeUrl: NonEmptyStringSchema,
3416
+ message: z.string().optional()
3417
+ }).strict(),
3418
+ error: HostApiErrorSchema
3419
+ }),
3420
+ getConnectionLogin: defineContract({
3421
+ method: "GET",
3422
+ path: "/api/connection-logins/:loginId",
3423
+ params: z.object({ loginId: NonEmptyStringSchema }).strict(),
3424
+ request: NoRequestBodySchema,
3425
+ response: z.object({
3426
+ loginId: NonEmptyStringSchema,
3427
+ status: z.enum([
3428
+ "pending",
3429
+ "scanned",
3430
+ "confirmed",
3431
+ "expired",
3432
+ "failed",
3433
+ "cancelled"
3434
+ ]),
3435
+ qrCodeUrl: NonEmptyStringSchema.optional(),
3436
+ connectionId: ConnectionIdSchema.optional(),
3437
+ adapterKey: NonEmptyStringSchema,
3438
+ message: z.string().optional()
3439
+ }).strict(),
3440
+ error: HostApiErrorSchema
3441
+ }),
3442
+ cancelConnectionLogin: defineContract({
3443
+ method: "DELETE",
3444
+ path: "/api/connection-logins/:loginId",
3445
+ params: z.object({ loginId: NonEmptyStringSchema }).strict(),
3446
+ request: NoRequestBodySchema,
3447
+ response: z.object({
3448
+ loginId: NonEmptyStringSchema,
3449
+ status: z.literal("cancelled")
3450
+ }).strict(),
3451
+ error: HostApiErrorSchema
3452
+ }),
3453
+ updateConnectionAlias: defineContract({
3454
+ invalidatesSnapshot: true,
3455
+ method: "POST",
3456
+ path: "/api/connections/:connectionId/alias",
3457
+ params: connectionParam,
3458
+ request: z.object({ alias: z.string().trim().max(80) }).strict(),
3459
+ response: z.object({
3460
+ connectionId: ConnectionIdSchema,
3461
+ alias: ConnectionAliasOutputSchema.optional()
3462
+ }).strict(),
3463
+ error: HostApiErrorSchema
3464
+ }),
3465
+ updateConnectionActivityTriggerDefaults: defineContract({
3466
+ invalidatesSnapshot: true,
3467
+ method: "POST",
3468
+ path: "/api/connections/:connectionId/activity-trigger-defaults",
3469
+ params: connectionParam,
3470
+ request: z.object({ activityKeys: z.array(AdapterActivityKeySchema) }).strict(),
3471
+ response: z.object({
3472
+ connectionId: ConnectionIdSchema,
3473
+ activityKeys: z.array(AdapterActivityKeySchema)
3474
+ }).strict(),
3475
+ error: HostApiErrorSchema
3476
+ }),
3477
+ updateConnectionConfiguration: defineContract({
3478
+ invalidatesSnapshot: true,
3479
+ method: "POST",
3480
+ path: "/api/connections/:connectionId/configuration",
3481
+ params: connectionParam,
3482
+ request: z.object({ configuration: z.record(z.string(), z.union([
3483
+ z.string(),
3484
+ z.number(),
3485
+ z.boolean()
3486
+ ])) }).strict(),
3487
+ response: z.object({
3488
+ connectionId: ConnectionIdSchema,
3489
+ configuration: z.record(z.string(), z.union([
3490
+ z.string(),
3491
+ z.number(),
3492
+ z.boolean()
3493
+ ]))
3494
+ }).strict(),
3495
+ error: HostApiErrorSchema
3496
+ }),
3497
+ deleteConnection: defineContract({
3498
+ invalidatesSnapshot: true,
3499
+ method: "DELETE",
3500
+ path: "/api/connections/:connectionId",
3501
+ params: connectionParam,
3502
+ request: z.object({ deleteChannelData: z.boolean() }).strict(),
3503
+ response: z.object({
3504
+ connectionId: ConnectionIdSchema,
3505
+ archived: z.boolean()
3506
+ }).strict(),
3507
+ error: HostApiErrorSchema
3508
+ }),
3509
+ restoreConnection: defineContract({
3510
+ invalidatesSnapshot: true,
3511
+ method: "POST",
3512
+ path: "/api/connections/:connectionId/restore",
3513
+ params: connectionParam,
3514
+ request: NoRequestBodySchema,
3515
+ response: z.object({
3516
+ connectionId: ConnectionIdSchema,
3517
+ restored: z.literal(true)
3518
+ }).strict(),
3519
+ error: HostApiErrorSchema
3520
+ }),
3521
+ dshPlugins: defineContract({
3522
+ method: "GET",
3523
+ path: "/api/dsh/plugins",
3524
+ params: EmptyParamsSchema,
3525
+ request: NoRequestBodySchema,
3526
+ response: z.object({ plugins: z.array(DshPluginCatalogEntrySchema) }).strict(),
3527
+ error: HostApiErrorSchema
3528
+ }),
3529
+ inspectDshPluginTarball: defineContract({
3530
+ method: "POST",
3531
+ timeoutMs: 3e5,
3532
+ path: "/api/dsh/plugin-installs/inspect-tarball",
3533
+ params: EmptyParamsSchema,
3534
+ request: BinaryUploadRequestSchema,
3535
+ encodeRequest: encodeBinaryUpload,
3536
+ response: DshPluginInstallInspectionSchema,
3537
+ error: HostApiErrorSchema
3538
+ }),
3539
+ exportExtensionRevision: defineContract({
3540
+ method: "GET",
3541
+ timeoutMs: 3e5,
3542
+ path: "/api/extensions/:extensionId/revisions/:revisionId/export",
3543
+ params: extensionRevisionParam,
3544
+ request: NoRequestBodySchema,
3545
+ responseFormat: "bytes",
3546
+ response: z.instanceof(Uint8Array),
3547
+ error: HostApiErrorSchema
3548
+ }),
3549
+ inspectDshPluginInstall: defineContract({
3550
+ timeoutMs: 3e5,
3551
+ method: "POST",
3552
+ path: "/api/dsh/plugin-installs/inspect",
3553
+ params: EmptyParamsSchema,
3554
+ request: z.object({
3555
+ spec: NonEmptyStringSchema.max(500),
3556
+ operationId: z.string().uuid().optional()
3557
+ }).strict(),
3558
+ response: DshPluginInstallInspectionSchema,
3559
+ error: HostApiErrorSchema
3560
+ }),
3561
+ commitDshPluginInstall: defineContract({
3562
+ invalidatesSnapshot: true,
3563
+ timeoutMs: 3e5,
3564
+ method: "POST",
3565
+ path: "/api/dsh/plugin-installs",
3566
+ params: EmptyParamsSchema,
3567
+ request: z.object({
3568
+ token: NonEmptyStringSchema,
3569
+ approvedBuilds: z.array(NonEmptyStringSchema).default([]),
3570
+ operationId: z.string().uuid().optional()
3571
+ }).strict(),
3572
+ response: z.object({
3573
+ packageId: DshPluginPackageIdSchema,
3574
+ operationId: z.string().uuid().optional()
3575
+ }).strict(),
3576
+ error: HostApiErrorSchema
3577
+ }),
3578
+ inspectDshPluginEntryConfig: defineContract({
3579
+ method: "POST",
3580
+ path: "/api/dsh/plugin-entries/:entryId/config/inspect",
3581
+ params: dshPluginEntryParam,
3582
+ request: NoRequestBodySchema,
3583
+ response: z.discriminatedUnion("mode", [
3584
+ z.object({
3585
+ mode: z.literal("schema"),
3586
+ schema: JsonValueSchema
3587
+ }).strict(),
3588
+ z.object({ mode: z.literal("json") }).strict(),
3589
+ z.object({
3590
+ mode: z.literal("incompatible"),
3591
+ reason: NonEmptyStringSchema
3592
+ }).strict()
3593
+ ]),
3594
+ error: HostApiErrorSchema
3595
+ }),
3596
+ activateDshPluginEntry: defineContract({
3597
+ method: "PUT",
3598
+ path: "/api/dsh/plugin-entries/:entryId/activation",
3599
+ params: dshPluginEntryParam,
3600
+ request: z.object({
3601
+ target: z.enum(["host", "agent"]),
3602
+ agentId: AgentIdSchema.optional(),
3603
+ config: JsonValueSchema,
3604
+ permissionApproval: z.object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) }).strict().optional()
3605
+ }).strict(),
3606
+ response: z.object({ targetKey: NonEmptyStringSchema }).strict(),
3607
+ error: HostApiErrorSchema
3608
+ }),
3609
+ deactivateDshPluginEntry: defineContract({
3610
+ method: "DELETE",
3611
+ path: "/api/dsh/plugin-entries/:entryId/activation",
3612
+ params: dshPluginEntryParam,
3613
+ request: z.object({ targetKey: NonEmptyStringSchema }).strict(),
3614
+ response: z.object({ disabled: z.literal(true) }).strict(),
3615
+ error: HostApiErrorSchema
3616
+ }),
3617
+ removeDshPluginPackage: defineContract({
3618
+ invalidatesSnapshot: true,
3619
+ method: "DELETE",
3620
+ path: "/api/dsh/plugin-installs/:packageId",
3621
+ params: dshPluginPackageParam,
3622
+ request: NoRequestBodySchema,
3623
+ response: z.object({ removed: z.literal(true) }).strict(),
3624
+ error: HostApiErrorSchema
3625
+ }),
3626
+ inspectExtensionImport: defineContract({
3627
+ timeoutMs: 3e5,
3628
+ method: "POST",
3629
+ path: "/api/extensions/imports/inspect",
3630
+ params: EmptyParamsSchema,
3631
+ request: BinaryUploadRequestSchema,
3632
+ encodeRequest: encodeBinaryUpload,
3633
+ response: ExtensionImportInspectionSchema,
3634
+ error: HostApiErrorSchema
3635
+ }),
3636
+ /**
3637
+ * Management-edge endpoints: they exist only when the Server is reached through its management edge (a management
3638
+ * key is set); clients tell that from the edge's CSRF cookie.
3639
+ */
3640
+ listManagementDevices: defineContract({
3641
+ method: "GET",
3642
+ path: "/api/management/devices",
3643
+ params: EmptyParamsSchema,
3644
+ request: NoRequestBodySchema,
3645
+ response: z.object({ devices: z.array(ManagementDeviceViewSchema) }).strict(),
3646
+ error: HostApiErrorSchema
3647
+ }),
3648
+ revokeManagementDevice: defineContract({
3649
+ method: "DELETE",
3650
+ path: "/api/management/devices/:deviceId",
3651
+ params: z.object({ deviceId: ManagementDeviceIdSchema }).strict(),
3652
+ request: NoRequestBodySchema,
3653
+ response: z.object({ revoked: z.boolean() }).strict(),
3654
+ error: HostApiErrorSchema
3655
+ }),
3656
+ managementLogout: defineContract({
3657
+ method: "DELETE",
3658
+ path: "/api/management/session",
3659
+ params: EmptyParamsSchema,
3660
+ request: NoRequestBodySchema,
3661
+ response: z.object({ authenticated: z.literal(false) }).strict(),
3662
+ error: HostApiErrorSchema
3663
+ }),
3664
+ getCommunityStatus: defineContract({
3665
+ method: "GET",
3666
+ path: "/api/community/status",
3667
+ params: EmptyParamsSchema,
3668
+ request: NoRequestBodySchema,
3669
+ response: CommunityStatusSchema,
3670
+ error: HostApiErrorSchema
3671
+ }),
3672
+ startCommunityLogin: defineContract({
3673
+ method: "POST",
3674
+ path: "/api/community/login",
3675
+ params: EmptyParamsSchema,
3676
+ /** 浏览器当前访问本实例使用的来源;社区授权完成后回到 `<returnOrigin>/community/callback`。 */
3677
+ request: z.object({ returnOrigin: z.string().url().max(300) }).strict(),
3678
+ response: z.object({ authorizeUrl: z.string().url() }).strict(),
3679
+ error: HostApiErrorSchema
3680
+ }),
3681
+ communityLogout: defineContract({
3682
+ method: "DELETE",
3683
+ path: "/api/community/login",
3684
+ params: EmptyParamsSchema,
3685
+ request: NoRequestBodySchema,
3686
+ response: CommunityStatusSchema,
3687
+ error: HostApiErrorSchema
3688
+ }),
3689
+ listCommunityExtensions: defineContract({
3690
+ timeoutMs: 3e4,
3691
+ method: "GET",
3692
+ path: "/api/community/extensions",
3693
+ params: z.object({
3694
+ query: z.string().trim().max(80).optional(),
3695
+ scope: z.enum([
3696
+ "agent",
3697
+ "host-adapter",
3698
+ "host-ui"
3699
+ ]).optional(),
3700
+ cursor: z.string().max(200).optional()
3701
+ }).strict(),
3702
+ request: NoRequestBodySchema,
3703
+ response: z.object({
3704
+ items: z.array(CommunityExtensionSummarySchema),
3705
+ nextCursor: z.string().nullable()
3706
+ }).strict(),
3707
+ error: HostApiErrorSchema
3708
+ }),
3709
+ getCommunityExtension: defineContract({
3710
+ timeoutMs: 3e4,
3711
+ method: "GET",
3712
+ path: "/api/community/extensions/:extensionId",
3713
+ params: z.object({ extensionId: ExtensionIdSchema }).strict(),
3714
+ request: NoRequestBodySchema,
3715
+ response: CommunityExtensionDetailSchema,
3716
+ error: HostApiErrorSchema
3717
+ }),
3718
+ /** 下载社区发布并按包摘要校验,结果与本地文件导入的检查相同,再经 `commitExtensionImport` 确认。 */
3719
+ importCommunityRelease: defineContract({
3720
+ timeoutMs: 12e4,
3721
+ method: "POST",
3722
+ path: "/api/community/releases/:releaseId/import",
3723
+ params: z.object({ releaseId: CommunityReleaseIdSchema }).strict(),
3724
+ request: NoRequestBodySchema,
3725
+ response: ExtensionImportInspectionSchema,
3726
+ error: HostApiErrorSchema
3727
+ }),
3728
+ publishToCommunity: defineContract({
3729
+ timeoutMs: 12e4,
3730
+ method: "POST",
3731
+ path: "/api/community/publish",
3732
+ params: EmptyParamsSchema,
3733
+ request: z.object({
3734
+ extensionId: ExtensionIdSchema,
3735
+ revisionId: ExtensionRevisionIdSchema,
3736
+ notes: z.string().max(2e3)
3737
+ }).strict(),
3738
+ response: z.object({
3739
+ releaseId: CommunityReleaseIdSchema,
3740
+ reviewStatus: CommunityReviewStatusSchema,
3741
+ pageUrl: z.string().url(),
3742
+ reportUrl: z.string().url(),
3743
+ findings: z.array(z.object({
3744
+ severity: z.string(),
3745
+ title: z.string()
3746
+ }).strict())
3747
+ }).strict(),
3748
+ error: HostApiErrorSchema
3749
+ }),
3750
+ testMcpServer: defineContract({
3751
+ timeoutMs: 3e4,
3752
+ method: "POST",
3753
+ path: "/api/mcp-servers/test",
3754
+ params: EmptyParamsSchema,
3755
+ request: z.object({ server: McpServerFormSchema }).strict(),
3756
+ response: z.object({
3757
+ ok: z.boolean(),
3758
+ message: z.string(),
3759
+ serverName: z.string().optional(),
3760
+ tools: z.array(z.object({
3761
+ name: z.string(),
3762
+ description: z.string().optional()
3763
+ }).strict())
3764
+ }).strict(),
3765
+ error: HostApiErrorSchema
3766
+ }),
3767
+ createMcpExtension: defineContract({
3768
+ invalidatesSnapshot: true,
3769
+ timeoutMs: 12e4,
3770
+ method: "POST",
3771
+ path: "/api/mcp-servers",
3772
+ params: EmptyParamsSchema,
3773
+ request: z.object({
3774
+ displayName: z.string().trim().min(1).max(80),
3775
+ description: z.string().trim().max(500).default(""),
3776
+ server: McpServerFormSchema
3777
+ }).strict(),
3778
+ response: z.object({
3779
+ extensionId: ExtensionIdSchema,
3780
+ revisionId: ExtensionRevisionIdSchema,
3781
+ /** Credential config fields created for the form's secret rows, by row name. */
3782
+ secretFields: z.array(z.object({
3783
+ key: z.string(),
3784
+ name: z.string()
3785
+ }).strict())
3786
+ }).strict(),
3787
+ error: HostApiErrorSchema
3788
+ }),
3789
+ commitExtensionImport: defineContract({
3790
+ invalidatesSnapshot: true,
3791
+ timeoutMs: 3e5,
3792
+ method: "POST",
3793
+ path: "/api/extensions/imports/:token/commit",
3794
+ params: z.object({ token: NonEmptyStringSchema }).strict(),
3795
+ request: z.object({ localSlug: z.string().trim().min(3).max(64).optional() }).strict(),
3796
+ response: z.object({
3797
+ extensionId: ExtensionIdSchema,
3798
+ revisionId: ExtensionRevisionIdSchema,
3799
+ idempotent: z.boolean()
3800
+ }).strict(),
3801
+ error: HostApiErrorSchema
3802
+ }),
3803
+ dshSettings: defineContract({
3804
+ method: "GET",
3805
+ path: "/api/dsh/settings",
3806
+ params: EmptyParamsSchema,
3807
+ request: NoRequestBodySchema,
3808
+ response: z.object({ namespaces: z.array(DshSettingsNamespaceSchema) }).strict(),
3809
+ error: HostApiErrorSchema
3810
+ }),
3811
+ dshSettingsMutate: defineContract({
3812
+ invalidatesSnapshot: true,
3813
+ method: "POST",
3814
+ path: "/api/dsh/settings/:namespace/mutate",
3815
+ params: dshSettingsParam,
3816
+ request: DshSettingsMutationRequestSchema,
3817
+ response: DshSettingsNamespaceSchema,
3818
+ error: HostApiErrorSchema
3819
+ }),
3820
+ dshCredentialsDescribe: defineContract({
3821
+ method: "POST",
3822
+ path: "/api/dsh/credentials/describe",
3823
+ params: EmptyParamsSchema,
3824
+ request: z.object({ refs: z.array(DshCredentialRefSchema).max(64) }).strict(),
3825
+ response: z.object({ credentials: z.record(z.string(), DshCredentialViewSchema) }).strict(),
3826
+ error: HostApiErrorSchema
3827
+ }),
3828
+ dshCredentialSet: defineContract({
3829
+ invalidatesSnapshot: true,
3830
+ method: "PUT",
3831
+ path: "/api/dsh/credentials/:ref",
3832
+ params: dshCredentialParam,
3833
+ request: z.object({ value: z.string().min(1).max(64 * 1024) }).strict(),
3834
+ response: DshCredentialViewSchema,
3835
+ error: HostApiErrorSchema
3836
+ }),
3837
+ dshCredentialUnset: defineContract({
3838
+ invalidatesSnapshot: true,
3839
+ method: "DELETE",
3840
+ path: "/api/dsh/credentials/:ref",
3841
+ params: dshCredentialParam,
3842
+ request: NoRequestBodySchema,
3843
+ response: DshCredentialViewSchema,
3844
+ error: HostApiErrorSchema
3845
+ }),
3846
+ llmProviders: defineContract({
3847
+ method: "GET",
3848
+ path: "/api/llm/providers",
3849
+ params: EmptyParamsSchema,
3850
+ request: NoRequestBodySchema,
3851
+ response: LlmProviderSettingsSchema,
3852
+ error: HostApiErrorSchema
3853
+ }),
3854
+ llmDiscoverModels: defineContract({
3855
+ method: "POST",
3856
+ path: "/api/llm/discover-models",
3857
+ params: EmptyParamsSchema,
3858
+ request: z.object({
3859
+ provider: NonEmptyStringSchema.optional(),
3860
+ settingsNs: NonEmptyStringSchema.optional(),
3861
+ baseURL: z.url().optional(),
3862
+ api: NonEmptyStringSchema.optional(),
3863
+ apiKey: z.string().min(1).max(64 * 1024).optional()
3864
+ }).strict(),
3865
+ response: z.object({ models: z.array(LlmDiscoveredModelSchema) }).strict(),
3866
+ error: HostApiErrorSchema
3867
+ }),
3868
+ llmTestProvider: defineContract({
3869
+ method: "POST",
3870
+ path: "/api/llm/test-provider",
3871
+ params: EmptyParamsSchema,
3872
+ request: z.object({
3873
+ provider: NonEmptyStringSchema,
3874
+ model: NonEmptyStringSchema,
3875
+ settingsNs: NonEmptyStringSchema.optional(),
3876
+ apiKey: z.string().min(1).max(64 * 1024).optional(),
3877
+ baseURL: z.url().optional(),
3878
+ api: NonEmptyStringSchema.optional(),
3879
+ models: z.array(LlmDiscoveredModelSchema).optional()
3880
+ }).strict(),
3881
+ response: z.object({
3882
+ provider: NonEmptyStringSchema,
3883
+ model: NonEmptyStringSchema
3884
+ }).strict(),
3885
+ error: HostApiErrorSchema
3886
+ }),
3887
+ llmProviderRemovalImpact: defineContract({
3888
+ method: "GET",
3889
+ path: "/api/llm/providers/:provider/removal-impact",
3890
+ params: llmProviderParam,
3891
+ request: NoRequestBodySchema,
3892
+ response: z.object({
3893
+ provider: NonEmptyStringSchema,
3894
+ displayName: NonEmptyStringSchema,
3895
+ declared: z.boolean(),
3896
+ expectedRevision: z.number().int().nonnegative(),
3897
+ models: z.array(NonEmptyStringSchema),
3898
+ blockedReason: z.string(),
3899
+ references: z.array(z.object({
3900
+ agentId: AgentIdSchema,
3901
+ displayName: NonEmptyStringSchema,
3902
+ model: NonEmptyStringSchema,
3903
+ role: z.enum(["primary", "vision"]),
3904
+ scope: z.enum(["configuration", "context"]),
3905
+ channelId: ChannelIdSchema.optional(),
3906
+ channelName: z.string().optional(),
3907
+ episodeStatus: z.enum(["opening", "active"]).optional()
3908
+ }).strict())
3909
+ }).strict(),
3910
+ error: HostApiErrorSchema
3911
+ }),
3912
+ llmRemoveProvider: defineContract({
3913
+ invalidatesSnapshot: true,
3914
+ method: "DELETE",
3915
+ path: "/api/llm/providers/:provider",
3916
+ params: llmProviderParam,
3917
+ request: z.object({ expectedRevision: z.number().int().nonnegative() }).strict(),
3918
+ response: LlmProviderSettingsSchema,
3919
+ error: HostApiErrorSchema
3920
+ }),
3921
+ llmRestoreProviderModels: defineContract({
3922
+ invalidatesSnapshot: true,
3923
+ method: "POST",
3924
+ path: "/api/llm/providers/:provider/restore-models",
3925
+ params: llmProviderParam,
3926
+ request: z.object({ expectedRevision: z.number().int().nonnegative() }).strict(),
3927
+ response: LlmProviderSettingsSchema,
3928
+ error: HostApiErrorSchema
3929
+ }),
3930
+ llmSaveProvider: defineContract({
3931
+ invalidatesSnapshot: true,
3932
+ method: "POST",
3933
+ path: "/api/llm/providers/:provider",
3934
+ params: llmProviderParam,
3935
+ request: z.object({
3936
+ expectedRevision: z.number().int().nonnegative(),
3937
+ apiKey: z.string().min(1).max(64 * 1024).optional(),
3938
+ displayName: z.string().trim().min(1).max(120).optional(),
3939
+ baseURL: z.url().optional(),
3940
+ api: NonEmptyStringSchema.optional(),
3941
+ models: z.array(LlmDiscoveredModelSchema).optional()
3942
+ }).strict(),
3943
+ response: LlmProviderSettingsSchema,
3944
+ error: HostApiErrorSchema
3945
+ }),
3946
+ testConnection: defineContract({
3947
+ invalidatesSnapshot: true,
3948
+ method: "POST",
3949
+ path: "/api/connections/:connectionId/test",
3950
+ params: connectionParam,
3951
+ request: z.object({
3952
+ direction: z.enum(["send", "receive"]),
3953
+ channelId: ChannelIdSchema.optional()
3954
+ }).strict(),
3955
+ response: ConnectionTestResultSchema,
3956
+ error: HostApiErrorSchema
3957
+ }),
3958
+ dynamicInventory: defineContract({
3959
+ method: "POST",
3960
+ path: "/api/dynamic/:agentId/inventory",
3961
+ params: agentParam,
3962
+ request: z.object({ episodeId: EpisodeIdSchema }).strict(),
3963
+ response: z.object({ rows: z.array(DynamicInventoryRowSchema) }).strict(),
3964
+ error: HostApiErrorSchema
3965
+ }),
3966
+ dynamicApprove: defineContract({
3967
+ invalidatesSnapshot: true,
3968
+ method: "POST",
3969
+ path: "/api/dynamic/:agentId/approve",
3970
+ params: agentParam,
3971
+ request: z.object({
3972
+ episodeId: EpisodeIdSchema,
3973
+ requestId: DynamicIdSchema,
3974
+ pluginRunId: DynamicIdSchema.optional()
3975
+ }).strict(),
3976
+ response: z.object({ accepted: z.boolean() }).strict(),
3977
+ error: HostApiErrorSchema
3978
+ }),
3979
+ dynamicDecline: defineContract({
3980
+ invalidatesSnapshot: true,
3981
+ method: "POST",
3982
+ path: "/api/dynamic/:agentId/decline",
3983
+ params: agentParam,
3984
+ request: z.object({
3985
+ episodeId: EpisodeIdSchema,
3986
+ requestId: DynamicIdSchema,
3987
+ pluginRunId: DynamicIdSchema.optional()
3988
+ }).strict(),
3989
+ response: z.object({ accepted: z.boolean() }).strict(),
3990
+ error: HostApiErrorSchema
3991
+ }),
3992
+ dynamicInvoke: defineContract({
3993
+ method: "POST",
3994
+ path: "/api/dynamic/:agentId/invoke",
3995
+ params: agentParam,
3996
+ request: z.object({
3997
+ episodeId: EpisodeIdSchema,
3998
+ pluginId: DynamicIdSchema,
3999
+ pluginRunId: DynamicIdSchema,
4000
+ method: NonEmptyStringSchema,
4001
+ args: JsonValueSchema.optional()
4002
+ }).strict(),
4003
+ response: z.discriminatedUnion("ok", [z.object({
4004
+ ok: z.literal(true),
4005
+ value: JsonValueSchema
4006
+ }).strict(), z.object({
4007
+ ok: z.literal(false),
4008
+ message: z.string()
4009
+ }).strict()]),
4010
+ error: HostApiErrorSchema
4011
+ }),
4012
+ dynamicRunHostHalf: defineContract({
4013
+ method: "POST",
4014
+ path: "/api/dynamic/:agentId/run-host-half",
4015
+ params: agentParam,
4016
+ request: z.object({
4017
+ episodeId: EpisodeIdSchema,
4018
+ pluginId: DynamicIdSchema,
4019
+ packageId: DynamicIdSchema,
4020
+ mode: z.enum(["run", "update"]),
4021
+ requestId: DynamicIdSchema.nullable().optional(),
4022
+ approveFutureVersions: z.boolean().default(false)
4023
+ }).strict(),
4024
+ response: z.discriminatedUnion("ok", [z.object({
4025
+ ok: z.literal(true),
4026
+ pluginId: DynamicIdSchema,
4027
+ packageId: DynamicIdSchema,
4028
+ pluginRunId: DynamicIdSchema,
4029
+ waitingFor: z.array(z.string()),
4030
+ startedHere: z.boolean()
4031
+ }).strict(), DynamicErrorDetailsSchema.extend({ ok: z.literal(false) })]),
4032
+ error: HostApiErrorSchema
4033
+ }),
4034
+ dynamicSettleUserRun: defineContract({
4035
+ method: "POST",
4036
+ path: "/api/dynamic/:agentId/settle-user-run",
4037
+ params: agentParam,
4038
+ request: z.object({
4039
+ episodeId: EpisodeIdSchema,
4040
+ pluginId: DynamicIdSchema,
4041
+ resolution: DynamicRunResolutionSchema
4042
+ }).strict(),
4043
+ response: DynamicRunResponseSchema,
4044
+ error: HostApiErrorSchema
4045
+ }),
4046
+ dynamicGetClientCode: defineContract({
4047
+ method: "POST",
4048
+ path: "/api/dynamic/:agentId/get-client-code",
4049
+ params: agentParam,
4050
+ request: z.object({
4051
+ episodeId: EpisodeIdSchema,
4052
+ pluginId: DynamicIdSchema,
4053
+ pluginRunId: DynamicIdSchema
4054
+ }).strict(),
4055
+ response: z.object({
4056
+ code: z.string(),
4057
+ name: z.string(),
4058
+ pluginId: DynamicIdSchema,
4059
+ packageId: DynamicIdSchema,
4060
+ pluginRunId: DynamicIdSchema,
4061
+ /** What the candidate declared; preview data hooks enforce exactly what the saved Revision will. */
4062
+ permissions: HostUiPermissionDeclarationSchema.default({
4063
+ permissions: [],
4064
+ networkOrigins: []
4065
+ })
4066
+ }).strict(),
4067
+ error: HostApiErrorSchema
4068
+ }),
4069
+ dynamicReportRenderFailure: defineContract({
4070
+ method: "POST",
4071
+ path: "/api/dynamic/:agentId/report-render-failure",
4072
+ params: agentParam,
4073
+ request: z.object({
4074
+ episodeId: EpisodeIdSchema,
4075
+ pluginId: DynamicIdSchema,
4076
+ pluginRunId: DynamicIdSchema,
4077
+ failure: DynamicRenderFailureSchema
4078
+ }).strict(),
4079
+ response: z.object({ ok: z.literal(true) }).strict(),
4080
+ error: HostApiErrorSchema
4081
+ }),
4082
+ dynamicReportGuardFailure: defineContract({
4083
+ method: "POST",
4084
+ path: "/api/dynamic/:agentId/report-guard-failure",
4085
+ params: agentParam,
4086
+ request: z.object({
4087
+ episodeId: EpisodeIdSchema,
4088
+ pluginId: DynamicIdSchema,
4089
+ pluginRunId: DynamicIdSchema,
4090
+ message: z.string().min(1).max(4096),
4091
+ stack: z.string().max(16 * 1024).optional()
4092
+ }).strict(),
4093
+ response: z.object({ ok: z.literal(true) }).strict(),
4094
+ error: HostApiErrorSchema
4095
+ }),
4096
+ dynamicReportClientVerification: defineContract({
4097
+ method: "POST",
4098
+ path: "/api/dynamic/:agentId/report-client-verification",
4099
+ params: agentParam,
4100
+ request: z.object({
4101
+ episodeId: EpisodeIdSchema,
4102
+ pluginId: DynamicIdSchema,
4103
+ packageId: DynamicIdSchema,
4104
+ pluginRunId: DynamicIdSchema,
4105
+ renderedPanels: z.array(PanelContributionSchema).max(16).default([]),
4106
+ renderedToolViews: z.array(z.string().trim().min(1).max(64)).max(32).default([]),
4107
+ renderedMessageRenderers: z.array(RichKindSchema).max(32).default([]),
4108
+ renderedPages: z.array(HostPageContributionSchema).max(8).default([]),
4109
+ usedUiComponents: z.array(HostUiKitComponentNameSchema).max(HostUiKitComponentNameSchema.options.length).default([]),
4110
+ pageGeometry: z.array(HostUiPageGeometryEvidenceSchema).max(8).default([]),
4111
+ navigationEntries: z.array(z.string().trim().min(1).max(64)).max(8).default([])
4112
+ }).strict().refine((value) => value.renderedPanels.length > 0 || value.renderedToolViews.length > 0 || value.renderedMessageRenderers.length > 0 || value.renderedPages.length > 0, { message: "动态 Client 必须真实渲染至少一个面板、工具视图、富消息渲染器或页面。" }),
4113
+ response: z.object({ ok: z.literal(true) }).strict(),
4114
+ error: HostApiErrorSchema
4115
+ }),
4116
+ saveExtensionFromDynamic: defineContract({
4117
+ invalidatesSnapshot: true,
4118
+ timeoutMs: 3e5,
4119
+ method: "POST",
4120
+ path: "/api/extensions/save-from-dynamic",
4121
+ params: EmptyParamsSchema,
4122
+ request: z.union([z.object({
4123
+ taskId: AuthoringTaskIdSchema,
4124
+ attemptId: AuthoringAttemptIdSchema,
4125
+ displayName: z.string().trim().min(1).max(80),
4126
+ slug: z.string().trim().regex(/^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/u),
4127
+ description: z.string().max(500).default(""),
4128
+ targetExtensionId: ExtensionIdSchema.optional()
4129
+ }).strict(), z.object({
4130
+ agentId: AgentIdSchema,
4131
+ episodeId: EpisodeIdSchema,
4132
+ pluginId: DynamicIdSchema,
4133
+ packageId: DynamicIdSchema,
4134
+ displayName: z.string().trim().min(1).max(80),
4135
+ slug: z.string().trim().regex(/^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/u),
4136
+ description: z.string().max(500).default(""),
4137
+ targetExtensionId: ExtensionIdSchema.optional()
4138
+ }).strict()]),
4139
+ response: z.object({
4140
+ extensionId: ExtensionIdSchema,
4141
+ revisionId: ExtensionRevisionIdSchema,
4142
+ activation: z.literal("inactive"),
4143
+ installation: z.literal("uninstalled").optional()
4144
+ }).strict(),
4145
+ error: HostApiErrorSchema
4146
+ }),
4147
+ extensionClientCall: defineContract({
4148
+ method: "POST",
4149
+ path: "/api/extensions/:extensionId/revisions/:revisionId/call",
4150
+ params: extensionRevisionParam,
4151
+ request: z.object({
4152
+ agentId: AgentIdSchema,
4153
+ method: NonEmptyStringSchema,
4154
+ input: JsonValueSchema.optional()
4155
+ }).strict(),
4156
+ response: z.object({ value: JsonValueSchema }).strict(),
4157
+ error: HostApiErrorSchema
4158
+ }),
4159
+ extensionClientDiagnostic: defineContract({
4160
+ method: "POST",
4161
+ path: "/api/extensions/:extensionId/revisions/:revisionId/client-diagnostic",
4162
+ params: extensionRevisionParam,
4163
+ request: z.object({
4164
+ agentId: AgentIdSchema,
4165
+ status: z.enum(["loaded", "failed"]),
4166
+ message: z.string().max(4096).optional()
4167
+ }).strict(),
4168
+ response: z.object({ accepted: z.literal(true) }).strict(),
4169
+ error: HostApiErrorSchema
4170
+ }),
4171
+ hostExtensionClientDiagnostic: defineContract({
4172
+ method: "POST",
4173
+ path: "/api/extensions/:extensionId/revisions/:revisionId/host-client-diagnostic",
4174
+ params: extensionRevisionParam,
4175
+ request: z.object({
4176
+ status: z.enum(["loaded", "failed"]),
4177
+ message: z.string().max(4096).optional()
4178
+ }).strict(),
4179
+ response: z.object({ accepted: z.literal(true) }).strict(),
4180
+ error: HostApiErrorSchema
4181
+ }),
4182
+ activateExtension: defineContract({
4183
+ invalidatesSnapshot: true,
4184
+ method: "POST",
4185
+ path: "/api/agents/:agentId/extensions/:extensionId/activation",
4186
+ params: agentExtensionParam,
4187
+ request: z.object({
4188
+ revisionId: ExtensionRevisionIdSchema,
4189
+ permissionApproval: z.object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) }).strict().optional()
4190
+ }).strict(),
4191
+ response: z.object({ activation: z.object({
4192
+ agentId: AgentIdSchema,
4193
+ extensionId: ExtensionIdSchema,
4194
+ extensionRevisionId: ExtensionRevisionIdSchema,
4195
+ config: JsonValueSchema,
4196
+ configuredSecrets: z.array(z.string()).optional(),
4197
+ activatedAt: z.number().int().safe().nonnegative()
4198
+ }).strict() }).strict(),
4199
+ error: HostApiErrorSchema
4200
+ }),
4201
+ deactivateExtension: defineContract({
4202
+ invalidatesSnapshot: true,
4203
+ method: "DELETE",
4204
+ path: "/api/agents/:agentId/extensions/:extensionId/activation",
4205
+ params: agentExtensionParam,
4206
+ request: NoRequestBodySchema,
4207
+ response: z.object({ disabled: z.literal(true) }).strict(),
4208
+ error: HostApiErrorSchema
4209
+ }),
4210
+ updateExtensionActivationConfig: defineContract({
4211
+ invalidatesSnapshot: true,
4212
+ method: "PUT",
4213
+ path: "/api/agents/:agentId/extensions/:extensionId/activation/config",
4214
+ params: agentExtensionParam,
4215
+ request: z.object({
4216
+ config: JsonValueSchema,
4217
+ /** Write-only credential drafts keyed by secret field; an absent or empty draft keeps the stored one. */
4218
+ secrets: z.record(z.string(), z.string().max(8192)).optional()
4219
+ }).strict(),
4220
+ response: z.object({
4221
+ config: JsonValueSchema,
4222
+ configuredSecrets: z.array(z.string()).optional()
4223
+ }).strict(),
4224
+ error: HostApiErrorSchema
4225
+ }),
4226
+ updateHostExtensionConfig: defineContract({
4227
+ invalidatesSnapshot: true,
4228
+ timeoutMs: 3e5,
4229
+ method: "PUT",
4230
+ path: "/api/extensions/:extensionId/installation/config",
4231
+ params: extensionParam,
4232
+ request: z.object({ config: JsonValueSchema }).strict(),
4233
+ response: z.object({ config: JsonValueSchema }).strict(),
4234
+ error: HostApiErrorSchema
4235
+ }),
4236
+ installHostExtension: defineContract({
4237
+ invalidatesSnapshot: true,
4238
+ timeoutMs: 3e5,
4239
+ method: "PUT",
4240
+ path: "/api/extensions/:extensionId/installation",
4241
+ params: extensionParam,
4242
+ request: z.object({
4243
+ revisionId: ExtensionRevisionIdSchema,
4244
+ permissionApproval: z.object({ permissionDigest: z.string().regex(/^[a-f0-9]{64}$/u) }).strict().optional()
4245
+ }).strict(),
4246
+ response: z.object({ installation: z.object({
4247
+ extensionId: ExtensionIdSchema,
4248
+ extensionRevisionId: ExtensionRevisionIdSchema,
4249
+ installedAt: z.number().int().safe().nonnegative(),
4250
+ config: JsonValueSchema
4251
+ }).strict() }).strict(),
4252
+ error: HostApiErrorSchema
4253
+ }),
4254
+ uninstallHostExtension: defineContract({
4255
+ invalidatesSnapshot: true,
4256
+ timeoutMs: 3e5,
4257
+ method: "DELETE",
4258
+ path: "/api/extensions/:extensionId/installation",
4259
+ params: extensionParam,
4260
+ request: NoRequestBodySchema,
4261
+ response: z.object({ uninstalled: z.literal(true) }).strict(),
4262
+ error: HostApiErrorSchema
4263
+ }),
4264
+ updateHostUiPagePreferences: defineContract({
4265
+ invalidatesSnapshot: true,
4266
+ method: "PUT",
4267
+ path: "/api/host-ui/page-preferences",
4268
+ params: EmptyParamsSchema,
4269
+ request: z.object({
4270
+ expectedRevision: z.number().int().nonnegative(),
4271
+ entries: z.array(z.object({
4272
+ pageInstanceId: HostUiPageInstanceIdSchema,
4273
+ visible: z.boolean()
4274
+ }).strict())
4275
+ }).strict(),
4276
+ response: z.object({ revision: z.number().int().positive() }).strict(),
4277
+ error: HostApiErrorSchema
4278
+ }),
4279
+ callHostUiPage: defineContract({
4280
+ method: "POST",
4281
+ path: "/api/host-ui/pages/:pageInstanceId/call",
4282
+ params: z.object({ pageInstanceId: HostUiPageInstanceIdSchema }).strict(),
4283
+ request: z.object({
4284
+ method: NonEmptyStringSchema,
4285
+ input: JsonValueSchema.default({})
4286
+ }).strict(),
4287
+ response: z.object({ value: JsonValueSchema }).strict(),
4288
+ error: HostApiErrorSchema
4289
+ }),
4290
+ reportHostUiPageDiagnostic: defineContract({
4291
+ method: "POST",
4292
+ path: "/api/host-ui/pages/:pageInstanceId/diagnostic",
4293
+ params: z.object({ pageInstanceId: HostUiPageInstanceIdSchema }).strict(),
4294
+ request: z.object({
4295
+ status: z.enum([
4296
+ "ready",
4297
+ "load-failed",
4298
+ "navigation-failed",
4299
+ "rpc-failed"
4300
+ ]),
4301
+ message: z.string().max(2e3).optional()
4302
+ }).strict(),
4303
+ response: z.object({ recorded: z.literal(true) }).strict(),
4304
+ error: HostApiErrorSchema
4305
+ }),
4306
+ markChannelRead: defineContract({
4307
+ method: "POST",
4308
+ path: "/api/channels/:channelId/read",
4309
+ params: channelParam,
4310
+ request: z.object({
4311
+ /** Defaults to the newest inbound fact visible now. */
4312
+ upTo: z.object({
4313
+ occurredAt: z.number().int().safe().nonnegative(),
4314
+ sourceId: ChannelEventIdSchema
4315
+ }).strict().optional() }).strict(),
4316
+ response: z.object({
4317
+ channelId: ChannelIdSchema,
4318
+ activity: ChannelActivitySummarySchema
4319
+ }).strict(),
4320
+ error: HostApiErrorSchema
4321
+ }),
4322
+ listAttention: defineContract({
4323
+ method: "GET",
4324
+ path: "/api/attention",
4325
+ params: EmptyParamsSchema,
4326
+ request: NoRequestBodySchema,
4327
+ response: AttentionListSchema,
4328
+ error: HostApiErrorSchema
4329
+ }),
4330
+ dismissAttention: defineContract({
4331
+ method: "POST",
4332
+ path: "/api/attention/:attentionId/dismiss",
4333
+ params: z.object({ attentionId: z.string().min(1).max(200) }).strict(),
4334
+ request: NoRequestBodySchema,
4335
+ response: z.object({
4336
+ dismissed: z.literal(true),
4337
+ revision: z.string().min(1)
4338
+ }).strict(),
4339
+ error: HostApiErrorSchema
4340
+ }),
4341
+ getChannelPending: defineContract({
4342
+ method: "GET",
4343
+ path: "/api/channels/:channelId/pending",
4344
+ params: channelParam,
4345
+ request: NoRequestBodySchema,
4346
+ response: ChannelPendingContextSchema,
4347
+ error: HostApiErrorSchema
4348
+ }),
4349
+ stopChannelTask: defineContract({
4350
+ method: "POST",
4351
+ path: "/api/channels/:channelId/stop",
4352
+ params: channelParam,
4353
+ request: z.object({ expectedEpisodeId: EpisodeIdSchema.optional() }).strict(),
4354
+ response: z.object({
4355
+ result: z.enum(["stopped", "idle"]),
4356
+ episodeId: EpisodeIdSchema.optional(),
4357
+ /** Admitted messages that were not yet consumed and remain queued for the next turn. */
4358
+ retainedPending: z.number().int().nonnegative()
4359
+ }).strict(),
4360
+ error: HostApiErrorSchema
4361
+ }),
4362
+ resolveOutbound: defineContract({
4363
+ method: "POST",
4364
+ path: "/api/outbound/:outboundId/resolve",
4365
+ params: z.object({ outboundId: OutboundIntentIdSchema }).strict(),
4366
+ request: z.object({ action: z.enum(["retry", "confirm-delivered"]) }).strict(),
4367
+ response: z.object({
4368
+ outboundId: OutboundIntentIdSchema,
4369
+ action: z.enum(["retry", "confirm-delivered"]),
4370
+ deliveryState: z.enum([
4371
+ "planned",
4372
+ "sending",
4373
+ "sent",
4374
+ "partially-sent",
4375
+ "failed",
4376
+ "unknown"
4377
+ ]),
4378
+ resolvedAt: z.number().int().safe().nonnegative()
4379
+ }).strict(),
4380
+ error: HostApiErrorSchema
4381
+ }),
4382
+ getChannelActivity: defineContract({
4383
+ method: "GET",
4384
+ path: "/api/activity",
4385
+ params: ActivityQuerySchema,
4386
+ request: NoRequestBodySchema,
4387
+ response: ChannelActivitySeriesSchema,
4388
+ error: HostApiErrorSchema
4389
+ }),
4390
+ listAgentRevisions: defineContract({
4391
+ method: "GET",
4392
+ path: "/api/agents/:agentId/revisions",
4393
+ params: agentParam,
4394
+ request: NoRequestBodySchema,
4395
+ response: AgentRevisionHistorySchema,
4396
+ error: HostApiErrorSchema
4397
+ }),
4398
+ restoreAgentRevision: defineContract({
4399
+ invalidatesSnapshot: true,
4400
+ method: "POST",
4401
+ path: "/api/agents/:agentId/revisions/:revisionId/restore",
4402
+ params: agentRevisionParam,
4403
+ request: z.object({ expectedCurrentRevisionId: AgentRevisionIdSchema }).strict(),
4404
+ response: z.object({ currentRevisionId: AgentRevisionIdSchema }).strict(),
4405
+ error: HostApiErrorSchema
4406
+ }),
4407
+ updateAgentAppearance: defineContract({
4408
+ invalidatesSnapshot: true,
4409
+ method: "PATCH",
4410
+ path: "/api/agents/:agentId/appearance",
4411
+ params: agentParam,
4412
+ request: z.object({
4413
+ hue: z.number().int().min(0).max(359).nullable().optional(),
4414
+ /** `null` removes the avatar; uploading uses `uploadAgentAvatar`. */
4415
+ avatarAssetId: z.null().optional()
4416
+ }).strict(),
4417
+ response: z.object({
4418
+ agentId: AgentIdSchema,
4419
+ appearance: AgentAppearanceSchema
4420
+ }).strict(),
4421
+ error: HostApiErrorSchema
4422
+ }),
4423
+ uploadAgentAvatar: defineContract({
4424
+ invalidatesSnapshot: true,
4425
+ method: "POST",
4426
+ path: "/api/agents/:agentId/avatar",
4427
+ params: agentParam,
4428
+ request: BinaryUploadRequestSchema,
4429
+ encodeRequest: encodeBinaryUpload,
4430
+ response: z.object({
4431
+ agentId: AgentIdSchema,
4432
+ appearance: AgentAppearanceSchema
4433
+ }).strict(),
4434
+ error: HostApiErrorSchema
4435
+ }),
4436
+ deleteLocalExtension: defineContract({
4437
+ invalidatesSnapshot: true,
4438
+ method: "DELETE",
4439
+ path: "/api/extensions/:extensionId",
4440
+ params: extensionParam,
4441
+ request: NoRequestBodySchema,
4442
+ response: z.object({ deleted: z.literal(true) }).strict(),
4443
+ error: HostApiErrorSchema
4444
+ })
4445
+ };
4446
+ const pathParameterPattern = /:([A-Za-z][A-Za-z0-9]*)/gu;
4447
+ /** Build the transport URL only after all path/query parameters pass the shared schema. */
4448
+ const buildValidatedHostApiPath = (contract, input) => {
4449
+ const params = z.record(z.string(), z.unknown()).parse(contract.params.parse(input));
4450
+ const consumed = /* @__PURE__ */ new Set();
4451
+ const pathname = contract.path.replace(pathParameterPattern, (_placeholder, key) => {
4452
+ const value = params[key];
4453
+ if (typeof value !== "string") throw new TypeError(`Host API path parameter ${key} must be a string.`);
4454
+ consumed.add(key);
4455
+ return encodeURIComponent(value);
4456
+ });
4457
+ const query = new URLSearchParams();
4458
+ for (const [key, value] of Object.entries(params)) {
4459
+ if (consumed.has(key) || value === void 0) continue;
4460
+ 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.`);
4461
+ query.set(key, String(value));
4462
+ }
4463
+ const suffix = query.toString();
4464
+ return suffix ? `${pathname}?${suffix}` : pathname;
4465
+ };
4466
+ function buildHostApiContractPath(contract, input) {
4467
+ return buildValidatedHostApiPath(contract, input);
4468
+ }
4469
+ function buildHostApiPath(name, input) {
4470
+ return buildValidatedHostApiPath(HostApiContracts[name], input);
4471
+ }
4472
+ //#endregion
4473
+ 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_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, CommunityExtensionDetailSchema, CommunityExtensionSummarySchema, CommunityGradeSchema, CommunityPermissionItemSchema, CommunityReleaseIdSchema, CommunityReleaseSchema, CommunityReviewStatusSchema, 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, communityReviewLabel, configDescription, configFieldKind, configFields, configSchema, configSecretKeys, extensionCapabilitiesExpand, insecureHttpManagementPairProofMessage, managementPairProofMessage, mcpSecretFields, messagePartAssetId, messagePartAssetIds, messagePartsSearchText, normalizePromptDocument, parseConfigValue, parseJsonValue, parseMessageParts, promptDocumentFromText, promptDocumentPlainText, richPartContextText, summarizeExtensionCapabilities, validateConfigValue };
4474
+
4475
+ //# sourceMappingURL=index.mjs.map