diff --git a/agent_reach/channels/twitter.py b/agent_reach/channels/twitter.py index 8c8869b4..90e37b25 100644 --- a/agent_reach/channels/twitter.py +++ b/agent_reach/channels/twitter.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- """Twitter/X — check if twitter-cli or bird CLI is available.""" -from .base import Channel from agent_reach.probe import probe_command +from .base import Channel + class TwitterChannel(Channel): name = "twitter" @@ -75,6 +76,12 @@ def _check_twitter_cli(self): output = probe.output if "ok: true" in output: + if "failed to init clienttransaction" in output.lower(): + return "warn", ( + "twitter-cli 已认证,读取、时间线和用户查询可用;" + "但搜索初始化失败,SearchTimeline 当前会返回 HTTP 404。" + "优先改用 OpenCLI(复用浏览器登录态),或升级 twitter-cli 后重试" + ) return "ok", ( "twitter-cli 完整可用(搜索、读推文、时间线、长文/Article、" "用户查询、Thread)" diff --git a/agent_reach/skill/references/social.md b/agent_reach/skill/references/social.md index 1bd5303c..55931e36 100644 --- a/agent_reach/skill/references/social.md +++ b/agent_reach/skill/references/social.md @@ -97,9 +97,11 @@ twitter likes ### search 失败时的重试链(按序执行,成功即停) 1. 直接重试一次(偶发失败常见):`twitter search "query" -n 10` -2. 升级后再试:`pipx upgrade twitter-cli && twitter search "query" -n 10` +2. 按实际安装器升级后再试:`uv tool upgrade twitter-cli || pipx upgrade twitter-cli`,然后重新执行搜索 3. 换 OpenCLI 备选(桌面,复用浏览器登录态):`opencli twitter search "query" -f yaml` -4. 都不行就改用 `twitter feed` / `twitter user-posts @somebody` 等稳定命令绕路 +4. 若环境有已登录 X 的浏览器控制工具,打开 + `https://x.com/search?q=URL_ENCODED_QUERY&src=typed_query&f=live` 读取结果 +5. 都不行就改用 `twitter feed` / `twitter user-posts @somebody` 等稳定命令绕路 ### 重要注意事项 @@ -111,6 +113,8 @@ twitter likes > > **OpenCLI 备选**: 桌面装了 OpenCLI 的话,`opencli twitter search/article/user-posts -f yaml` 全套可用(浏览器登录态,无需 cookie 环境变量)。 > +> **doctor 判定**: `twitter status` 可能在认证正常时仍输出 `Failed to init ClientTransaction`。这代表读取类命令可用、但搜索会返回 HTTP 404;`agent-reach doctor` 会把它标为降级,并继续寻找 OpenCLI 等可用后端。 +> > **输出格式**: 建议用 `--yaml` 或 `--json` 获得结构化输出,对 AI agent 更友好。 ## B站 / Bilibili diff --git a/tests/test_twitter_channel.py b/tests/test_twitter_channel.py index 0670a212..9d4f62f4 100644 --- a/tests/test_twitter_channel.py +++ b/tests/test_twitter_channel.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from unittest.mock import patch, Mock +from unittest.mock import Mock, patch from agent_reach.channels.twitter import TwitterChannel @@ -29,6 +29,30 @@ def test_check_twitter_cli_found_and_auth_ok(): assert channel.active_backend == "twitter-cli" +def test_client_transaction_failure_marks_search_degraded(): + """认证正常但 ClientTransaction 初始化失败 → 不得误报搜索完整可用。""" + channel = TwitterChannel() + with patch( + "shutil.which", + side_effect=lambda name: "/usr/local/bin/twitter" if name == "twitter" else None, + ), patch( + "subprocess.run", + return_value=_cp( + stdout="ok: true\nusername: testuser\n", + stderr=( + "WARNING twitter_cli.client: Failed to init ClientTransaction: " + "'NoneType' object has no attribute 'group'\n" + ), + returncode=0, + ), + ): + status, message = channel.check() + assert status == "warn" + assert "搜索初始化失败" in message + assert "HTTP 404" in message + assert channel.active_backend == "twitter-cli" + + def test_check_twitter_cli_found_auth_missing(): """twitter-cli found + not_authenticated → warn about auth.""" channel = TwitterChannel()