paseo-plugin-zcode-provider 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/NOTICE.md +3 -3
  2. package/README.md +15 -15
  3. package/client/runtime.tsx +1 -1
  4. package/package.json +7 -6
  5. package/server/account.ts +10 -0
  6. package/server/build-info.ts +1 -1
  7. package/server/discovery/manifest.ts +2 -2
  8. package/server/host/bridge.ts +2 -0
  9. package/server/mapping.ts +31 -0
  10. package/server/provider.ts +5 -18
  11. package/server/runtime/pins.ts +7 -5
  12. package/server/session.ts +9 -10
  13. package/server/unsupported-capabilities.ts +21 -0
  14. package/server/vendor/zcode/NOTICE.md +4 -1
  15. package/server/vendor/zcode/packages/rpc/src/channelClient.ts +1 -0
  16. package/server/vendor/zcode/packages/rpc/src/channelServer.ts +2 -0
  17. package/server/vendor/zcode/packages/rpc/src/channels.shared.ts +1 -0
  18. package/server/vendor/zcode/packages/rpc/src/protocol.ts +3 -2
  19. package/server/vendor/zcode/packages/shared/src/app-runtime-preferences.ts +18 -0
  20. package/server/vendor/zcode/packages/shared/src/attachment-source.ts +5 -0
  21. package/server/vendor/zcode/packages/shared/src/bots.ts +385 -2
  22. package/server/vendor/zcode/packages/shared/src/browser-use/commands.ts +3 -1
  23. package/server/vendor/zcode/packages/shared/src/channel-mention.ts +131 -0
  24. package/server/vendor/zcode/packages/shared/src/conversationSelection.ts +37 -0
  25. package/server/vendor/zcode/packages/shared/src/dynamic-workflow-feature.ts +137 -0
  26. package/server/vendor/zcode/packages/shared/src/env.ts +15 -11
  27. package/server/vendor/zcode/packages/shared/src/highspeed.ts +232 -0
  28. package/server/vendor/zcode/packages/shared/src/mcp-apps/appTools.ts +148 -0
  29. package/server/vendor/zcode/packages/shared/src/mcp-apps/contract.ts +262 -0
  30. package/server/vendor/zcode/packages/shared/src/mcp-apps/instance.ts +12 -0
  31. package/server/vendor/zcode/packages/shared/src/mcp-apps/resourceMime.ts +73 -0
  32. package/server/vendor/zcode/packages/shared/src/mcp-apps/sampling.ts +117 -0
  33. package/server/vendor/zcode/packages/shared/src/mcp-apps/schemas.ts +90 -0
  34. package/server/vendor/zcode/packages/shared/src/model-execution.ts +58 -1
  35. package/server/vendor/zcode/packages/shared/src/oauth.ts +3 -0
  36. package/server/vendor/zcode/packages/shared/src/off-peak-execution.ts +73 -0
  37. package/server/vendor/zcode/packages/shared/src/protocol.ts +78 -4
  38. package/server/vendor/zcode/packages/shared/src/remoteTarget.ts +65 -0
  39. package/server/vendor/zcode/packages/shared/src/request-security-edition/verification-policy.ts +46 -0
  40. package/server/vendor/zcode/packages/shared/src/server-remote.ts +93 -0
  41. package/server/vendor/zcode/packages/shared/src/source-server/compatibility.ts +115 -0
  42. package/server/vendor/zcode/packages/shared/src/source-server/contracts.ts +426 -0
  43. package/server/vendor/zcode/packages/shared/src/source-server/errorCodes.ts +74 -0
  44. package/server/vendor/zcode/packages/shared/src/sqlite-migrations/contract.ts +83 -0
  45. package/server/vendor/zcode/packages/shared/src/subagent-profile.ts +62 -0
  46. package/server/vendor/zcode/packages/shared/src/subagent-runtime-config.ts +51 -0
  47. package/server/vendor/zcode/packages/shared/src/subagents-types.ts +164 -0
  48. package/server/vendor/zcode/packages/shared/src/usage-stats.ts +14 -0
  49. package/server/vendor/zcode/packages/shared/src/validationAppSettings.ts +136 -3
  50. package/server/vendor/zcode/packages/shared/src/version.ts +13 -0
  51. package/server/vendor/zcode/packages/shared/src/zcode-agent-policy.ts +24 -1
  52. package/server/vendor/zcode/packages/shared/src/zcode-protocol/index.ts +697 -36
  53. package/server/vendor/zcode/packages/shared/src/zcode-protocol/trace.ts +11 -0
  54. package/server/vendor/zcode/packages/shared/src/zcode-protocol-legacy-types.ts +14 -2
  55. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/apply.ts +28 -9
  56. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/attachment-ref.ts +3 -0
  57. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/command.ts +73 -53
  58. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/create-session-config.ts +15 -0
  59. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/create-workflow-display.ts +47 -1
  60. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/delta.ts +58 -2
  61. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/input-intent.ts +31 -0
  62. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/rows.ts +28 -13
  63. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index-workflow-activity.ts +37 -3
  64. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index.ts +36 -0
  65. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/snapshot.ts +21 -0
  66. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/submission.ts +1 -1
  67. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/toolDisplay.ts +32 -4
  68. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.ts +31 -6
  69. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-assembler.ts +4 -1
  70. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-fault.ts +4 -1
  71. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-artifacts.ts +62 -4
  72. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-command-rejections.ts +30 -0
  73. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-row-meta.ts +40 -3
  74. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-run-settings-command.ts +2 -2
  75. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs-delta.ts +6 -5
  76. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs.ts +103 -26
  77. package/server/vendor/zcode/packages/shared/src/zcode-task-mode-schema.ts +13 -1
  78. package/server/vendor/zcode/packages/shared/src/zcode-task-types-core.ts +31 -2
  79. package/server/vendor/zcode/packages/shared/src/zcodeEndpoint.ts +188 -73
  80. package/server/vendor/zcode/provenance.json +189 -80
