fix: 修复飞书配置层级问题,确保 dmPolicy 正确生效

- 修复 configureFeishuAccount 函数,同时设置顶层和账户级配置
- 原因:default 账户不会合并 accounts.default 的覆盖值
- 新增 --allow-from 和 --group-policy 参数
- 默认 dmPolicy 改为 allowlist(安全优先)
- 更新 SKILL.md 文档,添加配置层级说明
- 新增 FIXES.md 记录修复详情
This commit is contained in:
openclaw
2026-03-17 22:17:10 +08:00
parent dab90e9c58
commit b5bf96e882
3 changed files with 203 additions and 10 deletions

99
FIXES.md Normal file
View File

@@ -0,0 +1,99 @@
# agent-creator-with-binding 修复说明
## 修复的问题
### 问题 1配置层级错误导致 dmPolicy 不生效
**原因:**
- Skill 只在 `channels.feishu.accounts.<accountId>` 中设置 `dmPolicy``allowFrom`
- OpenClaw 的 `getLarkAccount` 函数在处理 `accountId === "default"` 时,**不会合并** `accounts.default` 中的覆盖值
- 导致 default 账户读取不到 dmPolicy 配置,始终使用默认的 `pairing` 模式
**表现:**
- 用户已在配置中设置 `dmPolicy: allowlist`
- 但机器人仍然回复配对提示,而不是拒绝访问
**修复:**
```javascript
// 如果是第一个账户或 default 账户,设置顶层配置
if (isFirstAccount || isDefaultBot) {
config.channels.feishu.dmPolicy = options.dmPolicy || 'allowlist';
config.channels.feishu.allowFrom = options.allowFrom || ['*'];
config.channels.feishu.groupPolicy = options.groupPolicy || 'open';
config.channels.feishu.groupAllowFrom = options.groupAllowFrom || [];
}
```
---
## 正确的配置结构
```json
{
"channels": {
"feishu": {
"enabled": true,
"appId": "cli_a93dc207e1f89bcb",
"appSecret": "xxx",
"dmPolicy": "allowlist",
"allowFrom": ["ou_xxx", "ou_yyy"],
"groupPolicy": "open",
"groupAllowFrom": [],
"accounts": {
"default": {
"appId": "cli_a93dc207e1f89bcb",
"appSecret": "xxx",
"dmPolicy": "allowlist",
"allowFrom": ["ou_xxx", "ou_yyy"]
},
"coding-expert-bot": {
"appId": "cli_a9320c94f23a1bd6",
"appSecret": "yyy",
"dmPolicy": "allowlist",
"allowFrom": ["ou_xxx", "ou_yyy"]
}
}
}
}
}
```
---
## 新增参数
- `--allow-from`: 白名单用户,逗号分隔(如:`ou_xxx,ou_yyy`
- `--group-policy`: 群聊策略open/allowlist/disabled默认 open
---
## 默认行为变更
| 参数 | 修复前默认值 | 修复后默认值 | 说明 |
|------|-------------|-------------|------|
| `--dm-policy` | `open` | `allowlist` | 安全优先,默认白名单模式 |
| `--allow-from` | `['*']` | 从顶层配置继承 | 确保一致性 |
---
## 验证方法
```bash
# 1. 创建新 Agent 后检查配置
openclaw agents list --bindings
# 2. 查看飞书配置
cat ~/.openclaw/openclaw.json | jq '.channels.feishu | {dmPolicy, allowFrom, accounts}'
# 3. 测试机器人响应
# 向机器人发送消息,确认不会收到配对提示(如果已配置 allowlist
```
---
## 相关文件
- `/home/admin/.openclaw/workspace/skills/agent-creator-with-binding/index.js` - 主要修复
- `/home/admin/.openclaw/workspace/skills/agent-creator-with-binding/SKILL.md` - 文档更新

View File

@@ -149,10 +149,56 @@ openclaw skills run agent-creator-with-binding -- \
| --account-id | ❌ | 飞书账户 ID现有机器人时需要 |
| --chat-id | ❌ | 群聊 ID群聊绑定时需要 |
| --bot-name | ❌ | 机器人名称 |
| --dm-policy | ❌ | DM 策略open/pairing/allowlist |
| --dm-policy | ❌ | DM 策略:allowlist/open/pairing(默认 allowlist |
| --allow-from | ❌ | 白名单用户逗号分隔ou_xxx,ou_yyy |
| --group-policy | ❌ | 群聊策略open/allowlist/disabled默认 open |
| --skip-confirm | ❌ | 跳过确认 |
| --skip-restart | ❌ | 跳过重启 |
## 配置层级说明
**⚠️ 重要:** 飞书配置必须同时设置顶层和账户级配置!
```json
{
"channels": {
"feishu": {
// ★ 顶层配置(必须设置!)
// 原因default 账户不会合并 accounts.default 的覆盖值
"dmPolicy": "allowlist",
"allowFrom": ["ou_xxx", "ou_yyy"],
"groupPolicy": "open",
"groupAllowFrom": [],
"accounts": {
// 账户级配置(可覆盖顶层设置)
"default": {
"appId": "cli_xxx",
"appSecret": "xxx",
"dmPolicy": "allowlist", // 继承顶层或覆盖
"allowFrom": ["ou_xxx"] // 继承顶层或覆盖
},
"bot-other": {
"appId": "cli_yyy",
"appSecret": "yyy",
"dmPolicy": "open" // 可独立设置
}
}
}
}
}
```
**修复前的问题:**
- 只在 `accounts.<accountId>` 中设置 dmPolicy
- `default` 账户读取不到配置(代码 bug
- 导致配对提示而不是拒绝访问
**修复后的行为:**
- 自动设置顶层 `channels.feishu.dmPolicy`
- 同时设置账户级配置(可覆盖)
- 确保所有账户(包括 default正确继承
## 配置变更
执行后会修改:

View File

@@ -379,19 +379,44 @@ function configureFeishuAccount(options) {
const config = loadConfig();
// 确保 channels.feishu.accounts 存在
// 确保 channels.feishu 结构存在
if (!config.channels) config.channels = {};
if (!config.channels.feishu) config.channels.feishu = { enabled: true };
if (!config.channels.feishu.accounts) config.channels.feishu.accounts = {};
// 添加账户
// ★ 重要:顶层配置必须设置 dmPolicy 和 allowFrom
// 原因:当 accountId === "default" 时getLarkAccount 不会合并 accounts.default 的覆盖值
// 所以顶层 channels.feishu 必须有 dmPolicy 和 allowFrom确保 default 账户正确继承
// 如果是第一个账户或者是 default 账户,设置顶层配置
const isDefaultBot = options.accountId === 'default' || options.accountId.startsWith('bot-');
const existingAccounts = Object.keys(config.channels.feishu.accounts);
const isFirstAccount = existingAccounts.length === 0;
if (isFirstAccount || isDefaultBot) {
// 设置顶层 dmPolicy 和 allowFrom默认 allowlist白名单用户
config.channels.feishu.dmPolicy = options.dmPolicy || 'allowlist';
config.channels.feishu.allowFrom = options.allowFrom || ['*'];
config.channels.feishu.groupPolicy = options.groupPolicy || 'open';
config.channels.feishu.groupAllowFrom = options.groupAllowFrom || [];
log.success(`已设置顶层飞书配置dmPolicy=${config.channels.feishu.dmPolicy}`);
}
// 添加账户级配置
config.channels.feishu.accounts[options.accountId] = {
appId: options.appId,
appSecret: options.appSecret,
botName: options.botName || `${options.agentName}机器人`,
dmPolicy: options.dmPolicy || 'open',
allowFrom: ['*'],
enabled: true
enabled: true,
domain: 'feishu',
connectionMode: 'websocket',
requireMention: true,
streaming: true,
// 账户级配置可以覆盖顶层设置
dmPolicy: options.dmPolicy || config.channels.feishu.dmPolicy || 'allowlist',
allowFrom: options.allowFrom || config.channels.feishu.allowFrom || ['*'],
groupPolicy: options.groupPolicy || config.channels.feishu.groupPolicy || 'open',
groupAllowFrom: options.groupAllowFrom || config.channels.feishu.groupAllowFrom || []
};
if (saveConfig(config)) {
@@ -582,7 +607,24 @@ async function interactiveMode() {
options.accountId = await question(`账户 ID默认bot-${agentId}: `) || `bot-${agentId}`;
options.botName = await question(`机器人名称(默认:${agentName}机器人): `) || `${agentName}机器人`;
options.dmPolicy = await question(`DM 策略open/pairing/allowlist默认 open: `) || 'open';
// DM 策略
console.log('\nDM 策略说明:');
console.log(' - allowlist: 仅允许白名单用户私聊(推荐,安全)');
console.log(' - open: 允许所有用户私聊');
console.log(' - pairing: 需要配对码才能访问');
const dmPolicy = await question(`DM 策略allowlist/open/pairing默认 allowlist: `) || 'allowlist';
options.dmPolicy = dmPolicy;
// 白名单用户(仅当 allowlist 时需要)
if (dmPolicy === 'allowlist') {
console.log('\n白名单用户说明');
console.log(' - 输入用户 open_id格式ou_xxx');
console.log(' - 多个用户用逗号分隔');
console.log(' - 留空则允许所有人(不推荐)');
const allowFromInput = await question('白名单用户(逗号分隔,默认:*: ') || '*';
options.allowFrom = allowFromInput.split(',').map(s => s.trim()).filter(Boolean);
}
} else {
// 列出飞书账户供选择
log.info('可用飞书账户:');
@@ -600,7 +642,8 @@ async function interactiveMode() {
options.appSecret = appSecret;
options.accountId = await question(`账户 ID默认bot-${agentId}: `) || `bot-${agentId}`;
options.botName = await question(`机器人名称(默认:${agentName}机器人): `) || `${agentName}机器人`;
options.dmPolicy = 'open';
options.dmPolicy = 'allowlist';
options.allowFrom = ['*'];
} else {
accountIds.forEach((id, index) => {
console.log(` ${index + 1}. ${id} (${accounts[id].botName || '未命名'})`);
@@ -742,7 +785,9 @@ ${colors.bold}选项:${colors.reset}
--account-id <id> 飞书账户 ID
--chat-id <id> 群聊 ID群聊绑定时需要
--bot-name <name> 机器人名称
--dm-policy <policy> DM 策略open/pairing/allowlist
--dm-policy <policy> DM 策略:allowlist/open/pairing(默认 allowlist
--allow-from <users> 白名单用户逗号分隔ou_xxx,ou_yyy
--group-policy <policy> 群聊策略open/allowlist/disabled默认 open
--skip-confirm 跳过确认
--skip-restart 跳过重启
@@ -789,7 +834,10 @@ ${colors.bold}示例:${colors.reset}
appSecret: options.appsecret,
accountId: options.accountid || `bot-${options.agentid}`,
botName: options.botname,
dmPolicy: options.dmpolicy || 'open',
dmPolicy: options.dmpolicy || 'allowlist',
allowFrom: options.allowfrom ? options.allowfrom.split(',').map(s => s.trim()) : undefined,
groupPolicy: options.grouppolicy || 'open',
groupAllowFrom: options.groupallowfrom ? options.groupallowfrom.split(',').map(s => s.trim()) : undefined,
chatId: options.chatid
};