@wenbin_wb/dsh-bridge 2.2.9 → 2.3.1

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/client/index.js CHANGED
@@ -348,6 +348,8 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
348
348
  appId: platform.config.appId ?? '',
349
349
  // Secret 不由后端回传;空值表示沿用已保存密钥
350
350
  clientSecret: '',
351
+ appSecret: '',
352
+ domain: platform.config.domain ?? 'feishu',
351
353
  });
352
354
  }
353
355
  }, [platform?.config]);
@@ -436,10 +438,14 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
436
438
  maxMessageChars: Number(cfgDraft.maxMessageChars),
437
439
  sendChunkDelayMs: Number(cfgDraft.sendChunkDelayMs),
438
440
  };
439
- // QQ 平台额外携带凭证
441
+ // QQ / 飞书 平台额外携带凭证
440
442
  if (platformId === 'qq') {
441
443
  payload.appId = cfgDraft.appId.trim();
442
444
  payload.clientSecret = cfgDraft.clientSecret.trim();
445
+ } else if (platformId === 'feishu') {
446
+ payload.appId = cfgDraft.appId.trim();
447
+ payload.appSecret = cfgDraft.appSecret.trim();
448
+ payload.domain = cfgDraft.domain || 'feishu';
443
449
  }
444
450
  await act(BRIDGE_ENDPOINTS.platformSetConfig, payload);
445
451
  }, [act, cfgDraft, platformId]);
@@ -451,6 +457,10 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
451
457
  (platformId === 'qq' && (
452
458
  cfgDraft.appId !== (platform.config.appId ?? '') ||
453
459
  cfgDraft.clientSecret !== (platform.config.clientSecret ?? '')
460
+ )) ||
461
+ (platformId === 'feishu' && (
462
+ cfgDraft.appId !== (platform.config.appId ?? '') ||
463
+ cfgDraft.appSecret !== (platform.config.appSecret ?? '')
454
464
  ))
455
465
  );
456
466
 
@@ -503,6 +513,16 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
503
513
  target: '_blank', rel: 'noopener noreferrer',
504
514
  style: s.btnGhost,
505
515
  }, '🌐 QQ 开放平台'),
