Skip to content

06 — v0.1.1 Hotfix + P1 起步

Status: ✅ v0.1.1 hotfix shipped 2026-05-07 · ⏳ P1.0 backend pending Scope: 用户报告的 get_price 拿不到最新价 bug 的修复方案 + 顺势启动 P1.0 backend 的决策与边界

修 stale price 的最短路径 + 把多租户决策从 P2 拉到 v0.1.1 起步落地

目标 (Goal)

修复用户在 stock-research_Agent profile 报告的 get_price 在交易时段返回隔夜收盘价的问题,并以这个 hotfix 为契机:

  1. 把 cite 信封拓展为前向兼容多源(served_by 字段)
  2. 跑通 install-skill.sh 把更新推到运行中的 profile
  3. 起步 P1.0 backend 时复用本次的路由逻辑

待研究 / 已确认的源

  • ✅ akshare stock_individual_spot_xq(雪球单 code 端点):~1.4s/查询,单 HTTP 调用
  • ❌ akshare stock_zh_a_spot_em(东方财富全市场):~75s/查询(58 页分页全市场扫描),不可用于实时单查
  • ✅ Tushare trade_cal(exchange=SSE):判断当日是否交易日,缓存当日结果即可
  • ⏳ pytdx3 / Yahoo / 跨源比对:P1.2 范围

關鍵決策點 (Open Questions)

Q1. 修复策略 — 自动路由 / 显式 flag / 仅文档

  • A) 自动路由:盘中调 akshare 实时,盘后/周末调 Tushare daily(agent 不用知道市场时段)
  • B) 加 --realtime flag:保持 tushare daily 默认,让 agent 显式选实时
  • C) 仅文档说明 T+1 语义,不改代码

已决 A(自动路由) —— 引用 §D1-D5 Background Track plan。理由:agent prompt 越简单越稳定;路由失败时 fallback 到 Tushare 仍然返回有效值。已落地 core/core/data/schemas.py:get_price

Q2. cite 信封怎么表达"哪个源出的数"

  • A) 复用 cite.source 字段("tushare" / "akshare")
  • B) 加 served_by 字段(更明确,跨源比对更友好)
  • C) 同时写 cite.source + cite.adapter

已决 B(加 served_bycite.source 历史含义是"这条数据的原始来源"(schema 里也是 tushare 字符串),served_by 表达"本次查询路由到了哪个 adapter",两者将来可能不一致(缓存场景:served_by="cache", source="tushare")。已落地 core/core/citation.py:ToolCite

Q3. v0.1.1 完成后是直接起 P1.0 还是先做 P1.2 多源?

  • A) 直接 P1.0 backend skeleton(按 Phase 1 plan Tasks 1-4 + 8)
  • B) 先 P1.2 多源(pytdx3 + Yahoo),再起 backend

已决 A(先 P1.0) —— 见 v3 plan §8 Week 2。理由:backend 是 Direct → Service 模式迁移的载体,越早把这条路跑通越能验证多租户假设;多源数据 P1.2 可以挂在 backend 后面增量做。

Q4. 是否同步替换 stock-research_Agent profile 的 AGENTS.md/SOUL.md?

  • A) 是,本次 hotfix 一并替换(A 股专用版)
  • B) 否,留到 P1.1 provisioner 模板化时统一处理

已决 A(一并替换):模板源就放在仓库 profile/template-stock-research-pro/,用本周末时间替换运行中的 profile,同时也是 P1.1 provisioner 用模板时的现成原料。

修复实现 (v0.1.1,已 shipped)

Code 改动

文件操作
core/core/data/akshare.py新建:get_spot_price(code) 走 Xueqiu 单 code 端点;_to_xueqiu_symbol("600519.SH") → "SH600519"
core/core/data/_market.py新建:is_market_open(now, token) + is_trading_day(date_str, token);缓存当日结果;Tushare 失败降级为 weekday-only
core/core/data/schemas.py:get_price加路由:trade_date is None && is_market_open() → akshare;否则 → tushare daily;akshare 失败 fallback 到 daily
core/core/citation.py:ToolCite加 `served_by: str
core/pyproject.tomlakshare>=1.13,<2;版本 0.1.0 → 0.1.1
skill/stock-research/SKILL.md加 §"价格新鲜度语义"段落,说明 metricserved_by 的语义

测试

  • 16 个新单测:test_data_market.py(市场时段、trade_cal 缓存、Tushare 降级)+ test_data_akshare.py(envelope shape、suffix 翻译、NaN/None 处理、upstream exception 包装)
  • 路由分支测试:test_data_schemas.py 加盘中→akshare、akshare 失败 fallback、市场关闭→tushare 三个场景
  • 集成测试:test_skill_scripts.pyserved_by 断言 + akshare 路由 e2e

E2E 验证(盘后路径)

bash
$ ~/.hermes/profiles/stock-research-agent/skills/research/stock-research/scripts/fetch_price.py 600519
{
  "value": 1371.05,
  "metric": "close",
  "code": "600519.SH",
  "as_of": "2026-05-07",
  "cite": {"served_by": "tushare", "source": "tushare", "table": "daily", ...}
}

akshare 路径直接调用(绕过市场时段判断):~1.4s 返回 served_by: "akshare"metric: "current_price"

P1.0 启动边界(Week 2)

起步范围

Phase 1 plan Tasks 1-4 + 8:

  • FastAPI app skeleton + Settings (Pydantic) + Bearer auth 中间件(SHA256 hash)
  • DuckDB cache 层(24h TTL,schema daily_cache(code, trade_date, close, fetched_at)
  • Endpoints:/healthz/price/fundamentals
  • admin CLI scripts/issue-token.py
  • Vultr 部署(systemd + Caddy)

不在 Week 2 范围

  • P1.1 支付 / onboarding(W3)
  • P1.2 pytdx3 / Yahoo / 跨源比对(W4)
  • P1.3 web search(W5)
  • P2 任何 initiative

与 v0.1.1 的复用

P1.0 /price endpoint 内部直接调 core/core/data/schemas.get_price,自动继承 v0.1.1 的 akshare/Tushare 路由。Backend 添加的只是:

  • 缓存(DuckDB cache 层在 schemas.get_price 之上)
  • 鉴权(Bearer 中间件)
  • HTTP 协议层

→ Direct/Service 双模式 user 看到一样的 cite 信封。

與其他層的關係

  • L3 Tools(v0.1.0):本次只改 schemas.get_price,不动 tushare.call 抽象
  • L4 Skills(v0.1.0):fetch_price.py CLI 不变;只更新 SKILL.md 让 agent 知道怎么解读 metricserved_by
  • 未来 cross-source 比对(P1.2):served_by 是 single 字段;P1.2 多源同时返回时改成 served_by: ["tushare", "pytdx3"],这是 forward-compatible 演进路径

下一步 (Next Steps)

已完成(v0.1.1 shipped 2026-05-07):

  1. ✅ akshare adapter + market clock + 路由
  2. ✅ cite served_by 加字段
  3. ✅ 测试 60/60 绿
  4. ✅ install-skill.sh dev 模式部署到 stock-research_Agent profile
  5. ✅ E2E 验证盘后路径

待办(Week 1 D5 收尾):

  1. 替换 stock-research_Agent profile 的 AGENTS.md/SOUL.md(A 股专用)
  2. 同步进 profile/template-stock-research-pro/
  3. tag v0.1.1 + push(触发 release workflow)
  4. 部署文档站到 Cloudflare Pages

待办(Week 2 起,P1.0):

详见 plans/2026-05-07-v0.1.1-hotfix.md §"Phase 2: P1.0 backend"。

进一步阅读

团队内部文档