@xmanrui/dsh-im 0.18.0 → 0.19.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/lib/client.js CHANGED
@@ -258,6 +258,24 @@ var EN = Object.freeze({
258
258
  "WhatsApp\u8D26\u53F7": "WhatsApp account",
259
259
  "\u5FAE\u4FE1\u8BBE\u7F6E": "WeChat settings",
260
260
  "\u98DE\u4E66\u673A\u5668\u4EBA\u8BBE\u7F6E": "Feishu bot settings",
261
+ "\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F": "Group response mode",
262
+ "\u4EC5\u5728 @\u673A\u5668\u4EBA\u65F6\u54CD\u5E94\uFF08\u63A8\u8350\uFF09": "Only respond when @mentioned (recommended)",
263
+ "\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F": "Respond to all group messages",
264
+ "\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\uFF08\u9700\u98DE\u4E66\u654F\u611F\u6743\u9650\uFF09": "Respond to all group messages (requires a sensitive Feishu scope)",
265
+ "\u91CD\u65B0\u6388\u6743": "Reauthorize",
266
+ "\u53BB\u6388\u6743": "Authorize",
267
+ "\u91CD\u65B0\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650": "Reauthorize group-message permission",
268
+ "\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650": "Authorize group-message permission",
269
+ "\u6B63\u5728\u51C6\u5907\u6388\u6743\u2026": "Preparing authorization\u2026",
270
+ "\u6B63\u5728\u51C6\u5907\u2026": "Preparing\u2026",
271
+ "\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u5F00\u901A\uFF0C\u518D\u6B21\u5207\u6362\u65E0\u9700\u6388\u6743\u3002": "Direct messages always work; group chats require an explicit @mention of this bot. The group-message permission is already granted, so switching again needs no authorization.",
272
+ "\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u9009\u62E9\u5168\u90E8\u6D88\u606F\u540E\u4F1A\u6253\u5F00\u98DE\u4E66\u5B98\u65B9\u6388\u6743\u6D41\u7A0B\u3002": "Direct messages always work; group chats require an explicit @mention of this bot. Selecting all messages opens the official Feishu authorization flow.",
273
+ "\u5DF2\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002": "The \u201CRead all messages in associated group chat\u201D scope (im:message.group_msg) is granted; the bot processes every visible group message.",
274
+ "\u5C1A\u672A\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF0C\u8BF7\u5B8C\u6210\u98DE\u4E66\u6388\u6743\u3002": "The \u201CRead all messages in associated group chat\u201D scope has not been confirmed. Complete Feishu authorization.",
275
+ "\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002": "Direct messages always work; group chats require an explicit @mention of this bot.",
276
+ "\u9700\u5728\u98DE\u4E66\u4E3A\u8BE5\u673A\u5668\u4EBA\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u5F00\u901A\u540E\uFF0C\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002": "Grant this bot the \u201CRead all messages in associated group chat\u201D Feishu scope (im:message.group_msg); once granted, it will process every visible group message.",
277
+ "\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not update the group response mode. Try again.",
278
+ "\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not authorize group-message permission. Try again.",
261
279
  "\u9489\u9489\u8BBE\u7F6E": "DingTalk settings",
262
280
  "\u4F01\u4E1A\u5FAE\u4FE1\u8BBE\u7F6E": "WeCom settings",
263
281
  "\u626B\u7801\u63A5\u5165\u673A\u5668\u4EBA": "Scan QR code",
@@ -380,6 +398,7 @@ var EN = Object.freeze({
380
398
  "\u751F\u6210 QQ \u4E8C\u7EF4\u7801": "Generate QQ QR code",
381
399
  "\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026": "Generating QR code\u2026",
382
400
  "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801": "Preparing authorization QR code",
401
+ "\u6B63\u5728\u51C6\u5907\u6743\u9650\u6388\u6743\u4E8C\u7EF4\u7801": "Preparing permission authorization QR code",
383
402
  "\u6B63\u5728\u51C6\u5907\u5FAE\u4FE1\u4E8C\u7EF4\u7801": "Preparing WeChat QR code",
384
403
  "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA": "Adding a new bot",
385
404
  "\u6B63\u5728\u7533\u8BF7\u9489\u9489\u6388\u6743\u4E8C\u7EF4\u7801\u2026": "Requesting DingTalk authorization QR code\u2026",
@@ -397,6 +416,16 @@ var EN = Object.freeze({
397
416
  "\u5728\u98DE\u4E66\u4E2D\u6253\u5F00": "Open in Feishu",
398
417
  "\u53D6\u6D88\u6DFB\u52A0": "Cancel",
399
418
  "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE": "Scan with Feishu to repair card buttons",
419
+ "\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650": "Confirm group-message permission with Feishu",
420
+ "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002": "Scanning updates the existing Feishu app with only the \u201CRead all messages in associated group chat\u201D scope. It does not create a new app. After confirmation, \u201CRespond to all group messages\u201D is enabled automatically; other bots are unaffected.",
421
+ "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650": "Review the existing app and confirm the \u201CRead all messages in associated group chat\u201D permission",
422
+ "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u751F\u6548\u5E76\u81EA\u52A8\u5207\u6362\u54CD\u5E94\u65B9\u5F0F": "Keep this page open while the permission takes effect and the response mode switches automatically",
423
+ "\u53D6\u6D88\u6388\u6743": "Cancel authorization",
424
+ "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F": "Confirmed. Enabling all-message mode",
425
+ "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u8BBE\u7F6E\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "The permission update was submitted. Saving the setting and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
426
+ "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "The permission update was submitted. Enabling all-message mode and reconnecting this bot. This stage cannot be cancelled; other bots will not be interrupted.",
427
+ "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a group-message permission QR code for the existing Feishu app\u2026",
428
+ "\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210": "Group-message permission was not granted",
400
429
  "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002": "Scanning updates the existing Feishu app with only the card-button callback. It does not create a new app. This bot reconnects briefly after confirmation; other bots are not affected.",
401
430
  "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03": "Review the existing app name and confirm that only the card callback is added",
402
431
  "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210": "Keep this page open until card-button repair finishes",
@@ -409,14 +438,25 @@ var EN = Object.freeze({
409
438
  "\u4FEE\u590D\u5361\u7247\u6309\u94AE": "Repair card buttons",
410
439
  "\u7B49\u5F85\u626B\u7801\u2026": "Waiting for scan\u2026",
411
440
  "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801": "Feishu returned a repair QR code for a different bot",
441
+ "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801": "Feishu returned a group-message permission QR code for a different bot",
412
442
  "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4FEE\u590D\u4FE1\u606F\u7F3A\u5C11 botId": "Feishu repair status is missing the bot ID",
443
+ "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u5E94\u7528\u66F4\u65B0\u4FE1\u606F\u7F3A\u5C11 botId": "Feishu app-update status is missing the bot ID",
413
444
  "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6": "Feishu returned registration progress for a different operation",
414
445
  "\u6B64\u673A\u5668\u4EBA": "this bot",
446
+ "\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801": "One-time QR code for granting group-message permission to ${botName}",
447
+ "\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650": "Granting group-message permission to \u201C${botName}\u201D",
415
448
  '${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002': 'Repair QR code generated for ${botName ?? "bot"}. Scan it with Feishu.',
449
+ '${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002': 'Group-message permission QR code generated for ${botName ?? "bot"}. Confirm it with Feishu.',
450
+ "${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002": "${targetBotName} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.",
451
+ "${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002": "${targetBot.bot.name} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.",
416
452
  "${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002": "${targetBot.bot.name} is connected and ready to chat in Feishu.",
417
453
  "\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002": "Card-button repair was cancelled.",
454
+ "\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002": "Group-message permission authorization was cancelled.",
418
455
  "\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001": "The card callback was updated, but the bot connection could not be confirmed yet",
456
+ "\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001": "The group-message permission was updated, but the bot connection could not be confirmed yet",
419
457
  "\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25": "Could not repair the Feishu card buttons",
458
+ "\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25": "Could not grant the Feishu group-message permission",
459
+ "\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u98DE\u4E66\u6388\u6743\u64CD\u4F5C\uFF0C\u518D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u3002": "Finish the current Feishu authorization before granting group-message permission.",
420
460
  "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA": "Confirmed. Connecting the new bot",
421
461
  "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002": "Saving credentials and checking the new bot connection. Existing bots will not be interrupted.",
422
462
  "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002": "Requesting a one-time authorization QR code from Feishu\u2026",
@@ -709,16 +749,26 @@ function translateDynamic(text5) {
709
749
  if (match) return `Remove \u201C${match[1]}\u201D from DeepSeek Harness?`;
710
750
  match = /^从 DeepSeek Harness 移除(.+)$/.exec(text5);
711
751
  if (match) return `Remove ${match[1]} from DeepSeek Harness`;
752
+ match = /^(.+)的飞书授权流程$/.exec(text5);
753
+ if (match) return `Feishu authorization flow for ${match[1]}`;
712
754
  match = /^用于修复(.+)卡片按钮的一次性授权二维码$/.exec(text5);
713
755
  if (match) return `One-time QR code for repairing card buttons for ${match[1]}`;
756
+ match = /^用于为(.+)开通群消息权限的一次性授权二维码$/.exec(text5);
757
+ if (match) return `One-time QR code for granting group-message permission to ${match[1]}`;
714
758
  match = /^正在修复「(.+)」$/.exec(text5);
715
759
  if (match) return `Repairing \u201C${match[1]}\u201D`;
760
+ match = /^正在为「(.+)」开通群消息权限$/.exec(text5);
761
+ if (match) return `Granting group-message permission to \u201C${match[1]}\u201D`;
716
762
  match = /^修复(.+)的卡片按钮$/.exec(text5);
717
763
  if (match) return `Repair card buttons for ${match[1]}`;
718
764
  match = /^(.+)的修复二维码已生成,请使用飞书扫码。$/.exec(text5);
719
765
  if (match) return `Repair QR code generated for ${match[1]}. Scan it with Feishu.`;
766
+ match = /^(.+)的群消息权限二维码已生成,请使用飞书确认。$/.exec(text5);
767
+ if (match) return `Group-message permission QR code generated for ${match[1]}. Confirm it with Feishu.`;
720
768
  match = /^(.+)的卡片按钮已修复。$/.exec(text5);
721
769
  if (match) return `Card buttons repaired for ${match[1]}.`;
770
+ match = /^(.+)已开通群消息权限,并启用“响应所有群消息”。$/.exec(text5);
771
+ if (match) return `${match[1]} now has group-message permission and \u201CRespond to all group messages\u201D is enabled.`;
722
772
  match = /^(检查连接|重试连接)(.+)$/.exec(text5);
723
773
  if (match) return `${localizeText(match[1])} ${match[2]}`;
724
774
  match = /^移除(.+)$/.exec(text5);
@@ -3278,6 +3328,7 @@ var FEISHU_ENDPOINTS = Object.freeze({
3278
3328
  status: "connection.status",
3279
3329
  beginProvisioning: "provision.begin",
3280
3330
  beginCallbackRepair: "bot.callback-repair.begin",
3331
+ beginGroupMessagePermission: "bot.group-message-permission.begin",
3281
3332
  pollProvisioning: "provision.poll",
3282
3333
  cancelProvisioning: "provision.cancel",
3283
3334
  bindCredentials: "bot.bind-credentials",
@@ -3286,13 +3337,15 @@ var FEISHU_ENDPOINTS = Object.freeze({
3286
3337
  deleteBot: "bot.delete",
3287
3338
  setWorkspace: "bot.workspace.set",
3288
3339
  setAgentPreset: "bot.preset.set",
3340
+ setGroupResponseMode: "bot.group-response-mode.set",
3289
3341
  // Kept for rolling upgrades. The multi-bot UI never calls these endpoints.
3290
3342
  testConnection: "connection.test",
3291
3343
  disconnect: "connection.disconnect"
3292
3344
  });
3293
3345
  var FEISHU_REGISTRATION_OPERATIONS = Object.freeze({
3294
3346
  PROVISION: "provision",
3295
- CALLBACK_REPAIR: "callback_repair"
3347
+ CALLBACK_REPAIR: "callback_repair",
3348
+ GROUP_MESSAGE_PERMISSION: "group_message_permission"
3296
3349
  });
3297
3350
  var CONNECTION_STATES = /* @__PURE__ */ new Set([
3298
3351
  "disconnected",
@@ -3325,11 +3378,23 @@ function optionalTimestamp(value) {
3325
3378
  }
3326
3379
  return void 0;
3327
3380
  }
3381
+ function normalizeGroupResponseMode(value) {
3382
+ return value === "all" ? "all" : "mention";
3383
+ }
3328
3384
  function clamp2(value, min, max, fallback) {
3329
3385
  return typeof value === "number" && Number.isFinite(value) ? Math.min(max, Math.max(min, value)) : fallback;
3330
3386
  }
3331
3387
  function normalizeRegistrationOperation(value) {
3332
- return value === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR ? FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR : FEISHU_REGISTRATION_OPERATIONS.PROVISION;
3388
+ if (value === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR) {
3389
+ return FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR;
3390
+ }
3391
+ if (value === FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION) {
3392
+ return FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
3393
+ }
3394
+ return FEISHU_REGISTRATION_OPERATIONS.PROVISION;
3395
+ }
3396
+ function isTargetedAppUpdate(operation) {
3397
+ return operation === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR || operation === FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
3333
3398
  }
3334
3399
  function unwrapRpcResult3(result) {
3335
3400
  if (!isRecord3(result) || typeof result.ok !== "boolean") {
@@ -3357,8 +3422,8 @@ function normalizeProvisioning2(value, now = Date.now()) {
3357
3422
  const expireIn = clamp2(source.expireIn, 1, 60 * 60, 5 * 60);
3358
3423
  const operation = normalizeRegistrationOperation(source.operation);
3359
3424
  const botId = optionalString2(source.botId);
3360
- if (operation === FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR && !botId) {
3361
- throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u4FEE\u590D\u4FE1\u606F\u7F3A\u5C11 botId");
3425
+ if (isTargetedAppUpdate(operation) && !botId) {
3426
+ throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u7684\u5E94\u7528\u66F4\u65B0\u4FE1\u606F\u7F3A\u5C11 botId");
3362
3427
  }
3363
3428
  return {
3364
3429
  attemptId,
@@ -3420,6 +3485,8 @@ function normalizeBotConnection(value, fallbackBotId) {
3420
3485
  configured: value.configured !== false,
3421
3486
  workspace: optionalString2(value.workspace)?.slice(0, 4096) ?? "",
3422
3487
  agentPreset: normalizeAgentPresetId(value.agentPreset),
3488
+ groupResponseMode: normalizeGroupResponseMode(value.groupResponseMode),
3489
+ groupMessagePermissionGranted: value.groupMessagePermissionGranted === true,
3423
3490
  bot: normalizeBot2(value.bot),
3424
3491
  health: normalizeHealth(value.health, connected),
3425
3492
  error: normalizeError2(value.error)
@@ -4000,6 +4067,50 @@ var CSS3 = String.raw`
4000
4067
  .bxf-metric dt { color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 17px; }
4001
4068
  .bxf-metric dd { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-primary, #1f2329); font-size: 12px; line-height: 18px; font-weight: 550; margin: 3px 0 0; }
4002
4069
 
4070
+ .bxf-responseMode { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr) max-content; align-items: center; column-gap: 10px; row-gap: 5px; margin-top: 6px; padding: 8px 10px; border: 1px solid var(--dsw-alias-border-l1, #eef0f3); border-radius: 9px; background: var(--dsw-alias-bg-module-platform, #f7f8fa); }
4071
+ .bxf-responseModeHeader { display: contents; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: normal; }
4072
+ .bxf-responseModeHeader > span:first-child { grid-column: 1; grid-row: 1; white-space: nowrap; }
4073
+ .bxf-responseModeStatus { grid-column: 2; grid-row: 1; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 12px; white-space: nowrap; }
4074
+ .bxf-responseModeSelect { min-width: 0; width: 100%; grid-column: 1 / -1; grid-row: 2; height: 32px; padding: 0 30px 0 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background-color: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 12px; cursor: pointer; transition: border-color .16s ease, box-shadow .16s ease, background-color .16s ease; }
4075
+ .bxf-responseModeSelect:hover:not(:disabled) { border-color: color-mix(in srgb, var(--bxf-accent) 45%, var(--dsw-alias-border-l2, #dfe1e5)); }
4076
+ .bxf-responseModeSelect:focus-visible { outline: none; border-color: var(--bxf-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--bxf-accent) 16%, transparent); }
4077
+ .bxf-responseModeSelect:disabled { cursor: not-allowed; opacity: .55; }
4078
+ .bxf-responseModeHelp { grid-column: 1 / -1; grid-row: 3; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; line-height: 1.45; }
4079
+ .bxf-responseModePermissionAction { grid-column: 1 / -1; grid-row: 4; display: flex; justify-content: flex-start; margin-top: 2px; }
4080
+ .bxf-responseModePermissionButton { min-height: 28px; padding: 3px 9px; color: var(--bxf-accent); border-color: color-mix(in srgb, var(--bxf-accent) 30%, var(--dsw-alias-border-l2, #dfe1e5)); background: var(--dsw-alias-bg-layer-1, #fff); }
4081
+ .bxf-responseModePermissionButton:hover:not(:disabled) { background: color-mix(in srgb, var(--bxf-accent) 7%, transparent); }
4082
+ .bxf-responseModeError { grid-column: 1 / -1; grid-row: 5; color: var(--bxf-error); font-size: 12px; line-height: 1.4; margin: 0; }
4083
+
4084
+ .bxf-botProvision {
4085
+ position: relative;
4086
+ margin-top: 14px;
4087
+ scroll-margin-block: 20px;
4088
+ animation: bxf-revealProvision .2s var(--ds-ease-out, ease-out) both;
4089
+ }
4090
+ .bxf-botProvision:focus { outline: none; }
4091
+ .bxf-botProvision:focus-visible {
4092
+ outline: 2px solid color-mix(in srgb, var(--bxf-accent) 75%, transparent);
4093
+ outline-offset: 3px;
4094
+ border-radius: 12px;
4095
+ }
4096
+ .bxf-botProvision > .bxf-provisionCard {
4097
+ border-radius: 11px;
4098
+ box-shadow: none;
4099
+ background: color-mix(in srgb, var(--bxf-accent) 2.5%, var(--dsw-alias-bg-layer-3, #fff));
4100
+ }
4101
+ .bxf-botProvision .bxf-cardBody { padding: 18px; }
4102
+ .bxf-botProvision .bxf-qrLayout {
4103
+ grid-template-columns: 184px minmax(0, 1fr);
4104
+ align-items: start;
4105
+ gap: 24px;
4106
+ }
4107
+ .bxf-botProvision .bxf-qrFrame { width: 176px; height: 176px; padding: 10px; border-radius: 11px; }
4108
+ .bxf-botProvision .bxf-countdown { width: 176px; }
4109
+ .bxf-botProvision .bxf-qrCopy h3 { font-size: 18px; line-height: 26px; }
4110
+ .bxf-botProvision .bxf-steps { gap: 8px; margin-top: 14px; }
4111
+ .bxf-botProvision .bxf-actions { margin-top: 16px; }
4112
+ .bxf-botProvision .bxf-inlineError { min-height: 160px; padding: 22px; }
4113
+
4003
4114
  .bxf-connectedFooter { display: flex; align-items: center; justify-content: space-between; gap: 15px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--dsw-alias-border-l1, #eef0f3); }
4004
4115
  .bxf-healthSummary { min-width: 0; color: var(--dsw-alias-label-secondary, #646a73); font-size: 12px; line-height: 18px; }
4005
4116
  .bxf-healthSummary[data-error="true"] { color: var(--bxf-error); }
@@ -4052,6 +4163,7 @@ var CSS3 = String.raw`
4052
4163
  @keyframes bxf-rotate { to { transform: rotate(360deg); } }
4053
4164
  @keyframes bxf-pulse { 0%, 100% { transform: scale(.9); opacity: .45; } 50% { transform: scale(1.08); opacity: 1; } }
4054
4165
  @keyframes bxf-shimmer { to { background-position: -220% 0; } }
4166
+ @keyframes bxf-revealProvision { from { opacity: 0; transform: translateY(-5px); } }
4055
4167
 
4056
4168
  @container (max-width: 620px) {
4057
4169
  .bxf-headingTools { gap: 6px; }
@@ -4063,6 +4175,7 @@ var CSS3 = String.raw`
4063
4175
  .bxf-intro { grid-template-columns: minmax(0, 1fr); }
4064
4176
  .bxf-markStage { display: none; }
4065
4177
  .bxf-qrLayout { grid-template-columns: minmax(0, 1fr); justify-items: center; }
4178
+ .bxf-botProvision .bxf-qrLayout { grid-template-columns: minmax(0, 1fr); }
4066
4179
  .bxf-qrCopy { width: 100%; }
4067
4180
  .bxf-statusGrid { grid-template-columns: minmax(0, 1fr); }
4068
4181
  .bxf-connectedTop { align-items: flex-start; flex-direction: column; }
@@ -4099,9 +4212,16 @@ function installFeishuStyles() {
4099
4212
 
4100
4213
  // plugin-src/client/channels/feishu/index.js
4101
4214
  var CALLBACK_REPAIR_OPERATION = FEISHU_REGISTRATION_OPERATIONS.CALLBACK_REPAIR;
4215
+ var GROUP_MESSAGE_PERMISSION_OPERATION = FEISHU_REGISTRATION_OPERATIONS.GROUP_MESSAGE_PERMISSION;
4102
4216
  function isCallbackRepair(value) {
4103
4217
  return value?.operation === CALLBACK_REPAIR_OPERATION;
4104
4218
  }
4219
+ function isGroupMessagePermission(value) {
4220
+ return value?.operation === GROUP_MESSAGE_PERMISSION_OPERATION;
4221
+ }
4222
+ function isTargetedAppUpdate2(value) {
4223
+ return isCallbackRepair(value) || isGroupMessagePermission(value);
4224
+ }
4105
4225
  function SvgIcon({ children, size = 18, className, viewBox = "0 0 24 24" }) {
4106
4226
  return h2("svg", {
4107
4227
  width: size,
@@ -4283,6 +4403,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
4283
4403
  const expired = provision.expired === true || remaining === 0;
4284
4404
  const progress = Math.min(1, remaining / Math.max(1, provision.durationMs ?? remaining));
4285
4405
  const repairing = isCallbackRepair(provision);
4406
+ const grantingGroupMessages = isGroupMessagePermission(provision);
4286
4407
  const botName = provision.botName ?? "\u6B64\u673A\u5668\u4EBA";
4287
4408
  React11.useEffect(() => setImageFailed(false), [qrSource]);
4288
4409
  return h2(
@@ -4299,7 +4420,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
4299
4420
  { className: "bxf-qrFrame dim-qrFrame" },
4300
4421
  qrSource && !imageFailed ? h2("img", {
4301
4422
  src: qrSource,
4302
- alt: repairing ? `\u7528\u4E8E\u4FEE\u590D${botName}\u5361\u7247\u6309\u94AE\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : "\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801",
4423
+ alt: repairing ? `\u7528\u4E8E\u4FEE\u590D${botName}\u5361\u7247\u6309\u94AE\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : grantingGroupMessages ? `\u7528\u4E8E\u4E3A${botName}\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801` : "\u7528\u4E8E\u65B0\u589E DeepSeek Harness \u98DE\u4E66\u673A\u5668\u4EBA\u7684\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801",
4303
4424
  onError: () => setImageFailed(true)
4304
4425
  }) : h2(
4305
4426
  "div",
@@ -4338,16 +4459,16 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
4338
4459
  "div",
4339
4460
  { className: "bxf-stateLabel dim-stateLabel" },
4340
4461
  h2("span", { className: "bxf-dot dim-stateDot", "data-tone": "warning" }),
4341
- h2("span", null, repairing ? `\u6B63\u5728\u4FEE\u590D\u300C${botName}\u300D` : "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
4462
+ h2("span", null, repairing ? `\u6B63\u5728\u4FEE\u590D\u300C${botName}\u300D` : grantingGroupMessages ? `\u6B63\u5728\u4E3A\u300C${botName}\u300D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650` : "\u6B63\u5728\u6DFB\u52A0\u65B0\u673A\u5668\u4EBA")
4342
4463
  ),
4343
- h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : repairing ? "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
4344
- h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002"),
4464
+ h2("h3", null, expired ? "\u5237\u65B0\u4E8C\u7EF4\u7801\u540E\u7EE7\u7EED" : repairing ? "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u4FEE\u590D\u5361\u7247\u6309\u94AE" : grantingGroupMessages ? "\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u7FA4\u6D88\u606F\u6743\u9650" : "\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u521B\u5EFA\u673A\u5668\u4EBA"),
4465
+ h2("p", null, repairing ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u8865\u5145\u5361\u7247\u6309\u94AE\u56DE\u8C03\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u6B64\u673A\u5668\u4EBA\u4F1A\u77ED\u6682\u91CD\u8FDE\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : grantingGroupMessages ? "\u626B\u7801\u4F1A\u66F4\u65B0\u73B0\u6709\u98DE\u4E66\u5E94\u7528\uFF0C\u53EA\u589E\u91CF\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF1B\u4E0D\u4F1A\u521B\u5EFA\u65B0\u5E94\u7528\u3002\u786E\u8BA4\u540E\u4F1A\u81EA\u52A8\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u626B\u7801\u53EA\u4F1A\u65B0\u589E\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5DF2\u63A5\u5165\u7684\u673A\u5668\u4EBA\u4F1A\u7EE7\u7EED\u6B63\u5E38\u6536\u53D1\u6D88\u606F\u3002"),
4345
4466
  h2(
4346
4467
  "ol",
4347
4468
  { className: "bxf-steps dim-steps" },
4348
4469
  h2("li", null, "\u6253\u5F00\u98DE\u4E66\u79FB\u52A8\u7AEF\uFF0C\u4F7F\u7528\u626B\u4E00\u626B\u8BFB\u53D6\u4E8C\u7EF4\u7801"),
4349
- h2("li", null, repairing ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03" : "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
4350
- h2("li", null, repairing ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210" : "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA")
4470
+ h2("li", null, repairing ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\u540D\u79F0\uFF0C\u5E76\u786E\u8BA4\u53EA\u65B0\u589E\u5361\u7247\u56DE\u8C03" : grantingGroupMessages ? "\u6838\u5BF9\u73B0\u6709\u5E94\u7528\uFF0C\u5E76\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650" : "\u6838\u5BF9\u5E94\u7528\u540D\u79F0\u4E0E\u6743\u9650\u8303\u56F4\uFF0C\u5E76\u786E\u8BA4\u521B\u5EFA"),
4471
+ h2("li", null, repairing ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5B8C\u6210" : grantingGroupMessages ? "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u6743\u9650\u751F\u6548\u5E76\u81EA\u52A8\u5207\u6362\u54CD\u5E94\u65B9\u5F0F" : "\u4FDD\u6301\u672C\u9875\u6253\u5F00\uFF0C\u7B49\u5F85\u65B0\u673A\u5668\u4EBA\u7684\u957F\u8FDE\u63A5\u5C31\u7EEA")
4351
4472
  ),
4352
4473
  h2(
4353
4474
  "div",
@@ -4364,7 +4485,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
4364
4485
  rel: "noopener noreferrer"
4365
4486
  }, h2("span", null, "\u5728\u98DE\u4E66\u4E2D\u6253\u5F00")) : null,
4366
4487
  !expired ? h2(Button5, { onClick: onRefresh, disabled: busy }, "\u6362\u4E00\u4E2A\u4E8C\u7EF4\u7801") : null,
4367
- h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : "\u53D6\u6D88\u6DFB\u52A0")
4488
+ h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : grantingGroupMessages ? "\u53D6\u6D88\u6388\u6743" : "\u53D6\u6D88\u6DFB\u52A0")
4368
4489
  )
4369
4490
  )
4370
4491
  )
@@ -4373,6 +4494,7 @@ function QrPane({ provision, now, onRefresh, onCancel, busy }) {
4373
4494
  function ProvisionProgress({ phase, provision, onCancel, busy }) {
4374
4495
  const connecting = phase === "connecting";
4375
4496
  const repairing = isCallbackRepair(provision);
4497
+ const grantingGroupMessages = isGroupMessagePermission(provision);
4376
4498
  return h2(
4377
4499
  "div",
4378
4500
  {
@@ -4380,17 +4502,18 @@ function ProvisionProgress({ phase, provision, onCancel, busy }) {
4380
4502
  "aria-busy": "true"
4381
4503
  },
4382
4504
  h2("div", { className: "dim-spinner", "aria-hidden": "true" }),
4383
- h2("h3", null, connecting ? repairing ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D" : "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA" : repairing ? "\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801"),
4384
- h2("p", null, connecting ? repairing ? "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : repairing ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002"),
4505
+ h2("h3", null, connecting ? repairing ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u5B8C\u6210\u5361\u7247\u6309\u94AE\u4FEE\u590D" : grantingGroupMessages ? "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F" : "\u5DF2\u786E\u8BA4\uFF0C\u6B63\u5728\u8FDE\u63A5\u65B0\u673A\u5668\u4EBA" : repairing ? "\u6B63\u5728\u51C6\u5907\u4FEE\u590D\u4E8C\u7EF4\u7801" : grantingGroupMessages ? "\u6B63\u5728\u51C6\u5907\u6743\u9650\u6388\u6743\u4E8C\u7EF4\u7801" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u4E8C\u7EF4\u7801"),
4506
+ h2("p", null, connecting ? repairing ? "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : grantingGroupMessages ? "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u4FDD\u5B58\u8BBE\u7F6E\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u6B63\u5728\u5B89\u5168\u4FDD\u5B58\u51ED\u636E\u5E76\u68C0\u67E5\u65B0\u673A\u5668\u4EBA\u7684\u6D88\u606F\u901A\u9053\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : repairing ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u4E00\u6B21\u6027\u66F4\u65B0\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : grantingGroupMessages ? "\u6B63\u5728\u4E3A\u73B0\u6709\u98DE\u4E66\u5E94\u7528\u7533\u8BF7\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002" : "\u6B63\u5728\u5411\u98DE\u4E66\u7533\u8BF7\u4E00\u6B21\u6027\u6388\u6743\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u5019\u3002"),
4385
4507
  connecting && onCancel ? h2(
4386
4508
  "div",
4387
4509
  { className: "bxf-actions dim-viewActions", style: { justifyContent: "center" } },
4388
- h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : "\u53D6\u6D88\u6DFB\u52A0")
4510
+ h2(Button5, { onClick: onCancel, disabled: busy }, repairing ? "\u53D6\u6D88\u4FEE\u590D" : grantingGroupMessages ? "\u53D6\u6D88\u6388\u6743" : "\u53D6\u6D88\u6DFB\u52A0")
4389
4511
  ) : null
4390
4512
  );
4391
4513
  }
4392
4514
  function ProvisionError2({ error, provision, onRetry, onCancel, busy }) {
4393
4515
  const repairing = isCallbackRepair(provision);
4516
+ const grantingGroupMessages = isGroupMessagePermission(provision);
4394
4517
  return h2(
4395
4518
  "div",
4396
4519
  { className: "bxf-card bxf-provisionCard dim-surfaceCard" },
@@ -4400,7 +4523,7 @@ function ProvisionError2({ error, provision, onRetry, onCancel, busy }) {
4400
4523
  h2(
4401
4524
  "div",
4402
4525
  null,
4403
- h2("h3", null, repairing ? "\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210" : "\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210"),
4526
+ h2("h3", null, repairing ? "\u5361\u7247\u6309\u94AE\u6CA1\u6709\u4FEE\u590D\u5B8C\u6210" : grantingGroupMessages ? "\u7FA4\u6D88\u606F\u6743\u9650\u6CA1\u6709\u5F00\u901A\u5B8C\u6210" : "\u65B0\u673A\u5668\u4EBA\u6CA1\u6709\u6DFB\u52A0\u5B8C\u6210"),
4404
4527
  h2("p", null, error.message),
4405
4528
  error.code ? h2("span", { className: "bxf-errorCode" }, error.code) : null,
4406
4529
  h2(
@@ -4482,10 +4605,101 @@ function RemoveConfirmation2({ bot, busy, onConfirm, onCancel }) {
4482
4605
  )
4483
4606
  );
4484
4607
  }
4608
+ function GroupResponseModeEditor({
4609
+ value,
4610
+ permissionGranted = false,
4611
+ disabled = false,
4612
+ authorizationDisabled = false,
4613
+ onSave,
4614
+ onAuthorize
4615
+ }) {
4616
+ const current = normalizeGroupResponseMode(value);
4617
+ const [saving, setSaving] = React11.useState(false);
4618
+ const [authorizing, setAuthorizing] = React11.useState(false);
4619
+ const [error, setError] = React11.useState(null);
4620
+ const change = async (event) => {
4621
+ const next = normalizeGroupResponseMode(event.target.value);
4622
+ if (next === current || saving || disabled) return;
4623
+ setSaving(true);
4624
+ setError(null);
4625
+ try {
4626
+ await onSave?.(next);
4627
+ } catch (cause) {
4628
+ setError(cause?.message ?? "\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
4629
+ } finally {
4630
+ setSaving(false);
4631
+ }
4632
+ };
4633
+ const authorize = async () => {
4634
+ if (current !== "all" || saving || authorizing || disabled || authorizationDisabled) return;
4635
+ setAuthorizing(true);
4636
+ setError(null);
4637
+ try {
4638
+ await onAuthorize?.();
4639
+ } catch (cause) {
4640
+ setError(cause?.message ?? "\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
4641
+ } finally {
4642
+ setAuthorizing(false);
4643
+ }
4644
+ };
4645
+ return h2(
4646
+ "div",
4647
+ { className: "bxf-responseMode dim-responseMode" },
4648
+ h2(
4649
+ "div",
4650
+ { className: "bxf-responseModeHeader dim-responseModeHeader" },
4651
+ h2("span", null, "\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F"),
4652
+ saving || authorizing ? h2(
4653
+ "span",
4654
+ { className: "bxf-responseModeStatus dim-responseModeStatus" },
4655
+ saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u6B63\u5728\u51C6\u5907\u6388\u6743\u2026"
4656
+ ) : null
4657
+ ),
4658
+ h2(
4659
+ "select",
4660
+ {
4661
+ className: "bxf-responseModeSelect dim-responseModeSelect",
4662
+ value: current,
4663
+ disabled: disabled || saving,
4664
+ "aria-label": "\u7FA4\u804A\u54CD\u5E94\u65B9\u5F0F",
4665
+ onChange: (event) => {
4666
+ void change(event);
4667
+ }
4668
+ },
4669
+ h2("option", { value: "mention" }, "\u4EC5\u5728 @\u673A\u5668\u4EBA\u65F6\u54CD\u5E94\uFF08\u63A8\u8350\uFF09"),
4670
+ h2("option", { value: "all" }, "\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F")
4671
+ ),
4672
+ h2(
4673
+ "small",
4674
+ { className: "bxf-responseModeHelp dim-responseModeHelp" },
4675
+ current === "mention" ? permissionGranted ? "\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u5F00\u901A\uFF0C\u518D\u6B21\u5207\u6362\u65E0\u9700\u6388\u6743\u3002" : "\u79C1\u804A\u59CB\u7EC8\u54CD\u5E94\uFF1B\u7FA4\u804A\u4EC5\u5904\u7406\u660E\u786E @\u5F53\u524D\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3002\u9009\u62E9\u5168\u90E8\u6D88\u606F\u540E\u4F1A\u6253\u5F00\u98DE\u4E66\u5B98\u65B9\u6388\u6743\u6D41\u7A0B\u3002" : permissionGranted ? "\u5DF2\u5F00\u901A\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF08im:message.group_msg\uFF09\uFF1B\u673A\u5668\u4EBA\u4F1A\u5904\u7406\u7FA4\u804A\u4E2D\u7684\u6240\u6709\u53EF\u89C1\u6D88\u606F\u3002" : "\u5C1A\u672A\u786E\u8BA4\u201C\u83B7\u53D6\u7FA4\u7EC4\u4E2D\u6240\u6709\u6D88\u606F\u201D\u6743\u9650\uFF0C\u8BF7\u5B8C\u6210\u98DE\u4E66\u6388\u6743\u3002"
4676
+ ),
4677
+ current === "all" ? h2(
4678
+ "div",
4679
+ { className: "bxf-responseModePermissionAction dim-responseModePermissionAction" },
4680
+ h2(Button5, {
4681
+ className: "bxf-responseModePermissionButton",
4682
+ size: "small",
4683
+ disabled: disabled || authorizationDisabled || saving || authorizing,
4684
+ "aria-busy": authorizing ? "true" : void 0,
4685
+ "aria-label": permissionGranted ? "\u91CD\u65B0\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650" : "\u6388\u6743\u7FA4\u6D88\u606F\u6743\u9650",
4686
+ onClick: () => {
4687
+ void authorize();
4688
+ }
4689
+ }, authorizing ? "\u6B63\u5728\u51C6\u5907\u2026" : permissionGranted ? "\u91CD\u65B0\u6388\u6743" : "\u53BB\u6388\u6743")
4690
+ ) : null,
4691
+ error ? h2("p", {
4692
+ className: "bxf-responseModeError dim-responseModeError",
4693
+ role: "alert"
4694
+ }, error) : null
4695
+ );
4696
+ }
4485
4697
  function BotCard({
4486
4698
  connection,
4487
4699
  busy,
4488
4700
  repairDisabled,
4701
+ provisionContent,
4702
+ provisionRef,
4489
4703
  actionError,
4490
4704
  testNotice,
4491
4705
  removing,
@@ -4493,6 +4707,8 @@ function BotCard({
4493
4707
  onRepairCallback,
4494
4708
  onWorkspaceSave,
4495
4709
  onAgentPresetSave,
4710
+ onGroupResponseModeSave,
4711
+ onGroupMessagePermissionAuthorize,
4496
4712
  onRequestRemove,
4497
4713
  onConfirmRemove,
4498
4714
  onCancelRemove,
@@ -4567,6 +4783,21 @@ function BotCard({
4567
4783
  disabled: Boolean(busy),
4568
4784
  onSave: onAgentPresetSave
4569
4785
  }),
4786
+ h2(GroupResponseModeEditor, {
4787
+ value: connection.groupResponseMode,
4788
+ permissionGranted: connection.groupMessagePermissionGranted,
4789
+ disabled: Boolean(busy),
4790
+ authorizationDisabled: repairDisabled,
4791
+ onSave: onGroupResponseModeSave,
4792
+ onAuthorize: onGroupMessagePermissionAuthorize
4793
+ }),
4794
+ provisionContent ? h2("section", {
4795
+ className: "bxf-botProvision dim-botProvision",
4796
+ "aria-label": `${bot.name}\u7684\u98DE\u4E66\u6388\u6743\u6D41\u7A0B`,
4797
+ "data-provision-for": connection.botId,
4798
+ ref: provisionRef,
4799
+ tabIndex: -1
4800
+ }, provisionContent) : null,
4570
4801
  h2(
4571
4802
  "div",
4572
4803
  { className: "bxf-connectedFooter dim-cardFooter" },
@@ -4632,8 +4863,10 @@ function BotList(props) {
4632
4863
  { key: bot.botId },
4633
4864
  h2(BotCard, {
4634
4865
  connection: bot,
4635
- busy: props.busyByBot[bot.botId] ?? (isCallbackRepair(props.provisioning) && props.provisioning.botId === bot.botId ? "callback-repair" : void 0),
4866
+ busy: props.busyByBot[bot.botId] ?? (isTargetedAppUpdate2(props.provisioning) && props.provisioning.botId === bot.botId ? props.provisioning.operation : void 0),
4636
4867
  repairDisabled: Boolean(props.provisioning),
4868
+ provisionContent: isTargetedAppUpdate2(props.provisioning) && props.provisioning.botId === bot.botId ? props.provisionContent : null,
4869
+ provisionRef: props.provisionRef,
4637
4870
  actionError: props.errorsByBot[bot.botId],
4638
4871
  testNotice: props.testNoticesByBot[bot.botId],
4639
4872
  removing: props.removeTargetId === bot.botId,
@@ -4641,6 +4874,8 @@ function BotList(props) {
4641
4874
  onRepairCallback: () => props.onRepairCallback(bot),
4642
4875
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(bot, workspace),
4643
4876
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(bot, agentPreset),
4877
+ onGroupResponseModeSave: (groupResponseMode) => props.onGroupResponseModeSave(bot, groupResponseMode),
4878
+ onGroupMessagePermissionAuthorize: () => props.onGroupMessagePermissionAuthorize(bot),
4644
4879
  onRequestRemove: () => props.onRequestRemove(bot),
4645
4880
  onConfirmRemove: () => props.onConfirmRemove(bot),
4646
4881
  onCancelRemove: props.onCancelRemove,
@@ -4727,6 +4962,7 @@ function FeishuSettingsTab({ rpcCall }) {
4727
4962
  const [focusBotId, setFocusBotId] = React11.useState(null);
4728
4963
  const cardRefs = React11.useRef(/* @__PURE__ */ new Map());
4729
4964
  const removeButtonRefs = React11.useRef(/* @__PURE__ */ new Map());
4965
+ const targetedProvisionRef = React11.useRef(null);
4730
4966
  const addButtonRef = React11.useRef(null);
4731
4967
  const mountedRef = React11.useRef(true);
4732
4968
  const workspaceFence = useWorkspaceSnapshotFence();
@@ -4804,15 +5040,27 @@ function FeishuSettingsTab({ rpcCall }) {
4804
5040
  node.focus({ preventScroll: true });
4805
5041
  setFocusBotId(null);
4806
5042
  }, [focusBotId, model.bots]);
5043
+ const targetedProvisionFocusKey = isTargetedAppUpdate2(model.provisioning) ? `${model.provisioning.botId}:${model.provisioning.attemptId ?? "preparing"}:${model.provisioning.phase}` : null;
5044
+ React11.useEffect(() => {
5045
+ if (!targetedProvisionFocusKey) return;
5046
+ scheduleAnimationFrame(() => {
5047
+ const node = targetedProvisionRef.current;
5048
+ if (!node) return;
5049
+ node.scrollIntoView?.({ block: "nearest", behavior: "smooth" });
5050
+ node.focus?.({ preventScroll: true });
5051
+ }, "targeted-provision-focus");
5052
+ }, [scheduleAnimationFrame, targetedProvisionFocusKey]);
4807
5053
  const startProvisioning = React11.useCallback(async ({
4808
5054
  replace = false,
4809
5055
  operation = FEISHU_REGISTRATION_OPERATIONS.PROVISION,
4810
5056
  bot
4811
5057
  } = {}) => {
4812
5058
  const repairing = operation === CALLBACK_REPAIR_OPERATION;
4813
- const botId = repairing ? bot?.botId ?? model.provisioning?.botId : void 0;
4814
- const botName = repairing ? bot?.bot?.name ?? model.provisioning?.botName : void 0;
4815
- if (repairing && !botId) return;
5059
+ const grantingGroupMessages = operation === GROUP_MESSAGE_PERMISSION_OPERATION;
5060
+ const targetedUpdate = repairing || grantingGroupMessages;
5061
+ const botId = targetedUpdate ? bot?.botId ?? model.provisioning?.botId : void 0;
5062
+ const botName = targetedUpdate ? bot?.bot?.name ?? model.provisioning?.botName : void 0;
5063
+ if (targetedUpdate && !botId) return;
4816
5064
  setCredentialOpen(false);
4817
5065
  setCredentialError(null);
4818
5066
  setProvisionBusy(true);
@@ -4835,12 +5083,13 @@ function FeishuSettingsTab({ rpcCall }) {
4835
5083
  } catch {
4836
5084
  }
4837
5085
  }
5086
+ const endpoint = repairing ? FEISHU_ENDPOINTS.beginCallbackRepair : grantingGroupMessages ? FEISHU_ENDPOINTS.beginGroupMessagePermission : FEISHU_ENDPOINTS.beginProvisioning;
4838
5087
  const provision2 = normalizeProvisioning2(await invoke(
4839
- repairing ? FEISHU_ENDPOINTS.beginCallbackRepair : FEISHU_ENDPOINTS.beginProvisioning,
4840
- repairing ? { botId } : { locale: "zh-CN" }
5088
+ endpoint,
5089
+ targetedUpdate ? { botId } : { locale: "zh-CN" }
4841
5090
  ));
4842
- if (repairing && (provision2.operation !== CALLBACK_REPAIR_OPERATION || provision2.botId !== botId)) {
4843
- throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801");
5091
+ if (targetedUpdate && (provision2.operation !== operation || provision2.botId !== botId)) {
5092
+ throw new Error(grantingGroupMessages ? "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801" : "\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u5361\u7247\u4FEE\u590D\u4E8C\u7EF4\u7801");
4844
5093
  }
4845
5094
  const timestamp7 = Date.now();
4846
5095
  setNow(timestamp7);
@@ -4854,7 +5103,7 @@ function FeishuSettingsTab({ rpcCall }) {
4854
5103
  expired: false
4855
5104
  }
4856
5105
  }));
4857
- announce(repairing ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002` : "\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002");
5106
+ announce(repairing ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u4FEE\u590D\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002` : grantingGroupMessages ? `${botName ?? "\u673A\u5668\u4EBA"}\u7684\u7FA4\u6D88\u606F\u6743\u9650\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u786E\u8BA4\u3002` : "\u6388\u6743\u4E8C\u7EF4\u7801\u5DF2\u751F\u6210\uFF0C\u8BF7\u4F7F\u7528\u98DE\u4E66\u626B\u7801\u3002");
4858
5107
  } catch (error) {
4859
5108
  setModel((current) => ({
4860
5109
  ...current,
@@ -4903,12 +5152,14 @@ function FeishuSettingsTab({ rpcCall }) {
4903
5152
  const activeProvision = model.provisioning;
4904
5153
  const attemptId = activeProvision?.attemptId;
4905
5154
  const repairing = isCallbackRepair(activeProvision);
4906
- const targetBot = repairing ? model.bots.find((bot) => bot.botId === activeProvision?.botId) : void 0;
5155
+ const grantingGroupMessages = isGroupMessagePermission(activeProvision);
5156
+ const targetedUpdate = isTargetedAppUpdate2(activeProvision);
5157
+ const targetBot = targetedUpdate ? model.bots.find((bot) => bot.botId === activeProvision?.botId) : void 0;
4907
5158
  setProvisionBusy(true);
4908
5159
  try {
4909
5160
  const result = attemptId ? normalizePollResult(await invoke(FEISHU_ENDPOINTS.cancelProvisioning, { attemptId })) : null;
4910
- if (repairing && result) {
4911
- if (result.operation !== CALLBACK_REPAIR_OPERATION || result.botId !== activeProvision.botId) {
5161
+ if (targetedUpdate && result) {
5162
+ if (result.operation !== activeProvision.operation || result.botId !== activeProvision.botId) {
4912
5163
  throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6");
4913
5164
  }
4914
5165
  if (result.status === "connecting") {
@@ -4922,23 +5173,23 @@ function FeishuSettingsTab({ rpcCall }) {
4922
5173
  expired: false
4923
5174
  }
4924
5175
  } : current);
4925
- announce("\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002");
5176
+ announce(grantingGroupMessages ? "\u6743\u9650\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u542F\u7528\u5168\u90E8\u6D88\u606F\u6A21\u5F0F\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002" : "\u914D\u7F6E\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u9A8C\u8BC1\u5361\u7247\u6309\u94AE\u56DE\u8C03\u5E76\u91CD\u8FDE\u6B64\u673A\u5668\u4EBA\uFF1B\u6B64\u9636\u6BB5\u65E0\u6CD5\u53D6\u6D88\uFF0C\u5176\u4ED6\u673A\u5668\u4EBA\u4E0D\u4F1A\u4E2D\u65AD\u3002");
4926
5177
  return;
4927
5178
  }
4928
5179
  if (result.status === "connected") {
4929
5180
  const targetBotName = targetBot?.bot.name ?? activeProvision.botName ?? "\u673A\u5668\u4EBA";
4930
5181
  setModel((current) => ({ ...current, provisioning: null }));
4931
- announce(`${targetBotName}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002`);
5182
+ announce(grantingGroupMessages ? `${targetBotName}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002` : `${targetBotName}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002`);
4932
5183
  if (activeProvision.botId) setFocusBotId(activeProvision.botId);
4933
5184
  await loadStatus({ silent: true, restoreProvisioning: false });
4934
5185
  return;
4935
5186
  }
4936
5187
  }
4937
5188
  setModel((current) => ({ ...current, provisioning: null }));
4938
- announce(repairing ? "\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002" : "\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002");
5189
+ announce(repairing ? "\u5DF2\u53D6\u6D88\u5361\u7247\u6309\u94AE\u4FEE\u590D\u3002" : grantingGroupMessages ? "\u5DF2\u53D6\u6D88\u7FA4\u6D88\u606F\u6743\u9650\u6388\u6743\u3002" : "\u5DF2\u53D6\u6D88\u6DFB\u52A0\u673A\u5668\u4EBA\u3002");
4939
5190
  await loadStatus({ silent: true, restoreProvisioning: false });
4940
5191
  scheduleAnimationFrame(() => {
4941
- if (repairing && activeProvision.botId) {
5192
+ if (targetedUpdate && activeProvision.botId) {
4942
5193
  cardRefs.current.get(activeProvision.botId)?.focus();
4943
5194
  } else {
4944
5195
  addButtonRef.current?.focus();
@@ -4986,26 +5237,26 @@ function FeishuSettingsTab({ rpcCall }) {
4986
5237
  { attemptId: provision2.attemptId },
4987
5238
  controller.signal
4988
5239
  ));
4989
- if (result.operation !== provision2.operation || isCallbackRepair(provision2) && result.botId !== provision2.botId) {
5240
+ if (result.operation !== provision2.operation || isTargetedAppUpdate2(provision2) && result.botId !== provision2.botId) {
4990
5241
  throw new Error("\u98DE\u4E66\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u5339\u914D\u7684\u6CE8\u518C\u8FDB\u5EA6");
4991
5242
  }
4992
5243
  if (result.status === "connected") {
4993
5244
  const snapshot = await loadStatus({ signal: controller.signal, silent: true, restoreProvisioning: false });
4994
5245
  const targetBot = snapshot?.bots.find((bot) => bot.botId === result.botId);
4995
5246
  if (!snapshot) {
4996
- throw new Error(isCallbackRepair(provision2) ? "\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : "\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001");
5247
+ throw new Error(isCallbackRepair(provision2) ? "\u5361\u7247\u6309\u94AE\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : isGroupMessagePermission(provision2) ? "\u7FA4\u6D88\u606F\u6743\u9650\u5DF2\u66F4\u65B0\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u673A\u5668\u4EBA\u8FDE\u63A5\u72B6\u6001" : "\u673A\u5668\u4EBA\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u8FDE\u63A5\u72B6\u6001");
4997
5248
  }
4998
5249
  if (!targetBot?.connected) {
4999
5250
  setModel((current) => current.provisioning?.attemptId === provision2.attemptId ? { ...current, provisioning: { ...current.provisioning, phase: "connecting" } } : current);
5000
5251
  return;
5001
5252
  }
5002
5253
  setModel((current) => ({ ...current, provisioning: null }));
5003
- announce(isCallbackRepair(provision2) ? `${targetBot.bot.name}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002` : targetBot ? `${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002` : "\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002");
5254
+ announce(isCallbackRepair(provision2) ? `${targetBot.bot.name}\u7684\u5361\u7247\u6309\u94AE\u5DF2\u4FEE\u590D\u3002` : isGroupMessagePermission(provision2) ? `${targetBot.bot.name}\u5DF2\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\uFF0C\u5E76\u542F\u7528\u201C\u54CD\u5E94\u6240\u6709\u7FA4\u6D88\u606F\u201D\u3002` : targetBot ? `${targetBot.bot.name}\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5728\u98DE\u4E66\u4E2D\u5F00\u59CB\u804A\u5929\u3002` : "\u65B0\u98DE\u4E66\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5\uFF0C\u53EF\u4EE5\u5F00\u59CB\u804A\u5929\u3002");
5004
5255
  if (result.botId) setFocusBotId(result.botId);
5005
5256
  return;
5006
5257
  }
5007
5258
  if (result.status === "failed") {
5008
- const error = new Error(result.message ?? (isCallbackRepair(provision2) ? "\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25" : "\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25"));
5259
+ const error = new Error(result.message ?? (isCallbackRepair(provision2) ? "\u98DE\u4E66\u5361\u7247\u6309\u94AE\u4FEE\u590D\u5931\u8D25" : isGroupMessagePermission(provision2) ? "\u98DE\u4E66\u7FA4\u6D88\u606F\u6743\u9650\u5F00\u901A\u5931\u8D25" : "\u98DE\u4E66\u5E94\u7528\u521B\u5EFA\u5931\u8D25"));
5009
5260
  error.code = "FEISHU_PROVISION_FAILED";
5010
5261
  throw error;
5011
5262
  }
@@ -5151,6 +5402,54 @@ function FeishuSettingsTab({ rpcCall }) {
5151
5402
  if (mountedRef.current) setBotBusy(botId, null);
5152
5403
  }
5153
5404
  }, [invoke, loadStatus, mergeSnapshot, setBotBusy, setBotError, workspaceFence]);
5405
+ const authorizeGroupMessages = React11.useCallback(async (connection) => {
5406
+ const { botId } = connection;
5407
+ if (model.provisioning) {
5408
+ throw new Error("\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u98DE\u4E66\u6388\u6743\u64CD\u4F5C\uFF0C\u518D\u5F00\u901A\u7FA4\u6D88\u606F\u6743\u9650\u3002");
5409
+ }
5410
+ setRemoveTargetId(null);
5411
+ setBotError(botId, null);
5412
+ setTestNoticesByBot((current) => {
5413
+ const next = { ...current };
5414
+ delete next[botId];
5415
+ return next;
5416
+ });
5417
+ await startProvisioning({
5418
+ operation: GROUP_MESSAGE_PERMISSION_OPERATION,
5419
+ bot: connection
5420
+ });
5421
+ }, [model.provisioning, setBotError, startProvisioning]);
5422
+ const saveGroupResponseMode = React11.useCallback(async (connection, groupResponseMode) => {
5423
+ const { botId } = connection;
5424
+ if (groupResponseMode === "all" && connection.groupMessagePermissionGranted !== true) {
5425
+ await authorizeGroupMessages(connection);
5426
+ return;
5427
+ }
5428
+ const snapshotVersion = workspaceFence.beginMutation();
5429
+ setBotBusy(botId, "group-response-mode");
5430
+ setBotError(botId, null);
5431
+ try {
5432
+ const snapshot = normalizeBotsSnapshot(await invoke(
5433
+ FEISHU_ENDPOINTS.setGroupResponseMode,
5434
+ { botId, groupResponseMode }
5435
+ ));
5436
+ if (mountedRef.current && workspaceFence.canCommitMutation(snapshotVersion)) {
5437
+ mergeSnapshot(snapshot);
5438
+ }
5439
+ } finally {
5440
+ const shouldRefresh = workspaceFence.endMutation();
5441
+ if (shouldRefresh && mountedRef.current) void loadStatus({ silent: true });
5442
+ if (mountedRef.current) setBotBusy(botId, null);
5443
+ }
5444
+ }, [
5445
+ invoke,
5446
+ authorizeGroupMessages,
5447
+ loadStatus,
5448
+ mergeSnapshot,
5449
+ setBotBusy,
5450
+ setBotError,
5451
+ workspaceFence
5452
+ ]);
5154
5453
  const requestRemove = React11.useCallback((connection) => {
5155
5454
  setRemoveTargetId(connection.botId);
5156
5455
  }, []);
@@ -5185,6 +5484,7 @@ function FeishuSettingsTab({ rpcCall }) {
5185
5484
  }
5186
5485
  }, [announce, invoke, loadStatus, mergeSnapshot, scheduleAnimationFrame, setBotBusy, setBotError, workspaceFence]);
5187
5486
  const provision = model.provisioning;
5487
+ const targetedProvisioning = isTargetedAppUpdate2(provision);
5188
5488
  const provisionBot = provision?.botId ? model.bots.find((bot) => bot.botId === provision.botId) ?? { botId: provision.botId, bot: { name: provision.botName ?? "\u6B64\u673A\u5668\u4EBA" } } : void 0;
5189
5489
  const restartProvisioning = ({ replace = false } = {}) => startProvisioning({
5190
5490
  replace,
@@ -5210,7 +5510,7 @@ function FeishuSettingsTab({ rpcCall }) {
5210
5510
  provisionContent = h2(ProvisionProgress, {
5211
5511
  phase: "connecting",
5212
5512
  provision,
5213
- onCancel: isCallbackRepair(provision) ? void 0 : () => void cancelProvisioning(),
5513
+ onCancel: isTargetedAppUpdate2(provision) ? void 0 : () => void cancelProvisioning(),
5214
5514
  busy: provisionBusy
5215
5515
  });
5216
5516
  } else if (provision?.phase === "error") {
@@ -5290,7 +5590,7 @@ function FeishuSettingsTab({ rpcCall }) {
5290
5590
  React11.Fragment,
5291
5591
  null,
5292
5592
  credentialContent,
5293
- provisionContent,
5593
+ targetedProvisioning ? null : provisionContent,
5294
5594
  model.bots.length === 0 && !provision && !credentialOpen ? h2(EmptyView2, { onStart: () => void startProvisioning(), busy: provisionBusy }) : null,
5295
5595
  model.bots.length > 0 ? h2(BotList, {
5296
5596
  bots: model.bots,
@@ -5299,10 +5599,14 @@ function FeishuSettingsTab({ rpcCall }) {
5299
5599
  testNoticesByBot,
5300
5600
  removeTargetId,
5301
5601
  provisioning: provision,
5602
+ provisionContent,
5603
+ provisionRef: targetedProvisionRef,
5302
5604
  onReconnect: (bot) => void reconnectOneBot(bot),
5303
5605
  onRepairCallback: repairCallback,
5304
5606
  onWorkspaceSave: saveWorkspace,
5305
5607
  onAgentPresetSave: saveAgentPreset,
5608
+ onGroupResponseModeSave: saveGroupResponseMode,
5609
+ onGroupMessagePermissionAuthorize: authorizeGroupMessages,
5306
5610
  onRequestRemove: requestRemove,
5307
5611
  onConfirmRemove: (bot) => void confirmRemove(bot),
5308
5612
  onCancelRemove: cancelRemove,