516
+ platformId === 'feishu' && React.createElement('a', {
517
+ href: 'https://github.com/wenbin-wb/dsh-bridge/blob/main/docs/feishu-usage.md',
518
+ target: '_blank', rel: 'noopener noreferrer',
519
+ style: s.btnGhost,
520
+ }, '📖 飞书使用说明'),
521
+ platformId === 'feishu' && React.createElement('a', {
522
+ href: 'https://open.feishu.cn/app',
523
+ target: '_blank', rel: 'noopener noreferrer',
524
+ style: s.btnGhost,
525
+ }, '🌐 飞书开放平台'),
506
526
  React.createElement('button', {
507
527
  style: s.btnGhost,
508
528
  onClick: () => setShowHelp(v => !v),
@@ -613,19 +633,49 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
613
633
  ),
614
634
  React.createElement('div', { style: { display: 'flex', gap: 8, marginTop: 10, flexWrap: 'wrap', alignItems: 'center' } },
615
635
  platform.status !== 'connected' && platform.status !== 'starting' &&
616
- React.createElement('button', { style: s.btnPri, onClick: onLogin, disabled: busy }, '重新登录'),
636
+ React.createElement('button', { style: s.btnPri, onClick: onLogin, disabled: busy }, '重新连接'),
617
637
  (platform.status === 'connected' || platform.status === 'starting') &&
618
638
  React.createElement('button', { style: s.btnGhost, onClick: onStop, disabled: busy }, '断开'),
619
639
  React.createElement('button', {
620
640
  style: { ...s.btnGhost, color: 'var(--dsw-alias-state-error-primary,#dc2626)', borderColor: 'var(--dsw-alias-state-error-primary,#dc2626)', opacity: busy ? 0.5 : 1 },
621
641
  disabled: busy,
622
- onClick: () => { if (window.confirm('确认解绑?这将清除登录凭证,下次需重新登录。')) act(BRIDGE_ENDPOINTS.platformUnbind, {}); },
623
- title: '清除登录凭证,下次需重新登录',
642
+ onClick: () => { if (window.confirm('确认解绑?这将清除保存的凭证。')) act(BRIDGE_ENDPOINTS.platformUnbind, {}); },
643
+ title: '清除登录凭证,下次需重新配置',
624
644
  }, '解绑账号'),
625
645
  ),
646
+ // 飞书专属:手机扫码直达 Bot 对话
647
+ platformId === 'feishu' && platform.botQr && React.createElement('div', {
648
+ style: {
649
+ marginTop: 12,
650
+ padding: 12,
651
+ background: 'var(--dsw-alias-bg-layer-1,#ffffff)',
652
+ border: '1px solid var(--dsw-alias-border-l2,#e5e7eb)',
653
+ borderRadius: 8,
654
+ display: 'flex',
655
+ gap: 14,
656
+ alignItems: 'center',
657
+ flexWrap: 'wrap',
658
+ },
659
+ },
660
+ React.createElement('img', { src: platform.botQr, alt: 'Feishu Bot QR', style: { width: 110, height: 110, borderRadius: 8, border: '1px solid var(--dsw-alias-border-l2,#e5e7eb)', padding: 4, background: '#fff' } }),
661
+ React.createElement('div', { style: { flex: 1, minWidth: 160 } },
662
+ React.createElement('div', { style: { ...s.label, fontSize: 13, fontWeight: 600 } }, '📱 手机飞书扫码直达对话'),
663
+ React.createElement('div', { style: { ...s.muted, fontSize: 12, marginTop: 4, lineHeight: 1.5 } },
664
+ '用飞书手机 App 扫描左侧二维码,立即打开与 Bot 对话;发送首条消息自动完成白名单授权。'
665
+ ),
666
+ platform.botLink && React.createElement('div', { style: { display: 'flex', gap: 8, marginTop: 8 } },
667
+ React.createElement('a', {
668
+ href: platform.botLink,
669
+ target: '_blank',
670
+ rel: 'noopener noreferrer',
671
+ style: { ...s.btnGhost, textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 4, padding: '4px 10px', fontSize: 12 },
672
+ }, '在飞书客户端打开 ↗'),
673
+ ),
674
+ ),
675
+ ),
626
676
  ),
627
677
 
628
- // 未配置 / 登录中:二维码(QQ 无二维码,显示凭证表单)
678
+ // 未配置 / 登录中:表单(QQ / 飞书)或二维码(微信)
629
679
  (!platform?.configured || showQr) && React.createElement('div', { style: s.block },
630
680
  showQr && login.qr
631
681
  ? React.createElement('div', null,
@@ -637,28 +687,45 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
637
687
  ),
638
688
  login.error && React.createElement('div', { style: { ...s.muted, marginTop: 4, color: 'var(--dsw-alias-state-warn-primary,#92400e)' } }, login.error),
639
689
  )
640
- : platformId === 'qq'
690
+ : (platformId === 'qq' || platformId === 'feishu')
641
691
  ? React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 10, marginTop: 4 } },
692
+ platformId === 'feishu' && React.createElement('div', {
693
+ style: {
694
+ background: 'var(--dsw-alias-bg-layer-1,#ffffff)',
695
+ border: '1px dashed var(--dsw-alias-border-l2,#e5e7eb)',
696
+ borderRadius: 6,
697
+ padding: '8px 10px',
698
+ fontSize: 12,
699
+ lineHeight: 1.5,
700
+ },
701
+ },
702
+ React.createElement('span', { style: s.label }, '💡 扫码自动创建引导:'),
703
+ React.createElement('span', { style: s.muted }, ' 可在终端运行 '),
704
+ React.createElement('code', { style: { ...s.code, fontSize: 11, background: 'var(--dsw-alias-bg-layer-2,#f3f4f6)', padding: '2px 4px', borderRadius: 4 } }, 'npx feishu-bot-bootstrap'),
705
+ React.createElement('span', { style: s.muted }, ' 手机扫码一键自动创建应用并输出凭证;或在下方手动填入凭证。')
706
+ ),
642
707
  React.createElement('div', null,
643
- React.createElement('div', { style: { ...s.muted, marginBottom: 4 } }, 'AppID — QQ 开放平台机器人应用 ID'),
708
+ React.createElement('div', { style: { ...s.muted, marginBottom: 4 } },
709
+ platformId === 'qq' ? 'AppID — QQ 开放平台机器人应用 ID' : 'App ID — 飞书开放平台自建应用 ID (cli_xxx)'
710
+ ),
644
711
  React.createElement('input', {
645
712
  style: { ...s.input, width: '100%' },
646
- placeholder: '请输入 AppID',
713
+ placeholder: platformId === 'qq' ? '请输入 AppID' : '请输入 App ID (如 cli_a1b2c3d4...)',
647
714
  value: cfgDraft?.appId ?? '',
648
715
  onChange: (e) => setCfgDraft(d => ({ ...d, appId: e.target.value })),
649
- onKeyDown: (e) => { if (e.key === 'Enter' && cfgDraft?.appId?.trim() && cfgDraft?.clientSecret?.trim() && !busy) saveConfig(); },
650
716
  }),
651
717
  ),
652
718
  React.createElement('div', null,
653
- React.createElement('div', { style: { ...s.muted, marginBottom: 4 } }, 'ClientSecret — QQ 开放平台机器人密钥'),
719
+ React.createElement('div', { style: { ...s.muted, marginBottom: 4 } },
720
+ platformId === 'qq' ? 'ClientSecret — QQ 开放平台机器人密钥' : 'App Secret — 飞书开放平台应用密钥'
721
+ ),
654
722
  React.createElement('div', { style: { display: 'flex', gap: 6, alignItems: 'center' } },
655
723
  React.createElement('input', {
656
724
  style: { ...s.input, flex: 1 },
657
725
  type: showSecret ? 'text' : 'password',
658
- placeholder: '请输入 ClientSecret',
659
- value: cfgDraft?.clientSecret ?? '',
660
- onChange: (e) => setCfgDraft(d => ({ ...d, clientSecret: e.target.value })),
661
- onKeyDown: (e) => { if (e.key === 'Enter' && cfgDraft?.appId?.trim() && cfgDraft?.clientSecret?.trim() && !busy) saveConfig(); },
726
+ placeholder: platformId === 'qq' ? '请输入 ClientSecret' : '请输入 App Secret',
727
+ value: platformId === 'qq' ? (cfgDraft?.clientSecret ?? '') : (cfgDraft?.appSecret ?? ''),
728
+ onChange: (e) => setCfgDraft(d => platformId === 'qq' ? ({ ...d, clientSecret: e.target.value }) : ({ ...d, appSecret: e.target.value })),
662
729
  }),
663
730
  React.createElement('button', {
664
731
  style: { ...s.btnGhost, height: 32, padding: '0 10px', fontSize: 13, flexShrink: 0 },
@@ -670,15 +737,16 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
670
737
  ),
671
738
  React.createElement('div', null,
672
739
  React.createElement('a', {
673
- href: 'https://bot.q.qq.com/wiki/develop/api-v2/',
740
+ href: platformId === 'qq' ? 'https://bot.q.qq.com/wiki/develop/api-v2/' : 'https://open.feishu.cn/app',
674
741
  target: '_blank', rel: 'noopener noreferrer',
675
742
  style: s.btnLink,
676
- }, '📖 前往 QQ 开放平台申请机器人'),
743
+ }, platformId === 'qq' ? '📖 前往 QQ 开放平台申请机器人' : '📖 前往飞书开放平台创建企业自建应用'),
677
744
  ),
678
745
  React.createElement('div', { style: { display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' } },
679
746
  React.createElement('button', {
680
747
  style: { ...s.btnPri, opacity: busy ? 0.5 : 1 },
681
- onClick: saveConfig, disabled: busy || !cfgDraft?.appId?.trim() || !cfgDraft?.clientSecret?.trim(),
748
+ onClick: saveConfig,
749
+ disabled: busy || !cfgDraft?.appId?.trim() || (platformId === 'qq' ? !cfgDraft?.clientSecret?.trim() : !cfgDraft?.appSecret?.trim()),
682
750
  }, busy ? '保存中…' : '保存并连接'),
683
751
  login.phase === 'error' && React.createElement('div', { style: { ...s.muted, fontSize: 12 } }, login.error ?? '连接失败'),
684
752
  ),
@@ -692,106 +760,7 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
692
760
  ),
693
761
  ),
694
762
 
695
- // 高级设置(紧凑 2x2 网格 + 恢复默认值)
696
- cfgDraft && React.createElement('div', { style: s.block },
697
- React.createElement('button', {
698
- style: { ...s.btnLink, fontSize: 12, marginBottom: showAdvanced ? 10 : 0 },
699
- onClick: () => setShowAdvanced(v => !v),
700
- }, showAdvanced ? '▾ 高级设置' : '▸ 高级设置'),
701
- showAdvanced && React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 10 } },
702
- // 2x2 参数网格
703
- React.createElement('div', {
704
- style: {
705
- display: 'grid',
706
- gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
707
- gap: 10,
708
- },
709
- },
710
- // 心跳间隔
711
- React.createElement('div', null,
712
- React.createElement('div', { style: { ...s.muted, marginBottom: 4 } }, '心跳进度间隔 (秒)'),
713
- React.createElement('input', {
714
- style: { ...s.input, width: '100%' },
715
- type: 'number', min: 30, max: 3600,
716
- value: cfgDraft.digestIntervalSec,
717
- onChange: (e) => setCfgDraft(d => ({ ...d, digestIntervalSec: e.target.value })),
718
- }),
719
- ),
720
- // 审批超时
721
- React.createElement('div', null,
722
- React.createElement('div', { style: { ...s.muted, marginBottom: 4 } }, '审批超时自动拒绝 (秒)'),
723
- React.createElement('input', {
724
- style: { ...s.input, width: '100%' },
725
- type: 'number', min: 30, max: 86400,
726
- value: cfgDraft.approvalTimeoutSec,
727
- onChange: (e) => setCfgDraft(d => ({ ...d, approvalTimeoutSec: e.target.value })),
728
- }),
729
- ),
730
- // 每气泡字数
731
- React.createElement('div', null,
732
- React.createElement('div', { style: { ...s.muted, marginBottom: 4 } }, '单条最大字数限制 (字)'),
733
- React.createElement('input', {
734
- style: { ...s.input, width: '100%' },
735
- type: 'number', min: 100, max: 10000,
736
- value: cfgDraft.maxMessageChars,
737
- onChange: (e) => setCfgDraft(d => ({ ...d, maxMessageChars: e.target.value })),
738
- }),
739
- ),
740
- // 分块延迟
741
- React.createElement('div', null,
742
- React.createElement('div', { style: { ...s.muted, marginBottom: 4 } }, '分块发送延迟 (毫秒)'),
743
- React.createElement('input', {
744
- style: { ...s.input, width: '100%' },
745
- type: 'number', min: 0, max: 10000,
746
- value: cfgDraft.sendChunkDelayMs,
747
- onChange: (e) => setCfgDraft(d => ({ ...d, sendChunkDelayMs: e.target.value })),
748
- }),
749
- ),
750
- ),
751
- // QQ 平台凭证
752
- platformId === 'qq' && React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 10, marginTop: 4 } },
753
- React.createElement('div', null,
754
- React.createElement('div', { style: { ...s.muted, marginBottom: 4 } }, 'AppID — QQ 开放平台机器人应用 ID'),
755
- React.createElement('input', {
756
- style: { ...s.input, width: '100%' },
757
- placeholder: '请输入 AppID',
758
- value: cfgDraft.appId,
759
- onChange: (e) => setCfgDraft(d => ({ ...d, appId: e.target.value })),
760
- }),
761
- ),
762
- React.createElement('div', null,
763
- React.createElement('div', { style: { ...s.muted, marginBottom: 4 } }, 'ClientSecret — QQ 开放平台机器人密钥(留空则保持已保存密钥)'),
764
- React.createElement('div', { style: { display: 'flex', gap: 6, alignItems: 'center' } },
765
- React.createElement('input', {
766
- style: { ...s.input, flex: 1 },
767
- type: showSecret ? 'text' : 'password',
768
- placeholder: '留空保持已保存密钥',
769
- value: cfgDraft.clientSecret,
770
- onChange: (e) => setCfgDraft(d => ({ ...d, clientSecret: e.target.value })),
771
- }),
772
- React.createElement('button', {
773
- style: { ...s.btnGhost, height: 32, padding: '0 10px', fontSize: 13, flexShrink: 0 },
774
- onClick: () => setShowSecret(v => !v),
775
- type: 'button',
776
- title: showSecret ? '隐藏密钥' : '显示明文',
777
- }, showSecret ? '🙈 隐藏' : '👁️ 显示'),
778
- ),
779
- ),
780
- ),
781
- React.createElement('div', { style: { display: 'flex', gap: 8, alignItems: 'center', marginTop: 4 } },
782
- React.createElement('button', {
783
- style: { ...s.btnPri, opacity: (cfgDirty && !busy) ? 1 : 0.5 },
784
- disabled: !cfgDirty || busy,
785
- onClick: saveConfig,
786
- }, busy ? '保存中…' : '保存设置'),
787
- React.createElement('button', {
788
- style: { ...s.btnGhost, height: 32, fontSize: 12 },
789
- onClick: resetDefaults,
790
- title: '恢复推荐默认配置',
791
- }, '↺ 恢复推荐默认'),
792
- ),
793
- ),
794
- ),
763
+
795
764
 
796
765
  React.createElement('div', { style: s.block },
797
766
  React.createElement('div', { style: { ...s.tip, fontSize: 12 } },
@@ -1221,7 +1190,7 @@ function BridgePanel({ rpcCall }) {
1221
1190
  const IM_PLATFORMS = [
1222
1191
  { id: 'wechat', label: '微信', icon: Icons.wechat, brandColor: '#07C160', desc: 'ClawBot 扫码直连 · 无需公网' },
1223
1192
  { id: 'qq', label: 'QQ', icon: Icons.qq, brandColor: '#12B7F5', desc: '官方机器人 · 私聊/群聊/按钮' },
1224
- { id: 'feishu', label: '飞书', icon: Icons.feishu, brandColor: '#00D6B9', desc: '官方事件回调 API' },
1193
+ { id: 'feishu', label: '飞书', icon: Icons.feishu, brandColor: '#00D6B9', desc: '官方 WebSocket 长连接 · 免公网' },
1225
1194
  { id: 'telegram', label: 'Telegram', icon: Icons.telegram, brandColor: '#24A1DE', desc: '官方 Bot API' },
1226
1195
  ];
1227
1196
 
@@ -0,0 +1,93 @@
1
+ # 飞书 (Feishu / Lark) 机器人接入指南
2
+
3
+ > 通过飞书官方开放平台 **WebSocket 长连接(免公网 IP)** 模式,将本地 DeepSeek Harness 接入飞书,支持单聊、群聊、表格命令与原生交互卡片权限审批。
4
+
5
+ ---
6
+
7
+ ## 🌟 核心优势
8
+
9
+ - **100% 免公网 IP**:基于飞书官方最新 WebSocket 长连接协议,无需配置公网服务器、无需域名、无需内网穿透工具。
10
+ - **免验签与加密配置**:长连接由飞书官方 SDK 在建立通道时完成认证,无需开发者手动处理 HTTP 回调验签。
11
+ - **飞书原生交互卡片**:Agent 触发敏感工具审批时,飞书端下发带点击按钮的交互卡片,手机/电脑端单手一键点击即可完成批准或拒绝。
12
+ - **多工作区与会话持久化**:支持 `/sessions` 表格查看历史会话、`/use <序号>` 极速切换、`/workspaces` 工作区调度。
13
+
14
+ ---
15
+
16
+ ## 🛠️ 第一步:创建飞书企业自建应用
17
+
18
+ 1. 登录 [飞书开放平台开发者后台](https://open.feishu.cn/app);
19
+ 2. 点击右上角 **「创建企业自建应用」**,填写应用名称(如 `DeepSeek Harness`)与应用描述,上传机器人头像;
20
+ 3. 创建完成后,在左侧导航栏点击 **「凭证与基础信息」**,即可查看到:
21
+ - **App ID**(格式如 `cli_a1b2c3d4...`)
22
+ - **App Secret**(点击复制密钥)
23
+
24
+ ---
25
+
26
+ ## 🤖 第二步:添加机器人能力
27
+
28
+ 1. 在应用详情页左侧导航栏,点击 **「添加应用能力」**;
29
+ 2. 找到 **「机器人」**,点击 **「添加」** 开启机器人能力。
30
+
31
+ ---
32
+
33
+ ## 🔐 第三步:开通必要权限
34
+
35
+ 在左侧导航栏点击 **「权限管理」**,搜索并开通以下权限:
36
+
37
+ | 权限名称 | 权限 Key | 权限说明 |
38
+ | :--- | :--- | :--- |
39
+ | **获取与发送单聊/群聊消息** | `im:message` | 基础消息收发权限 |
40
+ | **以应用的身份发消息** | `im:message:send_as_bot` | 允许机器人向用户/群回复消息 |
41
+ | **获取群组中所有消息** | `im:message.group_msg` | 允许机器人在群聊中被 `@` 时接收消息 |
42
+ | **获取用户 user ID** | `contact:user.id:readonly` | (可选) 获取用户信息 |
43
+
44
+ ---
45
+
46
+ ## ⚡ 第四步:开启 WebSocket 长连接事件订阅
47
+
48
+ 1. 在左侧导航栏点击 **「事件与回调」**;
49
+ 2. 在 **「事件配置」** 页面,将事件接收方式切换为 **「使用长连接接收事件」**(WebSocket 模式);
50
+ 3. 点击 **「添加事件」**,勾选并添加:
51
+ - **`im.message.receive_v1`**(接收消息)
52
+ - **`card.action.trigger`**(消息卡片回传交互 / 审批按钮点击)
53
+ 4. 保存配置。
54
+
55
+ ---
56
+
57
+ ## 🚀 第五步:版本发布
58
+
59
+ 1. 在左侧导航栏点击 **「版本管理与发布」**;
60
+ 2. 点击 **「创建版本」**,填写版本号(如 `1.0.0`),设置应用可用范围(如「所有员工」或「仅自己」);
61
+ 3. 点击 **「申请发布」**(自建应用通常由企业管理员直接免审或一键通过)。
62
+
63
+ ---
64
+
65
+ ## 📱 第六步:在 DSH 客户端中连接
66
+
67
+ 1. 打开 DeepSeek Harness,进入「设置」➔「远程访问」➔「IM 机器人」➔ 选择 **「飞书」**;
68
+ 2. 在表单中填入刚才复制的 **App ID** 和 **App Secret**;
69
+ 3. 点击 **「保存并连接」**;
70
+ 4. 状态显示为绿色 **「已连接」** 即表示长连接成功建立!
71
+
72
+ ---
73
+
74
+ ## 💬 常用操作与指令
75
+
76
+ 在飞书与机器人单聊或在群里 `@机器人` 即可开始对话:
77
+
78
+ ### 1. 会话与工作区管理
79
+ | 指令 | 说明 | 示例 |
80
+ | :--- | :--- | :--- |
81
+ | `/sessions` | 查看所有历史会话表格 | `/sessions` 或 `/list` |
82
+ | `/use <编号>` | 切换到指定编号会话 | `/use 1` 或 `/resume 1` |
83
+ | `/new <提示词>` | 在当前工作区创建新会话并开始 | `/new 帮我写个脚本` |
84
+ | `/new <词> @N` | 在指定工作区新建会话 | `/new 帮我写个脚本 @1` |
85
+ | `/workspaces` | 查看所有已注册的工作区列表 | `/workspaces` |
86
+ | `/status` | 查看 Agent 运行状态看板 | `/status` |
87
+ | `/stop` | 中断停止当前正在执行的任务 | `/stop` |
88
+ | `/end` | 结束当前会话回到空闲状态 | `/end` |
89
+
90
+ ### 2. 权限审批交互
91
+ 当 Agent 尝试执行需授权的操作(如终端命令、写敏感文件)时,飞书端会自动推送 **原生交互卡片**:
92
+ - 点击卡片上的 **「✓ 批准执行」** 或 **「✕ 拒绝执行」** 按钮即可一键处理;
93
+ - 亦可直接回复文字 `/yes` (或 `1`) / `/no` (或 `2`)。