Skip to content

fix(chat): request cancellation over HTTP without optimistic completion - #876

Open
dangzitou wants to merge 1 commit into
TencentCloud:developfrom
dangzitou:fix-chat-http-cancel
Open

dangzitou wants to merge 1 commit into
TencentCloud:developfrom
dangzitou:fix-chat-http-cancel

Conversation

@dangzitou

@dangzitou dangzitou commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #803 for ordinary running Dashboard turns.

  • Add an authenticated POST /agents/{agent_id}/threads/{thread_id}/cancel endpoint using the existing thread ownership check and synchronous cancellation entry.
  • Send Stop requests over HTTP with a separate 10-second timeout and an in-flight click guard, without requiring an existing WebSocket. Do not automatically retry.
  • Report requested / inactive / unconfirmed outcomes in English and Chinese. Keep stream reception, messages, usage, and reconnect state intact until the existing terminal/state-sync path observes completion; re-subscribe when no live socket remains.
  • Add cancellation regression coverage and update the changelog and API reference.

requested: true acknowledges that the cancellation entry was called, not that the task has already stopped. This does not address queued tasks, HITL, exact earlier-turn cancellation, rollback of external side effects, or Harness-internal cancellation (#805). Legacy WebSocket cancel and disconnect behavior are unchanged.

Target branch

  • Base is develop (feature / fix — default)
  • Base is main (release/* or hotfix/* only)

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactor / chore
  • Release / hotfix

Test plan

  • Local rebase verification at ec70e5f4: the Unreleased changelog conflict was resolved, the functional patch kept its stable patch-id, and git diff --check passed. Earlier local WebSocket integration 21 passed, stop-button tests 10 passed, and dashboard build passed. The latest Linux / Windows result is shown in GitHub Checks.
  • Previous rebase onto develop at 963cb140 (head d9032fe9): functional diff unchanged; WebSocket integration 21 passed, cancellation Vitest 10 passed, and npm run build passed.
  • On develop at 728ca521, make all PYTEST_JOBS=2 passed Ruff, formatting and mypy; the full backend run had 3713 passed, 18 skipped, 1 failed. The failure was the existing test_process_exit_after_commit_keeps_last_fragment subprocess exceeding its 20-second timeout while multiple suites were running.
  • After rebasing onto 6f7815bb (head ded4854e), the timeout test passed alone without code or timeout changes. make lint typecheck passed; uv run pytest tests/integration/test_chat_ws.py tests/unit/i18n -n 2 -q passed (91 passed).
  • Previous-head Vitest coverage passed: 16 tests across cancellation, ChatInput prefill and connector-card suites. Cancellation covers missing/closed WebSocket, authentication and encoded IDs, duplicate clicks, timeout/error feedback, retained streaming/usage, terminal handling, and session identity after navigation.
  • npm run build passed, including TypeScript checking and the production build.
  • OpenAPI response schema and Scalar rendering were inspected during implementation.

The full local run above was not green; its sole timeout passed in isolation. The unchanged chatStore.ts also has the same no-extra-boolean-cast ESLint error as clean develop; no unrelated lint fix is included. Local checks used macOS / Python 3.14. Final-head Linux/Windows CI and maintainer testing are tracked separately; real-LLM/manual refresh-and-stop testing is not claimed.

Reproduction evidence (before / after)

Turn running, dashboard without a live WebSocket: on develop POST /agents/{id}/threads/{tid}/cancel → 404 and the turn keeps streaming; on this branch it returns 200 {"requested": true} and the turn terminates (idle re-post honestly reports requested: false).

Before (develop @ 4667bd7b):

before

After (this branch):

after

Checklist

  • Updated CHANGELOG.md (if user-facing)
  • README / docs updated (if needed)

@jubaoliang

Copy link
Copy Markdown
Collaborator

问题是真的:Stop 只走 WebSocket,并且本地会乐观把回合标成 done。补 HTTP cancel、等服务端回执再结束,方向对。

当前与 develop 冲突(useChat 等)。请 rebase 到最新 develop,CI 绿后再合。夹带的无关测试修如果不是取消路径必需,请一并拿掉。

@dangzitou

Copy link
Copy Markdown
Contributor Author

@jubaoliang 已按意见处理,麻烦复核:

  • 已 rebase 到最新 develop(ae7dfc8b),新提交 168f1863,当前 GitHub 显示 MERGEABLE、无冲突。冲突解决未改动修复逻辑:CHANGELOG.md 保留双方条目;useChat.ts 里 develop 新增的 setSessionTeamRoom effect 与本次改动并存,没有回退 develop 的代码。
  • 与取消路径无关的测试修改已全部移除(publishedExperts.test.ts、AuthGuard.test.tsx、Channels/components/constants.test.ts、Settings/SearchConfig/index.test.tsx、test/setup.ts)。diff 现在只含取消链路本身:HTTP 接口、chatStore / useChat、octopThreads、新增 useChat.cancel.test.ts、中英文文案、docs/api.md 与 CHANGELOG,共 11 个文件。
  • 本地验证:完整非 live 后端套件 3628 passed / 17 skipped,Ruff 与 mypy --strict 通过;tests/integration/test_chat_ws.py 21 项全过(含新增的 HTTP cancel 两项);前端完整套件结果与干净 develop 基线完全一致(develop 自身就有同样 4 个文件 / 1 个测试失败,均为既有问题),新增 useChat.cancel.test.ts 10 项全过;tsc -b 与 Prettier 通过。

fork PR 的工作流需要审批才会运行,烦请批准后跑一遍 CI;若复核无问题,麻烦合并到 develop。谢谢!

@dangzitou
dangzitou force-pushed the fix-chat-http-cancel branch 2 times, most recently from d2885a8 to ded4854 Compare September 23, 2026 07:58
@dangzitou

Copy link
Copy Markdown
Contributor Author

@jubaoliang 已 rebase 到最新拉取的 develop(6f7815bb),当前 head 为 ded4854e。保留现有流结束/状态同步语义,停止按钮只通过 HTTP 发起取消,不提前把运行状态改成完成;功能 diff 未变,没有混入无关前端修复。

验证如实说明:首轮 make all 静态检查通过,全量 3713 passed / 18 skipped,唯一失败是已有历史持久化子进程的 20 秒超时。最终 head 上单独复跑该用例通过,未改代码或超时;后端相关回归 91 passed、前端相关回归 16 passed,lint / mypy / TypeScript / 生产构建通过。chatStore.ts 的既有 ESLint 报错在 develop 原文件上同样可复现,未混入修复。最新 Linux / Windows CI 等待本次推送后的结果。

PR 描述已更新验证范围。请按你的节奏测试,后续我会继续跟进 develop 并及时 rebase。

@dangzitou

Copy link
Copy Markdown
Contributor Author

@jubaoliang 同步到新 develop(963cb140),head d9032fe9。CHANGELOG 冲突已合并,取消链路的功能 diff 逐行未变。本地 WebSocket 集成回归 21 passed、停止按钮回归 10 passed,TypeScript 与生产构建通过。新 head 的 Linux / Windows CI 正在运行,我会继续跟进。

@dangzitou
dangzitou force-pushed the fix-chat-http-cancel branch 21 times, most recently from 43d886f to 7eea801 Compare September 27, 2026 10:41
@dangzitou
dangzitou force-pushed the fix-chat-http-cancel branch 11 times, most recently from cfcc978 to e0e1e84 Compare October 3, 2026 19:04
@dangzitou
dangzitou force-pushed the fix-chat-http-cancel branch from e0e1e84 to 1222424 Compare October 4, 2026 13:43
@dangzitou

Copy link
Copy Markdown
Contributor Author

@jubaoliang 这个是自己用得最多的:点停止前端会把回合乐观标成完成,帧也照收,其实服务端还没取消完。

按你说的,rebase 和不相关的测试修都处理了,现在只剩取消链路本身——HTTP 发起取消,等服务端回执再结束。刚跟着最新 develop 又推了一版。

正文最底下有修复前后的验证截图,麻烦再审一遍。

@dangzitou
dangzitou force-pushed the fix-chat-http-cancel branch 2 times, most recently from ffd82b8 to 9eea919 Compare October 8, 2026 18:16
@dangzitou
dangzitou force-pushed the fix-chat-http-cancel branch from 9eea919 to f95a3bb Compare October 10, 2026 17:11

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants