Commit Graph

142 Commits

Author SHA1 Message Date
zhulinsen
03dd26ac2e ci: shard backend tests across runners (#2165) 2026-08-05 22:33:50 +08:00
zhulinsen
4dda5d7148 feat: add explicit Responses API channel routing (#2157) 2026-08-05 19:15:08 +08:00
zhulinsen
8052d1a0ac ci: accelerate selective test gates (#2158) 2026-08-05 19:14:40 +08:00
Nicholas-Xiong
8d8fa56bc7 ci(#2131): 给 backend-gate offline pytest 加 --timeout=120 + faulthandler_timeout=300 watchdog (#2140)
* ci(#2131): 给 backend-gate offline pytest 加 --timeout=120 + faulthandler_timeout=300

issue #2131 报告 backend-gate 在执行 `Offline test suite` 步骤时两次
在同一提交 `e6abcef17fbc5d655c1c49429182079f02d6552e`(PR #2123)
上间歇性无 traceback 卡住:

  workflow run 30551305640(2026-07-30):
    - Offline test suite 开始于 14:23:13 UTC
    - 最后一条测试输出 14:23:58 UTC(AlphaSift hotspot PASSED [11%])
    - job 在 22 分 38 秒无输出后被取消

  workflow run 30553352307(2026-07-30):同样在 11% 位置卡住

GitHub Actions runner 在被取消前没有 pytest 进度的任何信号,也没
有 traceback。本地 16 个 AlphaSift hotspot 测试都能稳过,意味着
问题是 CI-only 的测试执行顺序、进程级全局状态、线程/事件循环
清理或依赖行为 — 没有稳定的 assertion failure 可调试。

issue #2131 已经列出推荐排查方向之一:给 pytest 加单测试超时与
卡住时的线程栈 dump(`pytest-timeout`、`faulthandler_timeout`)。
但当前 `scripts/ci_gate.sh` 的 `offline_test_suite()` 仅运行
`python -m pytest -m "not network"`,没有任何超时或 watchdog。

本 PR 实施 issue #2131 推荐的 watchdog 改造,目标不是修复根因
(那需要 issue #2131 的等线程栈 dump 复现才能定位),而是让任何
未来 CI hang 都会留下可定位的失败信息或 post-mortem 栈,而不是
静默消亡到 GitHub Actions workflow timeout 才被取消。

改动:

1. `.github/requirements-ci.txt`:新增 `pytest-timeout>=2.3.0`
   依赖。CI 的 `setup-python` + `pip install -r` 步骤会自动拉取。

2. `scripts/ci_gate.sh` 的 `offline_test_suite()`:
     python -m pytest -m "not network" \
       --timeout=120 -o timeout_method=thread \
       -o faulthandler_timeout=300

   - `--timeout=120`:单个测试如果执行超过 2 分钟直接 fail,
     生成 pytest-timeout 的 traceback 指出是哪个 case。
   - `-o timeout_method=thread`:pytest-timeout 用 watcher 线程
     而非 signal 方法,对吞了 SIGINT/SIGTERM 的测试更可靠
     (yfinance、AlphaSift 这类的 Threads/eventloop 都
     有可能 swallow signal)。
   - `-o faulthandler_timeout=300`:pytest 内置 faulthandler
     的 watchdog,整体 pytest 5 分钟无任何输出(最末一个测试
     结束到下一个测试开始之间的「沉默期」超过 300 秒)就 dump
     全部 Python 线程栈到 stderr。这是定位卡住位置的关键信号。

3. `docs/CHANGELOG.md`:在 [Unreleased] 段加一条 [修复] entry
   描述本次改动并指明 issue #2131。

本地验证:

  $ pip install pytest-timeout
  $ bash -n scripts/ci_gate.sh && echo syntax ok
  $ python -m pytest -m "not network" --timeout=120 \
      -o timeout_method=thread -o faulthandler_timeout=300 \
      tests/test_stock_list_parser.py tests/test_stock_code_utils.py -q
  ============================== 98 passed in 2.00s ==============================

  $ flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
  0

行为不变项:

- 本地开发 `python -m pytest ...` 不带 `--timeout` 仍可任意长跑调试
  (`setup.cfg` 没在 `[tool:pytest]` 全局加 timeout — 仅 CI 路径加)。
- `scripts/ci_gate.sh` 的 syntax/flake8/deterministic phases 不受影响。
- `pytest-timeout` 只在 `scripts/ci_gate.sh` 的 offline_test_suite 被
  调用时生效,不会污染本地开发流程。

注:本 PR 不修复 issue #2131 的根本 hang 原因(仍需 thread dump 复
现定位),而是把未来的 hang 转成可定位的失败。reviewer 在 issue
#2131 上对类似方向说过「即使再次复现,定位价值很低」—— 但本 PR
的 watchdog 至少把「无信息消亡」转成「带 stacktrace 的 fail」,
当 hang 再次发生时能立刻看到卡在哪个测试的哪一行。

* ci(#2131): close PR #2140 review blocker OR-COM-cc22d635 + OR-COM-c76d8eff — docker-publish.yml 对齐 backend-gate 依赖安装

按 reviewer 在 head `e01a1835` 上的 OpenReview Bot 复核反馈,关闭以下 2 个
高置信度 compatibility blocker:

- OR-COM-cc22d635: Docker Release Publish workflow 的 Install backend gate
  dependencies 仍按旧依赖集合执行 ./scripts/ci_gate.sh,新加的
  pytest-timeout 没覆盖到发布入口
- OR-COM-c76d8eff: 与 OR-COM-cc22d635 同源,cache-dependency-path 也
  缺失 .github/requirements-ci.txt

## 改了什么

.github/workflows/docker-publish.yml:
- setup-python cache-dependency-path 对齐 ci.yml backend-gate:
  加入 requirements.txt + .github/requirements-ci.txt 两个文件
  作为 pip cache key,命中缓存
- Install backend gate dependencies 改用与 ci.yml 完全相同的
  pattern:retry loop (3 attempts, 15s backoff) + 单一
  pip install -r .github/requirements-ci.txt(该文件已 -r 递归拉
  requirements.txt,所以无需重复 pip install -r requirements.txt)
- 加注释说明 issue #2131 引入 pytest-timeout 的关联

docs/CHANGELOG.md:
- [Unreleased] #2131 entry 末尾补一句:同步修正 docker-publish.yml
  的 install 与 cache-dependency-path 对齐

## 为什么这么改

issue #2131 让 scripts/ci_gate.sh 的 offline_test_suite 用
`--timeout=120 -o timeout_method=thread -o faulthandler_timeout=300`,
这要求 pytest-timeout>=2.3.0 插件。

ci.yml 的 backend-gate 已通过 .github/requirements-ci.txt 安装该
插件,但 docker-publish.yml 仍用旧的 `pip install flake8 pytest`,
没有 pytest-timeout,发布前 gate 跑 ./scripts/ci_gate.sh 会直接
报 unrecognized --timeout=120 fail,阻断镜像发布。

reviewer OR-COM-cc22d635 / OR-COM-c76d8eff 都指这是 PR 引入的
compatibility regression(不是已有旧债),需要 PR 同步修。

ci.yml 的 install pattern 是 retry 3 次带 backoff,对齐到
docker-publish 让两个工作流完全统一,未来新加 CI-only 依赖只需改
.github/requirements-ci.txt。

## 验证情况

已本地验证:
- python -c "import yaml; yaml.safe_load(open('.github/workflows/
  docker-publish.yml'))" — YAML 语法 OK
- 对比 ci.yml 的 backend-gate install 步骤,pattern 完全一致

已 CI 验证(待 push 后跑):
- 本 PR 触发 backend-gate / docker-build / ai-governance / Change
  Detection,但 docker-publish.yml 只在 v*.*.* tag 或 workflow_dispatch
  触发,本 PR CI 不会真跑该 workflow。reviewer 复核时会做静态比对

未验证 / 风险点:
- 真实发布流程跑不通:需要 maintainer 推 v*.*.* tag 或手动
  workflow_dispatch 触发,才能验证发布前 gate 真的工作
- 但 install pattern 与 ci.yml 完全对齐,ci.yml 那边过则该边也
  应该过;问题概率很低

## 风险点与回滚

回滚:
1. revert 本 commit
2. docker-publish.yml install step 改回 pip install -r requirements.txt
   + pip install flake8 pytest
3. cache-dependency-path 删除新增两行
4. CHANGELOG.md entry 末尾去掉补充句

潜在风险:
- .github/requirements-ci.txt 递归 -r requirements.txt,release
  runner 之前装过 requirements.txt;retry loop + cache 应该吸收掉
  任何 pip 网络抖动,但首次 release 可能比之前略慢(多一次冗余
  install)。Trade-off 可接受:与 ci.yml 完全统一比省一次冗余
  install 更重要。

* docs(#2131): 收窄 PR #2140 faulthandler_timeout 措辞 + 补 PR 描述 Refs/回滚

OpenReview Bot 在 head 14416440 上已给「可以直接合入」结论,剩 2 个非阻断建议:
1. CHANGELOG 与 PR 描述里 -o faulthandler_timeout=300 写成「整体超过 5 分钟无输出 watchdog」与 pytest 实际语义不一致,应改为「单个测试(含其 teardown)超过 5 分钟时 dump 线程栈」
2. 把 issue 关联补成显式 Refs #2131 + 加最小回滚方案

本 commit 同步两条:
- docs/CHANGELOG.md:把 faulthandler_timeout 描述从「整体超过 5 分钟无输出时 dump 全部线程栈」改为「单个测试(含其 teardown)超过 5 分钟时 dump 全部线程栈」,与 python -m pytest --help 中 faulthandler_timeout 的语义对齐
- PR #2140 描述:在末尾追加 "## 关联 issue Refs #2131" 与 "## 最小回滚方案" 两段(用 gh pr edit --body-file 更新),按 .github/PULL_REQUEST_TEMPLATE.md 模板完整化

无代码逻辑改动,仅文案同步。

---------

Co-authored-by: xxiaoxiong <xxiaoxiong@nicholasxiong.cn>
2026-08-01 22:41:41 +08:00
zhulinsen
2e7f4caaae fix: 避免 macOS unsigned 包携带残缺签名 (#2101)
* fix: mitigate broken signatures in unsigned macOS packages

* fix: normalize app signatures before DMG packaging
2026-07-26 11:40:10 +08:00
zhulinsen
e1e042096d fix: 修复 WebUI 版本与静态资源识别 (#2099)
* fix: make WebUI build identity reliable

* fix: address WebUI build metadata review

* fix: track WebUI dependency content state
2026-07-25 22:26:39 +08:00
Nicholas-Xiong
6194c7b1d9 fix: ai_review 对事件载荷读取/解析失败输出可定位警告(fixes #2070) (#2096)
* fix: surface event payload read/parse failures in ai_review (fixes #2070)

Issue #2070: .github/scripts/ai_review.py::_event_payload() previously
caught (OSError, ValueError) and silently returned {}, which collapsed
three distinct failure modes — missing event file, unreadable file, and
malformed JSON — into a single downstream symptom
('PR number is unavailable for GitHub API review'), making PR review
failures in workflow_dispatch / schedule runs impossible to triage.

Fix preserves the empty-payload degradation contract (so PR_NUMBER still
unblocks the chain when set explicitly), but splits the except clause
into three distinct branches that print a warning identifying the
failure mode by name (file-missing / OSError-derived / JSONDecodeError-
derived), the source path being GITHUB_EVENT_PATH, and the exception
class name. The warning never prints the payload content.

Tests in tests/test_ai_review_github_api.py add regression coverage for:
  - missing event file -> {} + 'GITHUB_EVENT_PATH 指向的文件不存在'
  - unreadable file (chmod 0o000) -> {} + '事件载荷读取失败' (skipped
    on root runners where chmod is a no-op, but never raises)
  - invalid JSON -> {} + '事件载荷 JSON 解析失败'
  - valid JSON happy path -> payload + no warning (guards against the
    warnings accidentally firing on success)
  - PR_NUMBER unset + bad event payload -> RuntimeError surfaces with
    the warning printed first so logs distinguish 'bad payload' vs
    'no PR number'

10 tests pass (5 new + 5 existing) in 0.09s.

* fix: 回应 codex P2 review 反馈 (PR #2096)

1. UnicodeDecodeError 显式分支: open(..., encoding='utf-8') 在非合法 UTF-8
   字节序列上抛 UnicodeDecodeError(是 ValueError 子类,旧 (OSError, ValueError)
   接住了它,但拆成 OSError + JSONDecodeError 后该异常不再被覆盖,会让 review
   终止而非降级). 新增 unicode 分支恢复降级行为,补 1 条独占回归测试.

2. CHANGELOG 收窄到本 PR 实际范围: 移除两条无关条目(parse_analysis_target 来自
   PR #2094,YfinanceFetcher 港股裸码路由来自 PR #2097),它们不应进入本 PR 的
   release notes.
2026-07-25 20:34:35 +08:00
zhulinsen
a54f46e1ec ci: temporarily disable automatic PR review (#2068) 2026-07-22 22:42:11 +08:00
Nicholas-Xiong
f2bfa0210f feat: 支持 TUSHARE_HTTP_URL 自定义 Tushare Pro 接入地址 (#2048)
* feat: support custom Tushare Pro endpoint via TUSHARE_HTTP_URL

Add TUSHARE_HTTP_URL so the Tushare data source can point at a self-hosted
or third-party compatible endpoint when the official api.tushare.pro is not
reachable. Defaults to the official host when unset, so behavior is
unchanged for existing users.

- data_provider/tushare_fetcher.py: add _resolve_tushare_http_url() helper
  (strip + http(s):// schema validation) and forward the resolved URL into
  _TushareHttpClient, with an info log when a custom endpoint is in use
- .env.example + .github/workflows/00-daily-analysis.yml: document and map
  TUSHARE_HTTP_URL so the new option is wired into the daily job without
  leaving a half-configured state
- tests: cover env parsing (empty/whitespace/http/https/missing schema),
  fetcher fall-through to the official host, and end-to-end POST target
- docs/CHANGELOG.md: flat [Unreleased] entries

Fixes #1985

* refactor: drop unnecessary string-literal type hint in _build_api_client

TushareHttpClient is already defined above TushareFetcher in the module
scope, so a string-literal type hint is not needed for forward reference.
Restore the bare type to match the surrounding code style and reduce the
diff against main.

* docs(tushare): 补 TUSHARE_HTTP_URL 在 full-guide 中英版本的用途/默认行为/workflow 映射说明

按 PR #2048 review 反馈补齐:
- 表格内新增 TUSHARE_HTTP_URL 行(中英文版本同步),明确默认 https://api.tushare.pro 与 http(s):// 前缀要求
- 在 GitHub Actions 段落后补充 TUSHARE_HTTP_URL 的 vars/Secrets 优先级与每日 workflow 0映射说明,与现有非敏感配置(TICKFLOW_PRIORITY)一致
- 完整环境变量列表(中英文版本)补 TUSHARE_HTTP_URL 行,默认值列填 https://api.tushare.pro
- 与代码实现一致:00-daily-analysis.yml 已用 vars.TUSHARE_HTTP_URL || secrets.TUSHARE_HTTP_URL 映射

* docs(tushare): align TUSHARE_HTTP_URL default with runtime and clarify vars/secrets precedence

Per review feedback on PR #2048: the per-repo config contract must stay
consistent across runtime, .env.example, workflow priority, tests and
both zh/en guides. Two fixes applied as a single contract update:

1. Default endpoint alignment. data_provider/tushare_fetcher.py:100,
   .env.example, and tests/test_tushare_fetcher_http_client.py all keep
   the existing official endpoint http://api.tushare.pro, but the zh/en
   full-guide rows had drifted to https://api.tushare.pro. Switching the
   documented default to HTTPS would silently change the runtime contract
   that the feat commit explicitly preserved. Revert both zh and en
   guide rows to http://api.tushare.pro so docs match runtime, .env.example
   and the test assertions.

2. vars/secrets precedence wording. The workflow uses
   'vars.TUSHARE_HTTP_URL || secrets.TUSHARE_HTTP_URL', which means a
   non-empty vars entry always wins and Secrets cannot override it. The
   zh/en notes previously suggested 'Secrets as a tamper fallback' which
   is incorrect under this precedence and can mislead users into thinking
   Secrets has override power. Replace with explicit description of the
   real semantics: vars wins when non-empty; Secrets is only selected
   when the Variable is empty; for a tamper-resistant deployment put the
   value only in Secrets and leave Variables empty.

Both zh and en guides are updated together; the same 6 contract surfaces
(runtime / .env.example / workflow priority / tests / zh guide / en guide)
now describe one consistent contract.

* docs(tushare): remove false Secret-as-tamper-guard claim, document real vars/secrets write-permission model
2026-07-22 20:54:40 +08:00
zhulinsen
16e3421c1b fix: secure fork PR review workflow (#2057) 2026-07-21 22:24:19 +08:00
JaxonHu
d13721e817 feat: 新增富途Futu真实持仓导入支持 (#2042)
* feat: add Futu portfolio import support

* docs: condense Futu changelog entry

* fix: tighten Futu portfolio import contracts
2026-07-20 22:45:45 +08:00
Sam Smith
a3c039ac13 feat: add feishu file upload support for report delivery (#1932)
* feat: add feishu file upload support for report delivery

- Add FEISHU_SEND_AS_FILE config option to switch from text to file delivery
- Implement FeishuSender.send_feishu_file() with App Bot SDK upload + webhook fallback
- Integrate file upload path into pipeline dashboard notification loop
- Integrate file upload path into NotificationService.send_report()
- Add save_and_send_feishu_file() convenience wrapper
- Add .env.example entry and CHANGELOG.md record

* fix: restrict feishu file mode to report routes and wire into workflow

- Limit FEISHU_SEND_AS_FILE to route_type=None or 'report' in
  _send_to_static_channel, preventing alert/event paths from
  unexpectedly saving alerts as files (Codex review P2).
- Add FEISHU_SEND_AS_FILE env var to .github/workflows/00-daily-analysis.yml
  so the setting is available in scheduled runs (Codex review P2).
- Add 13 tests: 7 FeishuSender unit tests (send_feishu_file webhook/App Bot
  paths), 6 NotificationService integration tests (route_type filtering)

* fix: address round-2 review blockers

Correctness:
- Remove route_type=None file-mode fallback; only explicit
  route_type='report' triggers Feishu file delivery
  (api/v1/endpoints/agent.py calls send() without route_type)

Compatibility:
- Isolate CreateFileRequest/CreateFileRequestBody imports from
  CreateMessageRequest; add FEISHU_FILE_SDK_AVAILABLE flag
  so old lark-oapi without file-upload classes won't break
  existing App Bot text messaging

Test fix:
- Fix webhook test assertion: # Test Report -> **Test Report**
  (format_feishu_markdown converts markdown headings to bold)

Documentation:
- Add FEISHU_SEND_AS_FILE to docs/notifications.md config table
- Add file-send section to docs/bot/feishu-bot-config.md
  (permissions, deps, webhook fallback, route scope, CI mapping)
- Add FEISHU_SEND_AS_FILE to docs/full-guide.md and
  docs/full-guide_EN.md config tables
- Add Feishu file create OpenAPI link to docs/notifications.md

* docs: fix feishu_sender drift and document config entry boundary

- Fix outdated '本轮未改动 feishu_sender.py' line in docs/notifications.md
  (we added send_feishu_file to feishu_sender.py)
- Document FEISHU_SEND_AS_FILE as .env/Actions-only in
  docs/bot/feishu-bot-config.md (not exposed in Web/Desktop settings)

* feat: add FEISHU_SEND_AS_FILE to system_config_service env mapping

- Add FEISHU_SEND_AS_FILE -> feishu_send_as_file (bool) mapping
  alongside FEISHU_MAX_BYTES in the notification env key mapping
- Update docs/bot/feishu-bot-config.md to reflect standard config paths

* test: add non-mock SDK import smoke test for file upload classes
2026-07-06 21:26:19 +08:00
zhulinsen
267c2139ae docs: clarify data source configuration (#1935) 2026-07-05 20:57:42 +08:00
Shlok Goyal
34f02af617 Ci/dingtalk GitHub actions (#1918)
* ci: map DingTalk secrets to daily analysis workflow

* docs: sync github actions documentation table for DingTalk

* docs: add changelog entry for DingTalk GitHub Actions mapping
2026-07-04 21:46:28 +08:00
zhulinsen
ade3b4cb6e feat: add JP KR market review support (#1822)
* feat: add JP KR market review support

* fix(review-feedback-1822): update the Market Light schema/service support before accepting these

* fix(review-feedback-1822): add JP/KR to daily market context before accepting them and update

* fix(review-feedback-1822): add English JP/KR strategy text or make the renderer language-aware

* fix(review-feedback-1822): update the prompt role/shell alongside the new accepted regions

* fix(review-feedback-1822): 修正 PR 描述中的过期验证结论,并补充/澄清 JP/KR Yahoo Finance 指数兼容性证据或在线验证边界

* fix(review-feedback-1822): 收敛 Market Light 告警契约与用户文档同步问题

* fix(review-feedback-1822): 修正后再合入

* fix(review-feedback-1822): 补齐外部 Yahoo Finance 指数接入与运行时配置变更的兼容性/迁移证据,并修正 PR 描述中与当前 CI 状态不一致的内容

* fix(review-feedback-1822): 当前 CI 状态为 failure,且阻断型 backend-gate 失败

* fix(review-feedback-1822): 修复 MARKET REVIEW REGION 逗号值在交易日过滤与配置 schema 中的契约漂移,并补充对应回归测试

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态与用户可见 Web 改动证据

* fix(review-feedback-1822): 修正 PR 描述中的过期验证结论,并补充 Web 设置变更的截图或无法截图时的替代可视证据说明

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态,并补齐 Web 设置变更的截图或替代可视证据

* fix(review-feedback-1822): 收敛 PR 描述后再合入

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态,并补充 Web 设置变更截图或无法截图时的替代可视证据说明

* fix(review-feedback-1822): 收敛验证状态和 Web UI 可视证据,避免合入记录与实际 head 不一致

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态与 Web 可视证据

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态,并补齐 Web 设置变更的截图或替代可视证据说明

* fix(review-feedback-1822): 修正 PR 描述与当前 CI 事实不一致的问题,补充 Web 设置可视证据,并收敛或拆出 PR 模板改动

* fix(review-feedback-1822): 收敛 PR 描述与证据

* fix(review-feedback-1822): 修正 PR 描述与证据,使验证状态、用户可见变更证据、模板改动范围和当前 head 保持一致

* fix(review-feedback-1822): 收敛 PR 描述、补齐可视证据,并澄清/补充外部模型/API 与运行时配置迁移相关兼容性证据

* fix(review-feedback-1822): 收敛 Web/文档契约不一致、同步残留测试,并更新 PR 描述与可视证据
2026-06-28 17:03:15 +08:00
Alfred
62adb5c4ee feat: add Hermes local HTTP generation (#1824) 2026-06-28 17:02:17 +08:00
zhulinsen
d0ab0663b8 ci: speed up Docker build checks (#1820)
* ci: speed up docker build checks

* test: align Dockerfile cache assertion
2026-06-27 22:35:44 +08:00
zhulinsen
ecf87ea010 fix: support STOCK_LIST environment variables (#1782) 2026-06-24 22:11:50 +08:00
zhulinsen
b308e44827 fix: repair backtest empty result handling (#1779) 2026-06-24 21:52:07 +08:00
Alfred
1f91024dec feat: 新增 codex_cli 本地生成后端 Phase2 (#1769)
* feat: add codex cli generation backend

* fix: harden local CLI backend phase 2

* fix: harden local cli output file handling

* fix: tighten codex cli backend contracts

* fix: support codex cli windows smoke path

* fix: make local cli tests portable on windows

* fix: avoid duplicate codex final output accounting
2026-06-24 20:19:19 +08:00
Alfred
df09b7ccf4 feat: add provider prompt cache controls (#1744) 2026-06-22 20:50:54 +08:00
mumu
f61c5362a6 docs: update Trendshift badge and PR workflow rules (#1736) 2026-06-21 15:02:52 +08:00
Alfred
4fa81a421c feat: add legacy LLM usage telemetry (#1698) 2026-06-17 18:46:01 +08:00
mumu
b9f5989a21 fix(issue-1683): [bug]-发布说明生成在作者查询失败时缺少诊断日志 (#1684) 2026-06-14 17:55:52 +08:00
ZhuLinsen
02ca95efd1 ci: simplify release notes generation 2026-06-13 19:27:14 +08:00
mumu
649f7757ae chore: remove one-off PR screenshot assets (#1625)
* chore: remove one-off PR screenshots

* chore: remove one-off issue screenshots
2026-06-06 22:54:41 +08:00
mumu
8a77960bcb docs: require screenshots for visual PR changes (#1613) 2026-06-05 22:04:50 +08:00
Delicious233
3471afbd98 feat: add Feishu App Bot notification sender with P2P and group support (#1553)
* feat: add Feishu App Bot notification sender with P2P and group support

The existing FeishuSender only supports custom robot Webhook mode.
This commit extends it to support App Bot (lark-oapi SDK) mode, auto-routing
between webhook (priority) and App Bot when FEISHU_APP_ID + FEISHU_APP_SECRET
+ FEISHU_CHAT_ID are configured.

Design:
- send_to_feishu() routes: webhook if URL set, else App Bot
- DCLP lazy client init with thread-safe sentinel guard
- Retry (3 attempts, exponential backoff) with fixed UUID for idempotency
- Card-first / text-fallback content strategy
- Chunking for long messages
- Runtime enum validation for FEISHU_RECEIVE_ID_TYPE and FEISHU_DOMAIN
- Safe SDK defaults (FEISHU_DOMAIN/LARK_DOMAIN) before import try-block
  so Webhook path never depends on lark-oapi SDK presence
- Config, diagnostics, setup check, notification test, and CI workflow
  all consistent with the new App Bot channel semantics
- lark-oapi>=1.0.0 already in requirements.txt (line 23)

Verification:
- 20/20 unit tests pass (help metadata + FeishuSender)
- E2E: real Feishu API — SDK import, token, client init, P2P text+card send all PASS
- Webhook regression: verified no SDK dependency for existing Webhook path

* fix: add missing Feishu App Bot locale entries and env table keys, harden sender error handling

CI fix 1 (test_registry_help_keys_exist_in_locales):
- Add zh-CN and en-US locale entries for FEISHU_CHAT_ID,
  FEISHU_RECEIVE_ID_TYPE, FEISHU_DOMAIN in settingsHelp.ts

CI fix 2 (test_notification_actions_env_table_matches_generated_output):
- Add FEISHU_RECEIVE_ID_TYPE, FEISHU_DOMAIN to feishu advanced_keys
  in CHANNEL_SPECS so they appear in KEY_SPECS
- Regenerate managed env table in docs/notifications.md

feishu_sender.py hardening:
- Catch network exceptions in webhook _post_payload so card-to-text
  fallback actually executes on transient failures
- Guard response.json() and isinstance(result, dict) against
  non-JSON / non-dict HTTP 200 responses
- Extract shared _build_card_body() to de-duplicate card payload
  construction between webhook and App Bot paths
- Rename module-level lark -> _lark to avoid shadowing
- Guard resp.get_log_id() with try/except
- Add None guard on send_to_feishu content parameter

e2e script improvements:
- Support FEISHU_OPEN_ID for P2P test, FEISHU_DOMAIN for Lark
- Add FEISHU_TEST_SEND_TEXT=1 for plain-text-only path testing
- Clarify docstring: setup validation + smoke test, not full e2e

* fix: consolidate Feishu App Bot notification contract

* fix: align Feishu domain help scope

---------

Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-06-05 08:56:42 +08:00
mumu
649413cf1a fix: pass SearXNG Actions variables to daily workflow (#1567) 2026-06-04 19:50:33 +08:00
mumu
647b9d24e5 fix: support Longbridge OAuth token cache (#1490)
* fix: support Longbridge OAuth token cache

* fix(review-feedback-1490): bump the runtime dependency minimum or fail with a clear upgrade

* fix(review-feedback-1490): 补充对应回归测试

* fix(review-feedback-1490): Point OAuth cache at the dsa home in Docker

* fix(review-feedback-1490): 修复或给出明确的 CI 重跑通过证据

* fix(review-feedback-1490): 处理 Docker/Actions 持久化 token cache 已损坏时无法被新的 LONGBRIDGE OAUTH TOKEN

* fix: tighten Longbridge OAuth compatibility

* fix: refresh stale Longbridge OAuth cache

* fix: guard Longbridge OAuth SDK availability
2026-05-29 23:08:16 +08:00
mumu
6684e327dd chore: prioritize daily analysis workflow (#1373) 2026-05-20 22:24:44 +08:00
mumu
4733d2185a fix: unify desktop updater artifacts (#1320) 2026-05-16 17:49:34 +08:00
mumu
e407b5bf14 feat: Add report LLM model visibility toggle (#1294) 2026-05-16 15:12:39 +08:00
mumu
f8458c582a feat: Configure market review index colors (#1295) 2026-05-15 22:35:40 +08:00
mumu
f553fe160a docs: 规范 PR title 指引 (#1308) 2026-05-15 22:01:55 +08:00
Alfred
a75a0c502e feat: complete p6 notification channel cleanup (#1275) 2026-05-13 19:19:54 +08:00
Alfred
9f56238420 feat: 支持 ntfy 一等通知渠道(P6-A) (#1271)
* feat: add ntfy notification channel

* test: add ntfy smoke evidence images

* fix: validate ntfy endpoint in structured config

* fix: align ntfy endpoint validation
2026-05-13 12:47:46 +08:00
Alfred
9f70705234 feat: 添加 P4 通知降噪机制 (Refs #1200) (#1260)
* feat: add notification noise controls

* docs: clarify notification timezone fallback

* fix: address notification noise review feedback
2026-05-11 07:45:41 +08:00
mumu
41844a181d feat: add desktop auto-update install flow (#1256) 2026-05-11 07:44:43 +08:00
mumu
595908c81a chore: reorganize root files (#1257)
* chore: reorganize root files

* fix: mark moved docs assets as binary
2026-05-10 19:50:22 +08:00
Alfred
0adcef3627 feat: add notification routing strategy (#1248)
Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-05-10 13:24:02 +08:00
Alfred
f9549c7f39 fix: add notification baseline diagnostics (#1200) (#1205)
Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-05-06 18:46:35 +08:00
mumu
629335852e docs: Clean root helper files (#1203)
* chore: clean root helper files

* fix: forward quick smoke args
2026-05-06 18:44:39 +08:00
mumu
695365b3d8 feat: add Anspire Open LLM support (#1193)
* feat: add Anspire Open LLM support
2026-05-04 23:53:22 +08:00
mumu
d0ff7abb14 chore: land #1180 P1 LLM Actions mapping (#1190)
* chore: 补齐 LLM Actions 映射与模板校准 P1 (#1180) (#1186)

* chore: align LLM channel Actions mapping (#1180)

* docs: prefer validated OpenRouter default (#1180)

* fix(review-feedback-1190): address latest review comments

---------

Co-authored-by: Alfred <massif0601@gmail.com>
2026-05-03 21:58:03 +08:00
Fangyu Zhao
c5ac36e731 feat: add optional Anspire API support for github action 2026-04-27 10:31:47 +08:00
mumu
4574c52b04 [fix] Support Kimi K2.6 fixed temperature (#1113)
* Fix Kimi K2.6 temperature compatibility
2026-04-25 22:46:53 +08:00
mumu
e480fccf50 docs: streamline README documentation (#1120)
* docs: streamline readme documentation
2026-04-25 18:17:22 +08:00
mumu
826c340c28 [fix] Map LLM channel envs in daily analysis workflow (#1112)
* Fix GitHub Actions LLM channel env mapping
2026-04-25 10:23:36 +08:00
zhulinsen
dbdf30d170 fix(ci): avoid secrets in docker publish step conditions 2026-04-22 23:15:23 +08:00