@@ -1,6 +1,9 @@
1
+ import { zcodeProtocolTraceSchema, type ZCodeProtocolTrace } from "./zcode-protocol/trace.js";
2
+ import { channelContentPartsSchema, type ChannelContentPart } from "./channel-mention.js";
1
3
  /* oxlint-disable eslint(max-lines) -- Bot 共享合约集中维护 provider、状态和 schema,保持类型与校验就近。 */
2
4
  import { z } from "zod";
3
5
  import { modelSelectionSchema, type ModelSelection } from "./model-selection.js";
6
+ import { conversationQuotesSchema } from "./conversationSelection.js";
4
7
  import { ZCODE_AGENT_PROVIDER, ZCODE_AGENT_PROVIDER_LABEL } from "./zcode-agent-policy.js";
5
8
  import type {
6
9
  ZCodeConfigOption,
@@ -44,6 +47,8 @@ export const zcodeAutomationBotDeliveryTargetSchema = z
44
47
  botId: z.string().trim().min(1),
45
48
  providerUserId: z.string().trim().min(1),
46
49
  chatType: z.enum(["private", "group"]),
50
+ threadId: z.string().min(1).optional(),
51
+ rootMessageId: z.string().min(1).optional(),
47
52
  })
48
53
  .strict();
49
54
 
@@ -76,6 +81,10 @@ export interface BotWorkspaceRef {
76
81
  label: string;
77
82
  workspacePath: string;
78
83
  workspaceIdentity?: string;
84
+ /** 新版选择虚拟项目;旧协议字段名保留。空 roots 在提交时才分配 cwd。 */
85
+ projectId?: string;
86
+ hostId?: string;
87
+ rootPaths?: string[];
79
88
  }
80
89
 
81
90
  export interface BotAllowedCommands {
@@ -176,9 +185,14 @@ export interface BotsConfigFile {
176
185
 
177
186
  export interface BotState {
178
187
  botId: string;
188
+ group?: BotGroupSession;
179
189
  workspacePath: string;
180
190
  workspaceIdentity?: string;
181
191
  workspaceId?: string;
192
+ /** hostId 缺席表示旧状态待交接;明确 NULL 项目不会再次按目录归入。 */
193
+ projectId?: string | null;
194
+ hostId?: string;
195
+ additionalDirectories?: string[];
182
196
  mode: BotContextMode;
183
197
  activeTaskId: string | null;
184
198
  draftOptions?: BotDraftOptions;
@@ -187,11 +201,263 @@ export interface BotState {
187
201
  telegramOffset?: number;
188
202
  weixinGetUpdatesBuf?: string;
189
203
  weixinActivatedAt?: number;
204
+ /** 单聊绑定代际,阻止换绑后迟到事件恢复旧关联。 */
205
+ privateBindingId?: string;
206
+ /** iLink 登录返回机器人身份,单聊接收人来自已授权入站消息。 */
207
+ privateRecipientId?: string;
190
208
  updatedAt: number;
191
209
  }
192
210
 
193
211
  export type BotContextState = BotState;
194
212
 
213
+ export const botGroupDeliverySchema = z
214
+ .object({
215
+ /** 名字解析前的请求指纹;重复调用只读原回执,不因目录变化改发给其他人。 */
216
+ channelReplyRequestHash: z
217
+ .string()
218
+ .regex(/^[a-f0-9]{64}$/u)
219
+ .optional(),
220
+ appId: z.string().optional(),
221
+ trace: zcodeProtocolTraceSchema.optional(),
222
+ authorizationId: z.string().optional(),
223
+ id: z.string().min(1),
224
+ taskId: z.string().min(1),
225
+ sourceCommandId: z.string().min(1).optional(),
226
+ text: z.string(),
227
+ replyToMessageId: z.string().optional(),
228
+ mentionedUserIds: z.array(z.string().min(1)).max(200).optional(),
229
+ contentParts: channelContentPartsSchema.optional(),
230
+ providerMessageId: z.string().optional(),
231
+ threadId: z.string().min(1).optional(),
232
+ rootMessageId: z.string().optional(),
233
+ status: z.enum(["pending", "sent", "failed", "unknown", "invalidated"]),
234
+ lastError: z.string().optional(),
235
+ updatedAt: z.number(),
236
+ })
237
+ .strict();
238
+ export type BotGroupDelivery = z.infer<typeof botGroupDeliverySchema>;
239
+
240
+ export const botGroupCardSchema = z
241
+ .object({
242
+ chatId: z.string().min(1),
243
+ threadId: z.string().min(1).optional(),
244
+ conversationThreadId: z.string().min(1).nullable().optional(),
245
+ taskId: z.string().nullable(),
246
+ authorizationId: z.string().min(1),
247
+ })
248
+ .strict();
249
+ export type BotGroupCard = z.infer<typeof botGroupCardSchema>;
250
+
251
+ export const botTopicMessageSchema = z
252
+ .object({
253
+ id: z.string().min(1),
254
+ chatId: z.string().min(1),
255
+ threadId: z.string().min(1),
256
+ senderId: z.string(),
257
+ senderName: z.string().optional(),
258
+ parentId: z.string().optional(),
259
+ attachments: z.array(z.object({ name: z.string(), kind: z.string() }).strict()).optional(),
260
+ senderType: z.enum(["user", "app"]),
261
+ text: z.string(),
262
+ createdAt: z.number(),
263
+ kind: z.string(),
264
+ controlCard: z.boolean().optional(),
265
+ deleted: z.boolean().optional(),
266
+ })
267
+ .strict();
268
+ export type BotTopicMessage = z.infer<typeof botTopicMessageSchema>;
269
+
270
+ export interface BotTopicHistoryRequest {
271
+ chatId: string;
272
+ threadId: string;
273
+ rootMessageId: string;
274
+ messageId: string;
275
+ checkpoint?: string;
276
+ }
277
+
278
+ export const botTopicContextSchema = z
279
+ .object({
280
+ messages: z.array(botTopicMessageSchema).max(201),
281
+ checkpoint: z.string().min(1),
282
+ hasGap: z.boolean(),
283
+ })
284
+ .strict();
285
+ export type BotTopicHistoryBatch = z.infer<typeof botTopicContextSchema>;
286
+
287
+ export const botIdentitySchema = z
288
+ .object({ name: z.string().min(1), openId: z.string().min(1).optional() })
289
+ .strict();
290
+ export const botBackgroundHistorySchema = z
291
+ .object({ revision: z.string().min(1), checkpoint: z.string().min(1).optional() })
292
+ .strict();
293
+
294
+ export const botAutoReplyGuardSchema = z
295
+ .object({
296
+ consecutive: z.number().int().min(0).max(5),
297
+ messageIds: z.array(z.string().min(1)),
298
+ })
299
+ .strict();
300
+
301
+ export interface BotGroupSession {
302
+ preparation?: BotTopicPreparation[];
303
+ chatId: string;
304
+ chatMode?: "group" | "topic";
305
+ threadId?: string;
306
+ rootMessageId?: string;
307
+ topicTitle?: string;
308
+ topicUrl?: string;
309
+ /** 仅群默认记录拥有此配置;话题按群授权检查读取。 */
310
+ historyEnabled?: boolean;
311
+ /** 仅成功接收首次输入后接入;leave 后保留任务但停止普通消息触发。 */
312
+ topicActive?: boolean;
313
+ topicAliases?: Record<string, { taskId: string; rootMessageId: string }>;
314
+ name: string;
315
+ ownerId: string;
316
+ enabled: boolean;
317
+ taskIds: string[];
318
+ taskWorkspaces?: Record<string, { workspacePath: string; workspaceIdentity?: string }>;
319
+ currentOptions: BotCurrentOptions;
320
+ initiatorId?: string;
321
+ authorizationId?: string;
322
+ deliveries?: Record<string, BotGroupDelivery>;
323
+ autoReplyGuard?: z.infer<typeof botAutoReplyGuardSchema>;
324
+ backgroundHistory?: z.infer<typeof botBackgroundHistorySchema>;
325
+ inputs?: Record<
326
+ string,
327
+ {
328
+ taskId: string;
329
+ source: BotGroupInputSource;
330
+ admission?: "pending" | "accepted" | "rejected";
331
+ progress?: BotGroupInputProgress;
332
+ }
333
+ >;
334
+ }
335
+
336
+ export const botGroupInputStatusSchema = z.enum([
337
+ "waiting",
338
+ "working",
339
+ "done",
340
+ "failed",
341
+ "stopped",
342
+ "cancelled",
343
+ "discarded",
344
+ ]);
345
+ export type BotGroupInputStatus = z.infer<typeof botGroupInputStatusSchema>;
346
+ export const botTopicPreparationSchema = z
347
+ .object({
348
+ contentParts: channelContentPartsSchema.optional(),
349
+ messageId: z.string().min(1),
350
+ senderName: z.string(),
351
+ text: z.string(),
352
+ status: z.enum(["preparing", "waitingStop", "failed"]),
353
+ error: z.string().optional(),
354
+ })
355
+ .strict();
356
+ export type BotTopicPreparation = z.infer<typeof botTopicPreparationSchema>;
357
+ export const botGroupInputProgressSchema = z
358
+ .object({
359
+ status: botGroupInputStatusSchema,
360
+ interruptionReason: z.literal("newMessage").optional(),
361
+ cardMessageId: z.string().min(1).optional(),
362
+ cardStatus: botGroupInputStatusSchema.optional(),
363
+ })
364
+ .strict();
365
+ export type BotGroupInputProgress = z.infer<typeof botGroupInputProgressSchema>;
366
+
367
+ /** CLI 只接收轻量材料索引;原文留在 Host 归档及文本附件。 */
368
+ export const botTopicHistorySourceSchema = z
369
+ .object({
370
+ checkpoint: z.string().min(1).max(256),
371
+ hasGap: z.boolean(),
372
+ messageCount: z.number().int().min(0).max(201),
373
+ resourceMessages: z
374
+ .array(
375
+ z
376
+ .object({
377
+ messageId: z.string().min(1).max(256),
378
+ count: z.number().int().min(1).max(1000),
379
+ })
380
+ .strict(),
381
+ )
382
+ .max(201),
383
+ })
384
+ .strict();
385
+
386
+ export const botTopicInputMessageSchema = z
387
+ .object({
388
+ contentParts: channelContentPartsSchema.optional(),
389
+ messageId: z.string().min(1),
390
+ senderId: z.string().min(1),
391
+ senderName: z.string(),
392
+ mentionedBot: z.boolean().optional(),
393
+ text: z.string(),
394
+ conversationQuotes: conversationQuotesSchema.optional(),
395
+ attachmentIndexes: z.array(z.number().int().nonnegative()),
396
+ })
397
+ .strict();
398
+
399
+ /** 可信 Host 注入的输入来源;身份展示不能反向授予执行权限。 */
400
+ export const botGroupInputSourceSchema = z
401
+ .object({
402
+ botIdentity: botIdentitySchema.optional(),
403
+ appId: z.string().min(1).optional(),
404
+ contentParts: channelContentPartsSchema.optional(),
405
+ authorizationId: z.string().min(1).optional(),
406
+ botId: z.string().min(1),
407
+ provider: z.enum(["feishu", "lark"]),
408
+ chatId: z.string().min(1),
409
+ threadId: z.string().min(1).optional(),
410
+ rootMessageId: z.string().optional(),
411
+ senderId: z.string().min(1),
412
+ senderName: z.string(),
413
+ mentionedBot: z.boolean().optional(),
414
+ messageId: z.string().min(1),
415
+ messages: z.array(botTopicInputMessageSchema).min(1).max(200).optional(),
416
+ topicContext: botTopicContextSchema.optional(),
417
+ topicHistory: botTopicHistorySourceSchema.optional(),
418
+ })
419
+ .strict()
420
+ .superRefine((source, ctx) => {
421
+ if (
422
+ source.messages &&
423
+ (!source.threadId ||
424
+ source.messages.at(-1)?.messageId !== source.messageId ||
425
+ new Set(source.messages.map((message) => message.messageId)).size !==
426
+ source.messages.length)
427
+ ) {
428
+ ctx.addIssue({
429
+ code: "custom",
430
+ path: ["messages"],
431
+ message: "Topic batch boundary mismatch",
432
+ });
433
+ }
434
+
435
+ if (
436
+ source.topicHistory &&
437
+ (!source.threadId || source.topicHistory.checkpoint !== source.messageId)
438
+ ) {
439
+ ctx.addIssue({
440
+ code: "custom",
441
+ path: ["topicHistory"],
442
+ message: "Topic history scope mismatch",
443
+ });
444
+ }
445
+ if (
446
+ source.topicContext &&
447
+ (!source.threadId ||
448
+ source.topicContext.checkpoint !== source.messageId ||
449
+ source.topicContext.messages.some(
450
+ (m) => m.chatId !== source.chatId || m.threadId !== source.threadId,
451
+ ))
452
+ )
453
+ ctx.addIssue({
454
+ code: "custom",
455
+ path: ["topicContext"],
456
+ message: "Topic context scope mismatch",
457
+ });
458
+ });
459
+ export type BotGroupInputSource = z.infer<typeof botGroupInputSourceSchema>;
460
+
195
461
  export interface BotsStateFile {
196
462
  version: 3;
197
463
  bots: Record<string, BotState>;
@@ -200,6 +466,8 @@ export interface BotsStateFile {
200
466
  export interface BotRuntimeInfo {
201
467
  /** 最近一次消息投递错误;独立于长连接状态,成功投递后清除。 */
202
468
  deliveryError?: string;
469
+ /** 当前进程保留的失败单聊回复;显式重试可能重复此前已收到的内容。 */
470
+ deliveryRetryId?: string;
203
471
  botId: string;
204
472
  provider: BotProvider;
205
473
  status: "disabled" | "idle" | "polling" | "connected" | "error";
@@ -210,12 +478,20 @@ export interface BotRuntimeInfo {
210
478
  }
211
479
 
212
480
  export interface BotActor {
481
+ /** 本次可信输入是否明确提及机器人;用于话题回复提醒。 */
482
+ mentionedBot?: boolean;
213
483
  provider: BotProvider;
214
484
  botId: string;
215
485
  providerUserId: string;
216
486
  displayName?: string;
217
487
  chatType: "private" | "group";
218
488
  chatId?: string;
489
+ threadId?: string;
490
+ /** 仅服务根据已保存的结果关联设置;null 表示原群默认任务。 */
491
+ conversationThreadId?: string | null;
492
+ rootMessageId?: string;
493
+ topicTitle?: string;
494
+ topicUrl?: string;
219
495
  providerMessageId?: string;
220
496
  providerContextToken?: string;
221
497
  }
@@ -236,6 +512,10 @@ export interface BotInboundAttachment {
236
512
  }
237
513
 
238
514
  export type BotCommand =
515
+ | { type: "group.history"; enabled?: boolean }
516
+ | { type: "queue.cancel"; commandId: string }
517
+ | { type: "group.enable" }
518
+ | { type: "group.disable" }
239
519
  | { type: "bind"; code: string }
240
520
  | { type: "help" }
241
521
  | { type: "status" }
@@ -255,6 +535,7 @@ export type BotCommand =
255
535
  | { type: "reply.list" }
256
536
  | { type: "reply.set"; value: string }
257
537
  | { type: "stop" }
538
+ | { type: "topic.leave" }
258
539
  | { type: "permission.respond"; value: string }
259
540
  | { type: "elicitation.respond"; value: string }
260
541
  | { type: "elicitation.submit" }
@@ -272,6 +553,7 @@ export interface SelectionPrompt {
272
553
  cancelLabel?: string;
273
554
  showCancel?: boolean;
274
555
  action:
556
+ | "queue.cancel"
275
557
  | "workspace.set"
276
558
  | "model.provider.set"
277
559
  | "model.set"
@@ -289,6 +571,23 @@ export interface SelectionPrompt {
289
571
  }
290
572
 
291
573
  export interface BotInboundMessage {
574
+ /** 仅供命令/纯唤醒识别;原文 text 和 contentParts 保持完整。 */
575
+ commandText?: string;
576
+ /** Provider 核验的当前机器人身份,不从正文推断。 */
577
+ botOpenId?: string;
578
+ /** Provider 校验的发送者类型;机器人正文不具有控制命令权限。 */
579
+ senderType?: "user" | "app";
580
+ contentParts?: ChannelContentPart[];
581
+ /** 由 Provider 根据真实 mention 身份设置;不是正文解析结果。 */
582
+ mentionedBot?: boolean;
583
+ /** 原生根消息经 Provider 核验确为当前机器人发送。 */
584
+ topicRootIsCurrentBot?: boolean;
585
+ /** 可信 Provider 校验后的明确引用,不参与控制命令解析。 */
586
+ referencedMessage?: import("./conversationSelection.js").ConversationSelectionText & {
587
+ messageId: string;
588
+ };
589
+ groupCard?: BotGroupCard;
590
+ groupCardAction?: boolean;
292
591
  botId: string;
293
592
  actor: BotActor;
294
593
  text: string;
@@ -298,6 +597,12 @@ export interface BotInboundMessage {
298
597
  }
299
598
 
300
599
  export interface BotOutboundMessage {
600
+ trace?: ZCodeProtocolTrace;
601
+ contentParts?: ChannelContentPart[];
602
+ groupCard?: BotGroupCard;
603
+ threadId?: string;
604
+ conversationThreadId?: string | null;
605
+ rootMessageId?: string;
301
606
  botId: string;
302
607
  provider: BotProvider;
303
608
  providerUserId: string;
@@ -306,6 +611,18 @@ export interface BotOutboundMessage {
306
611
  selection?: SelectionPrompt;
307
612
  elicitation?: BotOutboundElicitationRequest;
308
613
  providerContextToken?: string;
614
+ /** 无权限/过期回调只能提示操作者,不能覆盖群共享卡片。 */
615
+ callbackToastOnly?: boolean;
616
+ /** 管理员待办独立通知,不允许用拒绝提示覆盖共享卡片。 */
617
+ administratorAttention?: boolean;
618
+ replyToMessageId?: string;
619
+ /** 可信输入决定的提醒对象;只作展示,不授予群操作权限。 */
620
+ mentionedUserIds?: string[];
621
+ deliveryId?: string;
622
+ /** 任务回推需在实际发送前重新验证群当前关联。控制命令回复不携带。 */
623
+ groupTaskId?: string;
624
+ /** 可信任务事件中的输入命令,用于将投递状态定位到对应回复。 */
625
+ groupSourceCommandId?: string;
309
626
  }
310
627
 
311
628
  export interface BotTaskSummary {
@@ -395,6 +712,13 @@ export const botAllowedCommandsSchema = z
395
712
 
396
713
  export const botCommandPolicySchema = botAllowedCommandsSchema;
397
714
 
715
+ // 修复原因:第三方 CLI provider 已移除,ZCodeProvider 只剩 glm,但旧 bot 配置与状态文件里可能仍存有
716
+ // 已移除 provider 的历史值。改成严格 literal 会让整份文件 parse 失败、Bot 全部不可用;
717
+ // 因此解析时继续接受这些历史值,并统一归一到当前唯一的 agent provider。
718
+ const legacyBotAgentProviderSchema = z
719
+ .enum(["codex", "claude", "opencode", "gemini", "glm"])
720
+ .transform((): typeof ZCODE_AGENT_PROVIDER => ZCODE_AGENT_PROVIDER);
721
+
398
722
  export const botCurrentOptionsSchema = z
399
723
  .object({
400
724
  modelSelection: modelSelectionSchema.optional(),
@@ -402,13 +726,13 @@ export const botCurrentOptionsSchema = z
402
726
  sandboxMode: z.string().min(1).optional(),
403
727
  approvalPolicy: z.string().min(1).optional(),
404
728
  // 兼容旧 bot-config.json;CLI provider 现在统一由 ZCode Protocol 侧配置决定。
405
- cli: z.literal(ZCODE_AGENT_PROVIDER).optional(),
729
+ cli: legacyBotAgentProviderSchema.optional(),
406
730
  })
407
731
  .strict();
408
732
 
409
733
  export const botDraftOptionsSchema = z
410
734
  .object({
411
- provider: z.literal(ZCODE_AGENT_PROVIDER),
735
+ provider: legacyBotAgentProviderSchema,
412
736
  modelSelection: modelSelectionSchema.optional(),
413
737
  mode: z.string().min(1).optional(),
414
738
  })
@@ -492,9 +816,66 @@ export const botsStateFileSchema = z
492
816
  z.string(),
493
817
  z.object({
494
818
  botId: z.string().min(1),
819
+ group: z
820
+ .object({
821
+ chatId: z.string().trim().min(1),
822
+ chatMode: z.enum(["group", "topic"]).optional(),
823
+ threadId: z.string().trim().min(1).optional(),
824
+ rootMessageId: z.string().min(1).optional(),
825
+ topicTitle: z.string().optional(),
826
+ topicUrl: z.string().url().optional(),
827
+ historyEnabled: z.boolean().optional(),
828
+ topicActive: z.boolean().optional(),
829
+ preparation: z.array(botTopicPreparationSchema).optional(),
830
+ topicAliases: z
831
+ .record(
832
+ z.string(),
833
+ z.object({ taskId: z.string().min(1), rootMessageId: z.string().min(1) }).strict(),
834
+ )
835
+ .optional(),
836
+ name: z.string(),
837
+ ownerId: z.string().min(1),
838
+ enabled: z.boolean(),
839
+ taskIds: z.array(z.string().min(1)),
840
+ taskWorkspaces: z
841
+ .record(
842
+ z.string(),
843
+ z
844
+ .object({
845
+ workspacePath: z.string().min(1),
846
+ workspaceIdentity: z.string().optional(),
847
+ })
848
+ .strict(),
849
+ )
850
+ .optional(),
851
+ currentOptions: botCurrentOptionsSchema,
852
+ initiatorId: z.string().optional(),
853
+ authorizationId: z.string().optional(),
854
+ deliveries: z.record(z.string(), botGroupDeliverySchema).optional(),
855
+ autoReplyGuard: botAutoReplyGuardSchema.optional(),
856
+ backgroundHistory: botBackgroundHistorySchema.optional(),
857
+ inputs: z
858
+ .record(
859
+ z.string(),
860
+ z
861
+ .object({
862
+ taskId: z.string().min(1),
863
+ source: botGroupInputSourceSchema,
864
+ admission: z.enum(["pending", "accepted", "rejected"]).optional(),
865
+ progress: botGroupInputProgressSchema.optional(),
866
+ })
867
+ .strict(),
868
+ )
869
+ .optional(),
870
+ })
871
+ .strict()
872
+ .optional(),
495
873
  workspacePath: z.string().min(1),
496
874
  workspaceIdentity: z.string().min(1).optional(),
497
875
  workspaceId: z.string().min(1).optional(),
876
+ projectId: z.string().min(1).nullable().optional(),
877
+ hostId: z.string().min(1).optional(),
878
+ additionalDirectories: z.array(z.string().min(1)).max(256).optional(),
498
879
  mode: z.enum(["draft", "task"]),
499
880
  activeTaskId: z.string().min(1).nullable(),
500
881
  draftOptions: botDraftOptionsSchema.optional(),
@@ -514,6 +895,8 @@ export const botsStateFileSchema = z
514
895
  telegramOffset: z.number().optional(),
515
896
  weixinGetUpdatesBuf: z.string().optional(),
516
897
  weixinActivatedAt: z.number().optional(),
898
+ privateBindingId: z.string().min(1).optional(),
899
+ privateRecipientId: z.string().min(1).optional(),
517
900
  updatedAt: z.number(),
518
901
  }),
519
902
  ),
@@ -578,7 +578,9 @@ export const browserCommandSchema = z.discriminatedUnion("method", [
578
578
  })
579
579
  .strict(),
580
580
  z.object({ method: z.literal("turnEnded"), turnId: z.string().min(1).optional() }).strict(),
581
- z.object({ method: z.literal("closeSession") }).strict(),
581
+ // closeTabs:连同该 session 名下的 tab 一起关(含已释放回该 session 的)。只给永不回来认领的
582
+ // session 用——dwf 子代理(docs/browser-use/2026-07-14-browser-tab-conversation-isolation-spec.md §2.3)。
583
+ z.object({ method: z.literal("closeSession"), closeTabs: z.boolean().optional() }).strict(),
582
584
  z.object({ method: z.literal("cancelRequest"), requestId: z.string().min(1) }).strict(),
583
585
  // close:关闭指定受控 tab(tabId 缺省=当前 tab)。manager 层处理:detach + 通知 renderer 卸载 webview。
584
586
  z.object({ method: z.literal("close"), tabId: z.string().optional() }).strict(),
@@ -0,0 +1,131 @@
1
+ import { zcodeProtocolTraceSchema } from "./zcode-protocol/trace.js";
2
+ import { z } from "zod";
3
+
4
+ export const channelMentionSchema = z
5
+ .object({
6
+ type: z.literal("channelMention"),
7
+ refId: z.string().min(1).max(200),
8
+ name: z.string().min(1).max(200),
9
+ channel: z.enum(["feishu", "lark"]),
10
+ targetId: z
11
+ .string()
12
+ .max(128)
13
+ .regex(/^ou_[a-zA-Z0-9_-]+$/u),
14
+ idType: z.literal("open_id"),
15
+ entityType: z.enum(["user", "bot", "unknown"]),
16
+ })
17
+ .strict();
18
+ export const channelContentPartSchema = z.union([
19
+ z.object({ type: z.literal("text"), text: z.string().max(100_000) }).strict(),
20
+ channelMentionSchema,
21
+ ]);
22
+ export const channelContentPartsSchema = z.array(channelContentPartSchema).max(200);
23
+ export type ChannelContentPart = z.infer<typeof channelContentPartSchema>;
24
+ export const channelReplyPartsSchema = z
25
+ .array(
26
+ z.union([
27
+ z.object({ type: z.literal("text"), text: z.string().max(2000) }).strict(),
28
+ z.object({ type: z.literal("mention"), refId: z.string().min(1).max(200) }).strict(),
29
+ z
30
+ .object({
31
+ type: z.literal("mentionName"),
32
+ name: z.string().trim().min(1).max(200),
33
+ candidateRef: z.string().min(1).max(200).optional(),
34
+ })
35
+ .strict(),
36
+ ]),
37
+ )
38
+ .min(1)
39
+ .max(50);
40
+ export const channelReplyRequestSchema = z
41
+ .object({
42
+ taskId: z.string().min(1),
43
+ inputId: z.string().min(1),
44
+ authorizationId: z.string().min(1).optional(),
45
+ toolCallId: z.string().min(1),
46
+ parts: channelReplyPartsSchema,
47
+ })
48
+ .strict();
49
+ const channelDeliveryResultSchema = z
50
+ .object({
51
+ status: z.enum(["sent", "failed", "unknown", "invalidated"]),
52
+ deliveryId: z.string(),
53
+ providerMessageId: z.string().optional(),
54
+ error: z.string().optional(),
55
+ })
56
+ .strict();
57
+ export const channelMentionClarificationSchema = z
58
+ .object({
59
+ status: z.literal("needs_clarification"),
60
+ unresolved: z
61
+ .array(
62
+ z
63
+ .object({
64
+ name: z.string().max(200),
65
+ reason: z.enum(["ambiguous", "not_found", "unavailable", "selection_expired"]),
66
+ candidates: z
67
+ .array(
68
+ z
69
+ .object({
70
+ ref: z.string().max(200),
71
+ name: z.string().max(200),
72
+ label: z.string().max(250),
73
+ kind: z.enum(["user", "bot", "unknown"]),
74
+ })
75
+ .strict(),
76
+ )
77
+ .max(10),
78
+ truncated: z.boolean(),
79
+ })
80
+ .strict(),
81
+ )
82
+ .min(1)
83
+ .max(50),
84
+ })
85
+ .strict();
86
+ export const channelReplyResultSchema = z.union([
87
+ channelDeliveryResultSchema,
88
+ channelMentionClarificationSchema,
89
+ ]);
90
+ export type ChannelReplyRequest = z.infer<typeof channelReplyRequestSchema>;
91
+ export type ChannelReplyResult = z.infer<typeof channelReplyResultSchema>;
92
+ export function channelContentText(parts: readonly ChannelContentPart[]): string {
93
+ return parts.map((part) => (part.type === "text" ? part.text : `@${part.name}`)).join("");
94
+ }
95
+ /** 只从 Host 已验证的会话输入解析 ref;模型不得直接提供平台 ID。 */
96
+ export function resolveChannelReplyParts(
97
+ parts: z.infer<typeof channelReplyPartsSchema>,
98
+ source: readonly ChannelContentPart[],
99
+ ): ChannelContentPart[] {
100
+ const targets = new Map<string, z.infer<typeof channelMentionSchema>>();
101
+ for (const part of source) {
102
+ if (part.type !== "channelMention") continue;
103
+ const target = channelMentionSchema.parse(part);
104
+ const previous = targets.get(target.refId);
105
+ if (previous && JSON.stringify(previous) !== JSON.stringify(target))
106
+ throw new Error("Conflicting channel mention reference");
107
+ targets.set(target.refId, target);
108
+ }
109
+ channelReplyPartsSchema.parse(parts);
110
+ const resolved = parts.map((part) => {
111
+ if (part.type === "text") return part;
112
+ if (part.type === "mentionName")
113
+ throw new Error("Channel mention name must be resolved by Host");
114
+ const target = targets.get(part.refId);
115
+ if (!target) throw new Error("Unknown channel mention reference");
116
+ return target;
117
+ });
118
+ if (!channelContentText(resolved).trim() || channelContentText(resolved).length > 2000)
119
+ throw new Error("Channel reply must contain 1–2000 characters");
120
+ return resolved;
121
+ }
122
+
123
+ export const channelReplyHostRequestSchema = channelReplyRequestSchema
124
+ .extend({
125
+ trace: zcodeProtocolTraceSchema.optional(),
126
+ workspacePath: z.string().min(1),
127
+ workspaceIdentity: z.string().optional(),
128
+ remoteSessionId: z.string().optional(),
129
+ })
130
+ .strict();
131
+ export type ChannelReplyHostRequest = z.infer<typeof channelReplyHostRequestSchema>;
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ export const CONVERSATION_SELECTION_MAX_TEXT_LENGTH = 8_000;
3
+ export const CONVERSATION_SELECTION_MAX_COUNT = 8;
4
+ export const CONVERSATION_SELECTION_MAX_TOTAL_LENGTH = 16_000;
5
+
6
+ export const conversationQuoteSchema = z.object({
7
+ text: z.string().max(CONVERSATION_SELECTION_MAX_TEXT_LENGTH),
8
+ path: z.string().optional(),
9
+ senderName: z.string().optional(),
10
+ senderId: z.string().optional(),
11
+ messageId: z.string().optional(),
12
+ sentAt: z.string().datetime({ offset: true }).optional(),
13
+ });
14
+ export const conversationQuotesSchema = z
15
+ .array(conversationQuoteSchema)
16
+ .max(CONVERSATION_SELECTION_MAX_COUNT)
17
+ .refine(
18
+ (quotes) =>
19
+ quotes.reduce((sum, quote) => sum + quote.text.length, 0) <=
20
+ CONVERSATION_SELECTION_MAX_TOTAL_LENGTH,
21
+ );
22
+ export type ConversationSelectionText = z.infer<typeof conversationQuoteSchema>;
23
+
24
+ export function buildPromptWithConversationSelections(
25
+ visibleContent: string,
26
+ references: readonly ConversationSelectionText[],
27
+ ): string {
28
+ if (references.length === 0) return visibleContent;
29
+ // 文件选段曾只发正文,导致模型与历史丢失文件来源;只保留路径,不发送内部身份字段。
30
+ const block = [
31
+ "# userselect:",
32
+ "```userselect",
33
+ JSON.stringify(references.map(({ text, path }) => (path?.trim() ? { path, text } : { text }))),
34
+ "```",
35
+ ].join("\n");
36
+ return visibleContent ? `${visibleContent}\n\n${block}` : block;
37
+ }