Skip to content

feat(scheduler): qzone.reply_comments 自动回评论 builtin + 管理页子任务区#158

Merged
sweetcornna merged 1 commit into
mainfrom
feat/qzone-reply-comments
Jul 19, 2026
Merged

feat(scheduler): qzone.reply_comments 自动回评论 builtin + 管理页子任务区#158
sweetcornna merged 1 commit into
mainfrom
feat/qzone-reply-comments

Conversation

@sweetcornna

Copy link
Copy Markdown
Owner

PR-B6 — qzone.reply_comments 定时自动回复评论(净新增,hermes 没有的能力)

后端

  • 新 builtin qzone.reply_commentsscheduler/builtins/qzone_reply.py,镜像 qzone_daily 注册方式):驱动一次内部 ChatService turn,system tail 指示模型:qzone_list_feed 拉自己的说说(qq_account 已知时钉死 owner_uin,否则按 my_uin 过滤)→ 取最近 lookback_posts 条 → 跳过自己的评论与「已回复过」列表 → 对新评论 qzone_post_comment(人设口吻,reply_to_uin=评论者,至多 max_replies 条)→ 直接结束 turn(不发说说、不提问)。NapCat 鉴权在 agent 侧工具执行器内,故必须走 chat turn。
  • metadatapersona_id(必填) / qq_account? / max_replies(1-10, 默认 3) / lookback_posts(1-20, 默认 5),全部可选带默认、越界 clamp。
  • 去重 sidecar <DATA_DIR>/qzone_seen_comments/<persona_id>.json{version:1, seen:{tid:["uin:ts",...]}};slug 校验防路径穿越(镜像 feat(scheduler): QZone 日常发布多样性引擎 — 灵感种子 / 反重复 post-log / 多样性 tail / 发布抖动 (PR-B4) #155);per-tid 200 / 总 tid 100 封顶(LRU 式滚出);原子写;组 prompt 时注入「已回复过」块,turn 结束后从事件流收集成功的 qzone_post_comment(非 error 且 envelope ok)回填。
  • audit dict{ok, replies_posted, tids_scanned, skipped_seen, error?} + persona/qq/tools_called/duration_ms;builtin 永不抛,一切失败折叠(chat_error/chat_timeout/chat_service_failed/persona_* 等)。
  • 公共骨架抽取 scheduler/builtins/_qzone_chat.py:两个 builtin 共享 metadata/chat/persona-store/data-dir/model 解析、InternalChatRequest 构造、带超时的事件流 drive(ChatDriveOutcome 记录全部 tool_call/tool_result)、事件内省、slug 守卫。qzone_daily 改为薄封装,audit 语义逐字段不变——现有 33 个 daily 测试全绿零改动;多样性/labels/harvest 本体未动。
  • admin_validate_qzone_reply(缺 persona / 越界 / 非 int → 422 invalid_qzone_reply_args),create/PATCH/resume 三处生效;trigger 运行时回退支持 reply 任务并在 history 记 replies=NJobOut 新增只读回显 max_replies/lookback_posts(写入路径仍走 metadata)。

前端

  • /scheduler/qzone 新增「评论自动回复」子任务区:persona 选择 + QzoneSchedulePicker(新增可选 idPrefix prop 避免双实例 id 冲突,默认值保持旧选择器不变)+ max_replies/lookback_posts 数字输入(随 body.metadata 提交);任务名 {persona}.qzone_reply;行为复用 QzoneJobRow(立即跑/编辑/启停/删除),编辑就地回填。
  • i18n schedulerQzone.reply.* en+zh-CN 双份(title/editTitle/help/maxRepliesLabel/maxRepliesHint/lookbackLabel/lookbackHint/empty)。

验证

  • uv run ruff check(改动文件)✅
  • uv run mypy python/packages/(strict, 611 files)✅
  • uv run lint-imports(2 kept, 0 broken)✅
  • env -u ANTHROPIC_BASE_URL uv run pytest tests/scheduler/ tests/test_admin_scheduler_qzone.py196 passed(新增 backend 30:builtin 23 + admin 7)✅
  • cd ui && pnpm test161 files / 1254 passed(新增 4;守卫测试绿)✅
  • pnpm typecheck:0 错误 ✅

后端(PR-B6):
- 新 builtin `qzone.reply_comments`(scheduler/builtins/qzone_reply.py):
  驱动一次内部 ChatService turn,system tail 指示模型 qzone_list_feed
  拉自己最近 lookback_posts 条说说 → 跳过已回/自己的评论 → 对新评论
  qzone_post_comment(人设口吻,至多 max_replies 条)→ 结束 turn。
  audit dict = {ok, replies_posted, tids_scanned, skipped_seen, error?},
  builtin 永不抛。
- 去重 sidecar `<DATA_DIR>/qzone_seen_comments/<persona_id>.json`
  ({version:1, seen:{tid:["uin:ts",...]}},slug 防穿越、per-tid 200 /
  总 tid 100 封顶、原子写);已见列表注入 tail,turn 后从事件流回填。
- 公共骨架抽取 _qzone_chat.py:metadata/chat/persona-store/data-dir/
  model 解析、InternalChatRequest 构造、带超时的事件流 drive
  (ChatDriveOutcome 记录全部 tool_call/tool_result)、事件内省与
  slug 守卫。qzone_daily 改为薄封装调用,audit 语义逐字段保持不变
  (现有 33 个 daily 测试全绿,多样性/labels/harvest 逻辑未动)。
- admin 校验:_validate_qzone_reply(persona 必填;metadata.max_replies
  1-10 / lookback_posts 1-20,非法 422 invalid_qzone_reply_args),
  create/patch/resume 全走;trigger 运行时回退支持 reply 任务;JobOut
  只读回显 max_replies/lookback_posts 供编辑回填。

前端:
- /scheduler/qzone 新增「评论自动回复」子任务区:persona 选择 +
  QzoneSchedulePicker(新增 idPrefix 防重复 id)+ max_replies/
  lookback_posts 数字输入(走 body.metadata),任务名
  {persona}.qzone_reply,行为复用 QzoneJobRow(立即跑/编辑/启停/删除)。
- i18n schedulerQzone.reply.* en+zh-CN 双份。

测试:后端 +30(builtin 23 + admin 7),前端 +4 并适配双表单选择器;
ruff/mypy strict/lint-imports/vitest/typecheck 全绿。

Claude-Session: https://claude.ai/code/session_01PzzkxzLNdLrVCRAUyGtmEz
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions github-actions Bot added codex:needs-review A Codex review is needed for the current PR head. codex:review-requested A Codex review was requested or should be running automatically. status: 🔁 re-review loop A fresh Codex review was requested after the latest change or comment. codex:reviewed Codex posted a review result or thumbs-up after the latest request. status: 👀 ready for maintainer look No automation blocker is known; a maintainer should inspect the current result. and removed codex:review-requested A Codex review was requested or should be running automatically. codex:needs-review A Codex review is needed for the current PR head. status: 🔁 re-review loop A fresh Codex review was requested after the latest change or comment. labels Jul 19, 2026
@sweetcornna
sweetcornna merged commit 2c69ed5 into main Jul 19, 2026
8 of 9 checks passed
@sweetcornna
sweetcornna deleted the feat/qzone-reply-comments branch July 19, 2026 06:13
@github-actions github-actions Bot added the status: ✅ merge-ready Evidence and review are clear; normal merge gates may proceed. label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex:reviewed Codex posted a review result or thumbs-up after the latest request. status: ✅ merge-ready Evidence and review are clear; normal merge gates may proceed. status: 👀 ready for maintainer look No automation blocker is known; a maintainer should inspect the current result.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant