mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-07-19 21:07:28 +08:00
fix(wecom_bot): finalize stream on cancel; never force-finish on a timer
The streaming "···" bubble should only stop when the task actually completes or the user cancels — not on an arbitrary timeout that would also steal the response_url fallback's chance to deliver a late answer. - On agent_cancelled, finalize the stream (finish=true, "🛑 已中止" if empty) and schedule the response_url fallback so the bubble clears immediately when a run is cancelled, even past the poll window - Do not force-finish a still-running stream on a timer; let it keep spinning until completion or cancel. Answers that finish after WeCom's ~6min poll window are delivered via response_url instead Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -314,10 +314,14 @@ class WecomBotChannel(ChatChannel):
|
|||||||
# Unknown / expired stream: tell WeCom we're done to stop polling.
|
# Unknown / expired stream: tell WeCom we're done to stop polling.
|
||||||
return {"msgtype": "stream", "stream": {"id": stream_id, "finish": True, "content": ""}}
|
return {"msgtype": "stream", "stream": {"id": stream_id, "finish": True, "content": ""}}
|
||||||
state["last_access"] = time.time()
|
state["last_access"] = time.time()
|
||||||
finished = state["finished"]
|
|
||||||
if state.get("url_sent"):
|
if state.get("url_sent"):
|
||||||
# Final answer already pushed via response_url; finish silently.
|
# Final answer already pushed via response_url; finish silently.
|
||||||
return {"msgtype": "stream", "stream": {"id": stream_id, "finish": True, "content": ""}}
|
return {"msgtype": "stream", "stream": {"id": stream_id, "finish": True, "content": ""}}
|
||||||
|
# We never force-finish on a timer: while a task is still running the
|
||||||
|
# bubble should keep spinning until either the task finishes or the
|
||||||
|
# user cancels. If WeCom's 6min window closes before completion, the
|
||||||
|
# answer is delivered later via response_url instead.
|
||||||
|
finished = state["finished"]
|
||||||
content = state["committed"] + state["current"]
|
content = state["committed"] + state["current"]
|
||||||
images = state["images"] if finished else []
|
images = state["images"] if finished else []
|
||||||
if finished:
|
if finished:
|
||||||
@@ -342,6 +346,7 @@ class WecomBotChannel(ChatChannel):
|
|||||||
def on_event(event: dict):
|
def on_event(event: dict):
|
||||||
event_type = event.get("type")
|
event_type = event.get("type")
|
||||||
edata = event.get("data", {})
|
edata = event.get("data", {})
|
||||||
|
cancelled = False
|
||||||
with self._callback_lock:
|
with self._callback_lock:
|
||||||
state = self._callback_streams.get(stream_id)
|
state = self._callback_streams.get(stream_id)
|
||||||
if not state:
|
if not state:
|
||||||
@@ -363,12 +368,23 @@ class WecomBotChannel(ChatChannel):
|
|||||||
state["committed"] += state["current"]
|
state["committed"] += state["current"]
|
||||||
state["current"] = ""
|
state["current"] = ""
|
||||||
elif event_type == "agent_cancelled":
|
elif event_type == "agent_cancelled":
|
||||||
|
# Mechanism 1: a cancelled run never reaches send(), so finalize
|
||||||
|
# its stream here to stop the "···" bubble immediately.
|
||||||
if state["current"]:
|
if state["current"]:
|
||||||
state["committed"] += state["current"]
|
state["committed"] += state["current"]
|
||||||
state["current"] = ""
|
state["current"] = ""
|
||||||
state["committed"] = state["committed"].rstrip()
|
state["committed"] = state["committed"].rstrip()
|
||||||
if state["committed"].endswith("---"):
|
if state["committed"].endswith("---"):
|
||||||
state["committed"] = state["committed"][:-3].rstrip()
|
state["committed"] = state["committed"][:-3].rstrip()
|
||||||
|
if not state["committed"].strip():
|
||||||
|
state["committed"] = "🛑 已中止"
|
||||||
|
state["finished"] = True
|
||||||
|
state["last_access"] = time.time()
|
||||||
|
cancelled = True
|
||||||
|
|
||||||
|
if cancelled:
|
||||||
|
# Outside the lock: response_url fallback re-acquires it.
|
||||||
|
self._schedule_response_url_fallback(stream_id)
|
||||||
|
|
||||||
return on_event
|
return on_event
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user