Files
c020627 2fd55b34f3 fix: read user-edited config files as utf-8-sig (BOM tolerance)
Windows Notepad / PowerShell write UTF-8 with a BOM by default, and the JSON /
txt files CowAgent asks users to edit by hand are exactly the ones that get
re-saved that way. Plain `utf-8` turns the leading BOM into a `\ufeff`
character, and what happens next depends on the reader:

- `plugins/*/config.json` (godcmd's is created on first run for the operator
  to fill in): `json.load` raises "Unexpected UTF-8 BOM", the plugin's
  `__init__` fails, and `PluginManager.activate_plugins` answers a failed init
  by disabling the plugin and **persisting** `enabled=false` -- so it stayed
  off across restarts even after the file was put right.
- `banwords.txt`: the first line is read as `\ufeffword`, `str.strip()` does
  not remove U+FEFF (it is not whitespace), so the word is registered with the
  BOM glued to it and can never match. No error -- the first word of the list
  is silently unfiltered.
- `skills_config.json`: the read helper swallows the error and answers `{}`,
  and `cow skill list` rebuilds the file assuming `enabled: True` -- a skill
  the user had turned off comes back on, silently.
- `config.json` in `cow backup`: same swallow, so every caller treats the
  install as unconfigured and `cow backup` archives `~/cow` instead of the
  configured `agent_workspace`. `restore` hits the same read on the copy inside
  the archive, where it is not caught and aborts the restore.
- `mcp.json`: `_read_mcp_file` wraps it as `McpConfigError("mcp.json is not
  valid JSON: ...")`, which names the JSON rather than the BOM, so the file
  looks fine in an editor.

Apply the convention `agent/admin.py` already documents -- "utf-8-sig tolerates
a UTF-8 BOM (e.g. config.json edited with Windows Notepad / PowerShell)" -- at
every one of those read sites, replacing what were five separate PRs (#3419,
#3421, #3422, #3423) with one change.

`Plugin.load_config` also restores the `if os.path.exists(plugin_config_path)`
check inside the `if not plugin_conf` block that assigns `plugin_config_path`:
pulled out of it, the check ran on a name that was never assigned whenever
`pconf()` already returned a config, i.e. for every plugin with an entry in
`plugins/config.json`, and `load_config` raised `UnboundLocalError` -- the same
"plugin gets disabled" outcome the change was meant to avoid.
`tests/test_plugin_config_defaults.py` covers that case; it fails on the
previous revision with `UnboundLocalError: cannot access local variable
'plugin_config_path' where it is not associated with a value`.
2026-10-01 15:26:12 +08:00
..
2023-04-17 15:41:29 +08:00
2023-04-17 01:01:02 +08:00
2023-03-14 17:30:30 +08:00
2023-04-17 01:01:02 +08:00
2023-04-12 20:16:21 +08:00

插件描述

简易的敏感词插件,暂不支持分词,请自行导入词库到插件文件夹中的banwords.txt,每行一个词,一个参考词库是1。

使用前将config.json.template复制为config.json,并自行配置。

目前插件对消息的默认处理行为有如下两种:

  • ignore : 无视这条消息。
  • replace : 将消息中的敏感词替换成"*",并回复违规。
    "action": "replace",  
    "reply_filter": true,
    "reply_action": "ignore"

在以上配置项中:

  • action: 对用户消息的默认处理行为
  • reply_filter: 是否对ChatGPT的回复也进行敏感词过滤
  • reply_action: 如果开启了回复过滤,对回复的默认处理行为

致谢

搜索功能实现来自https://github.com/toolgood/ToolGood.Words