Skip to content

Commit 674bbc8

Browse files
massif-01ZhuLinsen
andcommitted
fix: add notification baseline diagnostics (ZhuLinsen#1200) (ZhuLinsen#1205)
Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
1 parent 3588a74 commit 674bbc8

20 files changed

Lines changed: 900 additions & 40 deletions

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,10 @@ AGENT_SKILLS=
459459
# 注册Server酱3账号并获取SendKey https://sc3.ft07.com/
460460
# SERVERCHAN3_SENDKEY=
461461
#
462+
# 【方式十一】AstrBot 配置
463+
# ASTRBOT_URL=
464+
# ASTRBOT_TOKEN= # 可选,用于需要 Bearer Token 的 AstrBot Webhook
465+
#
462466
# 【高级配置】消息长度限制(字节)
463467
# 超过限制会自动分批发送,一般无需修改
464468
# FEISHU_MAX_BYTES=20000 # 飞书限制约 20KB,默认 20000 字节

.github/workflows/daily_analysis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ jobs:
270270

271271
# 方式二:飞书 Webhook
272272
FEISHU_WEBHOOK_URL: ${{ secrets.FEISHU_WEBHOOK_URL }}
273+
FEISHU_WEBHOOK_SECRET: ${{ secrets.FEISHU_WEBHOOK_SECRET }}
274+
FEISHU_WEBHOOK_KEYWORD: ${{ vars.FEISHU_WEBHOOK_KEYWORD || secrets.FEISHU_WEBHOOK_KEYWORD }}
273275

274276
# 方式三:Telegram
275277
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
@@ -288,10 +290,13 @@ jobs:
288290

289291
# 方式六:PushPlus ⬅️ 新增!
290292
PUSHPLUS_TOKEN: ${{ secrets.PUSHPLUS_TOKEN }}
293+
PUSHPLUS_TOPIC: ${{ vars.PUSHPLUS_TOPIC || secrets.PUSHPLUS_TOPIC }}
291294

292295
# 方式七:自定义 Webhook(钉钉、Bark、自建服务等)
293296
CUSTOM_WEBHOOK_URLS: ${{ secrets.CUSTOM_WEBHOOK_URLS }}
294297
CUSTOM_WEBHOOK_BEARER_TOKEN: ${{ secrets.CUSTOM_WEBHOOK_BEARER_TOKEN }}
298+
CUSTOM_WEBHOOK_BODY_TEMPLATE: ${{ vars.CUSTOM_WEBHOOK_BODY_TEMPLATE || secrets.CUSTOM_WEBHOOK_BODY_TEMPLATE }}
299+
WEBHOOK_VERIFY_SSL: ${{ vars.WEBHOOK_VERIFY_SSL || secrets.WEBHOOK_VERIFY_SSL || 'true' }}
295300

296301
# 方式八:Discord
297302
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
1212
<!-- 新条目格式:- [类型] 描述(类型取值:新功能/改进/修复/文档/测试/chore)-->
1313
<!-- 每条独立一行追加到本段末尾,无需分类标题,合并时冲突最小 -->
1414
- [改进] 放宽 LiteLLM 依赖约束,保留 `>=1.80.10` 最低版本并显式排除 PyPI 事故版本 `1.82.7` / `1.82.8`,允许安装后续 1.x 修复版本。
15+
- [改进] 补齐通知渠道 P0 基线、Actions 映射与 `--check-notify` 只读诊断,完善 AstrBot 配置入口和通知回归快照。
1516
- [chore] 清理仓库根目录:移除误入库的 `.codex``review.md` 跟踪记录,将 smoke 测试入口迁移到 `scripts/`、环境检查脚本迁移为 `scripts/check_env.py`,并将 LiteLLM YAML 示例迁移到 `docs/examples/`
1617

1718
## [3.15.0] - 2026-05-05

docs/full-guide.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ daily_stock_analysis/
7171
7272
#### 通知渠道配置(可同时配置多个,全部推送)
7373

74+
> 通知渠道、minimal/advanced key 分层、Actions 映射与 `--check-notify` 诊断口径详见 [通知能力基线](notifications.md)
75+
7476
| Secret 名称 | 说明 | 必填 |
7577
|------------|------|:----:|
7678
| `WECHAT_WEBHOOK_URL` | 企业微信 Webhook URL | 可选 |
@@ -93,14 +95,16 @@ daily_stock_analysis/
9395
| `EMAIL_SENDER_NAME` | 发件人显示名称(默认:daily_stock_analysis股票分析助手) | 可选 |
9496
| `PUSHPLUS_TOKEN` | PushPlus Token([获取地址](https://www.pushplus.plus),国内推送服务) | 可选 |
9597
| `SERVERCHAN3_SENDKEY` | Server酱³ Sendkey([获取地址](https://sc3.ft07.com/),手机APP推送服务) | 可选 |
98+
| `ASTRBOT_URL` | AstrBot Webhook URL | 可选 |
99+
| `ASTRBOT_TOKEN` | AstrBot Bearer Token(可选) | 可选 |
96100
| `CUSTOM_WEBHOOK_URLS` | 自定义 Webhook(支持钉钉等,多个用逗号分隔) | 可选 |
97101
| `CUSTOM_WEBHOOK_BEARER_TOKEN` | 自定义 Webhook 的 Bearer Token(用于需要认证的 Webhook) | 可选 |
98102
| `CUSTOM_WEBHOOK_BODY_TEMPLATE` | 自定义 Webhook JSON body 模板,适配 AstrBot、NapCat、自建服务等特殊 payload | 可选 |
99103
| `WEBHOOK_VERIFY_SSL` | Webhook HTTPS 证书校验(默认 true)。设为 false 可支持自签名证书。警告:关闭有严重安全风险(MITM),仅限可信内网 | 可选 |
100104

101105
> *注:至少配置一个渠道,配置多个则同时推送
102106
>
103-
> 当前默认 `daily_analysis.yml` 只显式映射固定 Secret / Variable 名称,不会自动把 `STOCK_GROUP_1``EMAIL_GROUP_1` 这类任意编号变量导入运行环境。所以分组邮箱功能目前不适用于仓库自带默认 GitHub Actions workflow;它适用于本地 `.env`、Docker,或你自行显式扩展过 `env:` 映射的运行环境。
107+
> 当前默认 `daily_analysis.yml` 只显式映射固定 Secret / Variable 名称,不会自动把 `STOCK_GROUP_1``EMAIL_GROUP_1` 这类任意编号变量导入运行环境。所以分组邮箱功能目前不适用于仓库自带默认 GitHub Actions workflow;它适用于本地 `.env`、Docker,或你自行显式扩展过 `env:` 映射的运行环境。P0 已显式映射 `CUSTOM_WEBHOOK_BODY_TEMPLATE``WEBHOOK_VERIFY_SSL``FEISHU_WEBHOOK_SECRET``FEISHU_WEBHOOK_KEYWORD``PUSHPLUS_TOPIC``MARKDOWN_TO_IMAGE_CHANNELS``MERGE_EMAIL_NOTIFICATION` 仍作为行为开关留给后续阶段处理。
104108
105109
#### 推送行为配置
106110

@@ -216,6 +220,8 @@ daily_stock_analysis/
216220
217221
### 通知渠道配置
218222

223+
更多通知配置基线和诊断说明见 [通知能力基线](notifications.md)
224+
219225
| 变量名 | 说明 | 必填 |
220226
|--------|------|:----:|
221227
| `WECHAT_WEBHOOK_URL` | 企业微信机器人 Webhook URL | 可选 |
@@ -245,6 +251,8 @@ daily_stock_analysis/
245251
| `PUSHOVER_API_TOKEN` | Pushover API Token | 可选 |
246252
| `PUSHPLUS_TOKEN` | PushPlus Token(国内推送服务) | 可选 |
247253
| `SERVERCHAN3_SENDKEY` | Server酱³ Sendkey | 可选 |
254+
| `ASTRBOT_URL` | AstrBot Webhook URL | 可选 |
255+
| `ASTRBOT_TOKEN` | AstrBot Bearer Token(可选) | 可选 |
248256

249257
> 说明:默认 `daily_analysis` GitHub Actions workflow 只映射固定变量名,不会自动导入任意编号的 `STOCK_GROUP_N` / `EMAIL_GROUP_N`。因此分组邮箱目前仅在本地 `.env`、Docker 或其他已显式注入这些环境变量的运行环境中生效;若你要在自己的 GitHub Actions 中使用,需在 workflow 的 job `env:` 中逐组显式映射。
250258
@@ -652,6 +660,8 @@ crontab -e
652660

653661
## 通知渠道详细配置
654662

663+
通知渠道矩阵、minimal/advanced key 分层和 `--check-notify` 诊断口径见 [通知能力基线](notifications.md)。
664+
655665
### 企业微信
656666

657667
1. 在企业微信群聊中添加"群机器人"

docs/full-guide_EN.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ Go to your forked repo → `Settings` → `Secrets and variables` → `Actions`
7171
7272
#### Notification Channels (Multiple can be configured, all will receive notifications)
7373

74+
> The P0 notification baseline, minimal/advanced key split, Actions mapping, and `--check-notify` CLI behavior are tracked in [Notification Baseline](notifications.md). A complete English notification topic remains a later follow-up.
75+
7476
| Secret Name | Description | Required |
7577
|------------|------|:----:|
7678
| `WECHAT_WEBHOOK_URL` | WeChat Work Webhook URL | Optional |
@@ -94,14 +96,16 @@ Go to your forked repo → `Settings` → `Secrets and variables` → `Actions`
9496
| `STOCK_GROUP_N` / `EMAIL_GROUP_N` | Email routing groups (Issue #268): `STOCK_GROUP_N` should be a subset of `STOCK_LIST`; affects email recipients only, not analysis scope or other channels | Optional |
9597
| `PUSHPLUS_TOKEN` | PushPlus Token ([Get here](https://www.pushplus.plus), Chinese push service) | Optional |
9698
| `SERVERCHAN3_SENDKEY` | ServerChan v3 Sendkey ([Get here](https://sc3.ft07.com/), mobile app push service) | Optional |
99+
| `ASTRBOT_URL` | AstrBot Webhook URL | Optional |
100+
| `ASTRBOT_TOKEN` | Optional AstrBot Bearer Token | Optional |
97101
| `CUSTOM_WEBHOOK_URLS` | Custom Webhook (supports DingTalk, etc., comma-separated) | Optional |
98102
| `CUSTOM_WEBHOOK_BEARER_TOKEN` | Bearer Token for custom webhooks (for authenticated webhooks) | Optional |
99103
| `CUSTOM_WEBHOOK_BODY_TEMPLATE` | Custom Webhook JSON body template for AstrBot, NapCat, or self-hosted services with special payloads | Optional |
100104
| `WEBHOOK_VERIFY_SSL` | Verify Webhook HTTPS certificates (default true). Set to false for self-signed certs. WARNING: Disabling has serious security risk (MITM), use only on trusted internal networks | Optional |
101105

102106
> *Note: Configure at least one channel; multiple channels will all receive notifications
103107
>
104-
> The default `daily_analysis.yml` in this repository only exports fixed Secret / Variable names. Arbitrary numbered env vars such as `STOCK_GROUP_1` and `EMAIL_GROUP_1` are not auto-injected into the job, so grouped email routing is not available in the stock workflow unless you explicitly extend the workflow's `env:` mapping in your own fork.
108+
> The default `daily_analysis.yml` in this repository only exports fixed Secret / Variable names. Arbitrary numbered env vars such as `STOCK_GROUP_1` and `EMAIL_GROUP_1` are not auto-injected into the job, so grouped email routing is not available in the stock workflow unless you explicitly extend the workflow's `env:` mapping in your own fork. P0 maps `CUSTOM_WEBHOOK_BODY_TEMPLATE`, `WEBHOOK_VERIFY_SSL`, `FEISHU_WEBHOOK_SECRET`, `FEISHU_WEBHOOK_KEYWORD`, and `PUSHPLUS_TOPIC`; `MARKDOWN_TO_IMAGE_CHANNELS` and `MERGE_EMAIL_NOTIFICATION` remain behavior toggles for a later phase.
105109
106110
#### Push Behavior Configuration
107111

@@ -192,6 +196,8 @@ Default schedule: Every weekday at **18:00 (Beijing Time)** automatic execution.
192196
193197
### Notification Channel Configuration
194198

199+
For the P0 notification baseline and diagnostics, see [Notification Baseline](notifications.md).
200+
195201
| Variable | Description | Required |
196202
|--------|------|:----:|
197203
| `WECHAT_WEBHOOK_URL` | WeChat Work Bot Webhook URL | Optional |
@@ -221,6 +227,8 @@ Default schedule: Every weekday at **18:00 (Beijing Time)** automatic execution.
221227
| `PUSHOVER_API_TOKEN` | Pushover API Token | Optional |
222228
| `PUSHPLUS_TOKEN` | PushPlus Token (Chinese push service) | Optional |
223229
| `SERVERCHAN3_SENDKEY` | ServerChan v3 Sendkey | Optional |
230+
| `ASTRBOT_URL` | AstrBot Webhook URL | Optional |
231+
| `ASTRBOT_TOKEN` | Optional AstrBot Bearer Token | Optional |
224232

225233
> Note: the default `daily_analysis` GitHub Actions workflow only maps fixed variable names. It does not automatically import arbitrary numbered variables such as `STOCK_GROUP_N` / `EMAIL_GROUP_N`. This feature therefore works in local `.env`, Docker, or any runtime where you explicitly inject those variables.
226234
@@ -550,6 +558,8 @@ crontab -e
550558

551559
## Notification Channel Configuration
552560

561+
The P0 notification channel matrix and `--check-notify` CLI details are documented in [Notification Baseline](notifications.md).
562+
553563
### WeChat Work
554564

555565
1. Add "Group Bot" in WeChat Work group chat

docs/notifications.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# 通知能力基线
2+
3+
本文档记录通知能力 P0 基线:渠道、配置 key、GitHub Actions 映射、Web 设置元数据和 CLI 诊断口径。P0 只做基线与只读诊断,不包含 Web 一键测试、渠道路由、降噪、模板产品化等后续 Phase 能力。
4+
5+
## 渠道基线
6+
7+
| 渠道 | 类型 | Minimal key | Advanced key | 说明 |
8+
| --- | --- | --- | --- | --- |
9+
| 企业微信 | 静态配置 | `WECHAT_WEBHOOK_URL` | `WECHAT_MSG_TYPE` | 配置后参与批量通知发送 |
10+
| 飞书 Webhook | 静态配置 | `FEISHU_WEBHOOK_URL` | `FEISHU_WEBHOOK_SECRET`, `FEISHU_WEBHOOK_KEYWORD` | `FEISHU_APP_ID` / `FEISHU_APP_SECRET` 不会单独开启群 Webhook 推送 |
11+
| Telegram | 静态配置 | `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID` | `TELEGRAM_MESSAGE_THREAD_ID` | token 与 chat id 必须同时存在 |
12+
| 邮件 | 静态配置 | `EMAIL_SENDER`, `EMAIL_PASSWORD` | `EMAIL_RECEIVERS`, `EMAIL_SENDER_NAME` | `EMAIL_RECEIVERS` 留空时发给自己 |
13+
| Pushover | 静态配置 | `PUSHOVER_USER_KEY`, `PUSHOVER_API_TOKEN` | - | 两个 key 必须同时存在 |
14+
| PushPlus | 静态配置 | `PUSHPLUS_TOKEN` | `PUSHPLUS_TOPIC` | `PUSHPLUS_TOPIC` 仅在 token 存在时生效 |
15+
| Server酱3 | 静态配置 | `SERVERCHAN3_SENDKEY` | - | 手机 App 推送 |
16+
| 自定义 Webhook | 静态配置 | `CUSTOM_WEBHOOK_URLS` | `CUSTOM_WEBHOOK_BEARER_TOKEN`, `CUSTOM_WEBHOOK_BODY_TEMPLATE`, `WEBHOOK_VERIFY_SSL` | 支持多个 URL,逗号分隔 |
17+
| Discord | 静态配置 | `DISCORD_WEBHOOK_URL``DISCORD_BOT_TOKEN` + `DISCORD_MAIN_CHANNEL_ID` | `DISCORD_INTERACTIONS_PUBLIC_KEY` | Webhook 与 Bot 均可启用发送 |
18+
| Slack | 静态配置 | `SLACK_WEBHOOK_URL``SLACK_BOT_TOKEN` + `SLACK_CHANNEL_ID` | - | Bot 优先用于文本与图片同频道发送 |
19+
| AstrBot | 静态配置 | `ASTRBOT_URL` | `ASTRBOT_TOKEN`, `WEBHOOK_VERIFY_SSL` | `ASTRBOT_TOKEN` 可选 |
20+
| `UNKNOWN` | 兜底枚举 | - | - | 仅为未知渠道兜底,不由静态环境变量启用 |
21+
| 钉钉会话 | 运行时上下文 | - | - | 从来源消息上下文提取,无法仅由 `.env` 静态判断 |
22+
| 飞书会话 | 运行时上下文 | - | - | 从来源消息上下文提取,无法仅由 `.env` 静态判断 |
23+
24+
## Minimal / Advanced 分层
25+
26+
- Minimal key:足以启用一个通知渠道的最小配置。
27+
- Advanced key:只影响认证、安全、格式、线程、群组、证书校验或展示行为,不能单独启用渠道。
28+
- P0 不新增路由、降噪或发送策略语义;相关配置如未来引入,应先更新本文档、`.env.example`、Web 元数据与回归测试。
29+
30+
## GitHub Actions 映射
31+
32+
仓库自带 `.github/workflows/daily_analysis.yml` 只显式导入固定变量名。P0 补齐以下已存在发送链路所需的映射:
33+
34+
- `CUSTOM_WEBHOOK_BODY_TEMPLATE`
35+
- `WEBHOOK_VERIFY_SSL`
36+
- `FEISHU_WEBHOOK_SECRET`
37+
- `FEISHU_WEBHOOK_KEYWORD`
38+
- `PUSHPLUS_TOPIC`
39+
40+
P0 不映射 `MARKDOWN_TO_IMAGE_CHANNELS``MERGE_EMAIL_NOTIFICATION`。它们是发送形态或聚合行为开关,不是渠道凭证;在 Actions 中自动开始读取同名 Secret/Variable 会引入行为变化,留到后续专门阶段处理。
41+
42+
## CLI 诊断
43+
44+
```bash
45+
python main.py --check-notify
46+
```
47+
48+
该命令只读配置,不发送通知,不写入 `.env`。它会在配置加载和日志初始化后立即执行,完成后直接退出,不再进入 Web、调度、大盘复盘或默认分析流程。
49+
50+
- 返回码 `0`:没有 error 级诊断。
51+
- 返回码 `1`:存在 error,例如 0 个静态通知渠道已配置,或成对 key 只配置了一半。
52+
53+
## 场景占位
54+
55+
- Local:优先使用 `.env`,可用 `python main.py --check-notify` 做本地诊断。
56+
- Docker:配置来源与本地一致,需确保容器环境变量已注入。
57+
- GitHub Actions:只会读取 workflow `env:` 中显式映射的 Secret/Variable。
58+
- Desktop:当前 P0 仅补 Web 设置元数据和诊断口径,不新增桌面端通知测试入口。

main.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ def parse_arguments() -> argparse.Namespace:
213213
python main.py --dry-run # 仅获取数据,不进行 AI 分析
214214
python main.py --stocks 600519,000001 # 指定分析特定股票
215215
python main.py --no-notify # 不发送推送通知
216+
python main.py --check-notify # 检查通知配置,不发送通知
216217
python main.py --single-notify # 启用单股推送模式(每分析完一只立即推送)
217218
python main.py --schedule # 启用定时任务模式
218219
python main.py --market-review # 仅运行大盘复盘
@@ -243,6 +244,12 @@ def parse_arguments() -> argparse.Namespace:
243244
help='不发送推送通知'
244245
)
245246

247+
parser.add_argument(
248+
'--check-notify',
249+
action='store_true',
250+
help='只读检查通知渠道配置,不发送通知'
251+
)
252+
246253
parser.add_argument(
247254
'--single-notify',
248255
action='store_true',
@@ -748,6 +755,16 @@ def main() -> int:
748755
for warning in warnings:
749756
logger.warning(warning)
750757

758+
if getattr(args, "check_notify", False):
759+
from src.services.notification_diagnostics import (
760+
format_notification_diagnostics,
761+
run_notification_diagnostics,
762+
)
763+
764+
result = run_notification_diagnostics(config)
765+
print(format_notification_diagnostics(result))
766+
return 0 if result.ok else 1
767+
751768
# 解析股票列表(统一为大写 Issue #355)
752769
stock_codes = None
753770
if args.stocks:

src/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,7 @@ def _has_runtime_source_for_model(model: str) -> bool:
23962396
or self.pushplus_token
23972397
or self.serverchan3_sendkey
23982398
or self.custom_webhook_urls
2399+
or self.astrbot_url
23992400
or (self.discord_bot_token and self.discord_main_channel_id)
24002401
or self.discord_webhook_url
24012402
or self.slack_webhook_url

src/core/config_registry.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,37 @@
12271227
"validation": {},
12281228
"display_order": 45,
12291229
},
1230+
"ASTRBOT_URL": {
1231+
"title": "AstrBot URL",
1232+
"description": "AstrBot webhook endpoint URL.",
1233+
"category": "notification",
1234+
"data_type": "string",
1235+
"ui_control": "password",
1236+
"is_sensitive": True,
1237+
"is_required": False,
1238+
"is_editable": True,
1239+
"default_value": None,
1240+
"options": [],
1241+
"validation": {
1242+
"item_type": "url",
1243+
"allowed_schemes": ["http", "https"],
1244+
},
1245+
"display_order": 46,
1246+
},
1247+
"ASTRBOT_TOKEN": {
1248+
"title": "AstrBot Token",
1249+
"description": "Optional AstrBot bearer token.",
1250+
"category": "notification",
1251+
"data_type": "string",
1252+
"ui_control": "password",
1253+
"is_sensitive": True,
1254+
"is_required": False,
1255+
"is_editable": True,
1256+
"default_value": None,
1257+
"options": [],
1258+
"validation": {},
1259+
"display_order": 47,
1260+
},
12301261
"SINGLE_STOCK_NOTIFY": {
12311262
"title": "Single Stock Notify",
12321263
"description": "Push immediately after each single stock analysis instead of batching all results together.",

0 commit comments

Comments
 (0)