Skip to content

feat(dashboard): 支持 Webhook 新建群邀请多个机器人;修复搜索框和搜索图标样式错乱 - #1305

Open
pigeoner wants to merge 2 commits into
deepcoldy:masterfrom
pigeoner:fix/dashboard-webhook-target-bots
Open

feat(dashboard): 支持 Webhook 新建群邀请多个机器人;修复搜索框和搜索图标样式错乱#1305
pigeoner wants to merge 2 commits into
deepcoldy:masterfrom
pigeoner:fix/dashboard-webhook-target-bots

Conversation

@pigeoner

@pigeoner pigeoner commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

改了什么

  • Dashboard Webhook 的「每次新建群」模式新增「一并邀请的机器人」多选入口。
  • 复用固定群选择器的搜索下拉交互,支持多选机器人。
  • 已选机器人以标签展示在选择框内,支持点击叉号取消选择,hover 可查看完整机器人信息。
  • 保存时为 new-group target 写入 target.botIds,包含触发机器人和已选附加机器人并去重。
  • 非 new-group 模式显式清空 botIds,避免旧配置残留。
  • Webhook 列表补充展示新建群配置包含的机器人数量。
  • 增加搜索框左侧 padding 避免图标遮盖 placeholder & 搜索图标偏移相关样式修正。

为什么

后端已经支持 new-group 模式通过 target.botIds 固定邀请多个机器人,但 Dashboard 之前只暴露
了「触发的机器人」单选,无法直接配置一并邀请的机器人,需要通过 API 手工补字段。

影响面

  • 仅影响 Dashboard Webhook 创建/编辑表单和 Webhook 列表展示。
  • 后端 Webhook 触发、建群、daemon 逻辑未改。
  • dynamic / fixed 模式行为保持不变。
  • SearchableGroupPicker 只增加可选展示能力,现有固定群/允许群选择逻辑保持原样。

测试

  • bun run test -- test/dashboard-connectors.test.ts
  • bun run dashboard:bundle
  • bun run build
  • Playwright 验证:
    • new-group 模式可选择多个附加机器人
    • 已选标签可点击叉号取消
    • 标签 hover 可查看完整内容
    • 移动宽度下无横向溢出
    • 提交体包含 target.botIds
image

@pigeoner
pigeoner requested a review from deepcoldy as a code owner September 7, 2026 12:39
@deepcoldy

Copy link
Copy Markdown
Owner

感谢这个 PR!把 target.botIds 从「只能手工调 API 补字段」补成界面上的多选入口,方向很对;chip 展示 + 超出折叠 +N + hover 看全名这套交互也做得很完整,抽出的三个纯函数(normalizeConnectorBotIds / additionalConnectorBotIds / buildConnectorTargetBody)顺手把原来散在提交函数里的 target 拼装逻辑收敛了,可读性比改之前好。CI 9/9 全绿,新增的 8 条断言我做了反变异验证(去掉 trim() / 去掉 Set 去重 / 去掉 else 清空三枪全部转红),是承重的测试而不是摆设。

下面两点想请你看一下,第一点建议合入前修:


1. 取消勾选全部附加机器人后,配置删不掉(建议修复)

buildConnectorTargetBody 的 new-group 分支只在 botIds.length > 1 时写字段,否则整个 botIds key 不出现:

if (form.mode === 'new-group') {
  const botIds = normalizeConnectorBotIds(form.botId, form.additionalBotIds);
  if (botIds.length > 1) target.botIds = botIds;   // ← 为空时整个 key 消失
} else {
  target.botIds = [];
}

而后端 src/dashboard/connector-api.ts:246 用的是 hasOwn 判断——key 不存在就沿用 prior 旧值

const botIds = hasOwn(target, 'botIds') ? ...新值... : prior?.target.botIds;

两边拼起来,用户把 chips 全删光再保存,旧的 botIds 会原封不动留在库里。起真实 handleConnectorApi 服务器跑端到端(发的就是 UI 会发的 body):

AFTER CREATE  botIds = ["app1","app2","app3"]
UI SENDS ON EDIT   = {"kind":"turn","mode":"new-group","botId":"app1"}   ← 无 botIds 键
AFTER EDIT    botIds = ["app1","app2","app3"]
RE-READ       botIds = ["app1","app2","app3"]   ← 没删掉

症状对用户是即时可见的:保存后 UI 用服务器返回的 connector 刷新本地状态,formFromConnector 又把 prior botIds 读回 additionalBotIds,所以刚删掉的 chips 会当场复活;后续触发也会继续把已取消的机器人拉进新群。

「把触发机器人换成原本是附加项的那个」也是同一个缺口:prior [app1, app2],触发机器人 app1→app2,onChange 把 app2 从附加项里滤掉后附加项为空 → body 无 botIds 键 → 库里仍是 [app1, app2]

顺带一提,这个 hasOwn 合并语义在 API 层是对的(allowChats / chatId / instruction 都同构,脚本化局部更新依赖它),所以更适合在前端侧修。而且你的 else 分支显式发了 botIds: [] 并且后端确实正确清空了(实测切到 fixed 后回读是 undefined)——说明契约你是清楚的,new-group 这里应该只是漏了。

建议:去掉 length > 1 判断,恒发即可。

if (form.mode === 'new-group') {
  target.botIds = normalizeConnectorBotIds(form.botId, form.additionalBotIds);
} else {
  target.botIds = [];
}

只有触发机器人时发 ["app1"] 是安全的:后端 botIds.includes(botId) 能处理,lifecycleBotIds 会合并去重,列表徽标本来就是 length > 1 才显示,回填时 additionalConnectorBotIds 会滤成空。

另外现有单测正好跳过了这一格——覆盖了 length > 1 和 fixed 两种情况,缺「new-group 且附加项为空」,建议补一条断言钉住。


2. 新增的全局 CSS 会波及 8 个无关搜索框(建议收窄作用域)

input[type=search]:not([type=checkbox])...:not([type=button]) { padding-left: 32px; }

这条没有作用域,命中全仓所有 type="search"。我用真 Chromium 加载完整 style.css,按各站点从 .tsx 源码扒出的真实 DOM 祖先链做了 17 个采样点的 A/B:

                              master → PR
connectors picker(目标)      11px → 32px   ✅ 想要的
wb-session-search             11px → 32px   ⚠️ 有 ⌕ 图标
roles listener toolbar        11px → 32px   ⚠️ 无图标
bot-multi-select              11px → 32px   ⚠️ 无图标
insights convo-search         11px → 32px   ⚠️ 无图标
schedule chat picker          11px → 32px   ⚠️ 无图标
vc-bot-policy-search          11px → 32px   ⚠️ 无图标
sessions-filter-cli-search    11px → 32px   ⚠️ 无图标
(其余 9 点被更高特异性 / !important 挡住,不变)

即总共改动 9 处,其中 8 处是误伤:7 个没有搜索图标,32px 是纯空白;wb-session-search(agent workbench 会话列表)稍麻烦一些——它的 flex 兄弟节点而非定位覆盖层(.wb-session-search { display:flex; padding:0 14px }),32px 会在图标右边再顶开一段,把图标和文字撑开。

根因其实是特异性,不是缺规则:仓库里本来就有一条作用域规则

.connectors-page .cn-form .connector-group-search > input[type="search"] { padding: 0 12px 0 34px; }

但它 (0,3,1) 被基础规则那串 7 个 :not()(0,8,1) 压过了,所以看起来「没生效」。

建议:给这条已有规则补上同样的 :not() 链((0,11,1)),并删掉新增的全局规则。我实测过这个改法:目标站点 11px → 34px(正好对齐图标 left:13px + 10px 宽 + 间隙),其余 16 个采样点逐点不变。全仓带图标的搜索框只有两处,connectors(目标)和 skills-multi-picker(已有自己的 42px !important 规则),所以没有任何站点依赖那条全局规则兜底。

放大镜手柄 right/bottom 那两行微调没问题,作用域本来就在 .connector-group-search-icon 里。


补充说明:这个 PR 的 base 落后 master 17 个 commit,所以 GitHub 上 diff 会显示 103 个文件(大部分是主干漂移),实际改动是 4 个文件 +239/-15。我本地基于最新 origin/master rebase 过,零冲突,patch-id 前后一致,bun run build rc=0,connector 相关三个测试文件 29/29 绿。

以上是自动评审的初步意见,可能有理解偏差,最终以维护者审阅为准。第 2 点如果你有别的考虑(比如是想统一所有搜索框的观感)也完全可以讨论,我这边只是从「影响面最小」的角度给个建议。辛苦了!

@deepcoldy

Copy link
Copy Markdown
Owner

补充更正一处 —— 上一条评论第 2 点里我写了「误伤 8 处」,但表格只列出了 7 个站点名,数字和清单对不上,是我漏列了一行,抱歉。补上:

sessions-page.tsx:635  .filter-cli-search           11px → 32px   ⚠️(漏列的这个)
sessions-page.tsx:806  .sessions-filter-cli-search  11px → 32px   ⚠️(已列)

这是 sessions 页里两个不同的 CLI 筛选搜索框::806 在筛选栏 .sessions-filter-cli 容器里,:635<details class="filter-cli"> 下拉弹层的 .filter-cli-head 里,class 名不同。我实测了 :635details.filter-cli > .filter-cli-pop > .filter-cli-head > input.filter-cli-search,standalone 和套在 form.sessions-filters 下各量一遍):master 11px → PR 32px → 作用域方案 11px,与其余误伤点同构。它自身规则只有 (0,1,0),压不过全局规则的 (0,8,1)

所以完整清单是 目标 1 处 + 误伤 8 处,8 处里 sessions 页占两个(:635 / :806)。

有一点需要说明清楚,免得你去核的时候困惑::635 所在的 CliFilterGroup 组件目前在 dashboard 里没有任何渲染入口——全仓引用它的只有 test/dashboard-sessions-ui.test.tssessions-page.tsx 内部也没有调用它。所以这一处当前不会被用户看到,严格说是「潜在误伤」而非「线上可见误伤」。真正线上可见的是另外 7 处。我把它列出来是因为它同样落在全局规则的命中面里,将来这个组件一旦接回去就会跟着歪;但如果你只按「用户现在能看到的」口径衡量,那就是 7 处。

这不影响第 2 点的建议本身——收窄作用域的改法对这 8 处(无论可见与否)都是一次性解决,实测除目标站点外其余采样点逐点不变。

第 1 点(botIds 删不掉)不受此更正影响,结论不变。再次感谢,也为上一条的数字与清单不一致致歉。

@pigeoner
pigeoner force-pushed the fix/dashboard-webhook-target-bots branch from 0f46a62 to d3ea8f1 Compare September 8, 2026 03:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants