fix(bot-mode): DMs to a Desktop-owned Bot Chat land in the live session instead of being dropped (#100523)
When the Desktop has a bot's "Bot Chat" open, that session holds the single-owner lease, so the `hermes -p <bot> chat -c "Bot Chat"` subprocess `bot_relay.deliver` spawns refuses with "already has a live owner" and the DM payload is dropped — the sender was already acked. bot_relay.deliver now looks up a live in-process session for the target profile whose title resolves to "Bot Chat" (same profile_home match as session.resume's _find_live_unpersisted, pending_title for lazy sessions, otherwise the db title) and, when found, submits the message through the existing prompt.submit handler — the composer's choke point — so it lands as a normal user turn (role alternation preserved, streams to the open window). No live owner → the subprocess path runs exactly as before. On the local message_agent subprocess path, the lease refusal is surfaced as a structured `target_busy` delivery failure telling the sender the message was NOT delivered, instead of a raw exit-1 with the text buried in stderr. Closes #100523 Supersedes #100544, #100542 Co-authored-by: fangliquanflq <fangliquan@qq.com> Co-authored-by: 686f6c61 <github@00b.tech>
This commit is contained in:
@@ -109,6 +109,38 @@ def _(rid, params: dict) -> dict:
|
||||
if resolved not in known:
|
||||
return _err(rid, 4092, f"no profile '{profile}' on this gateway")
|
||||
|
||||
# #100523: when THIS gateway already hosts the target's Bot Chat live
|
||||
# (the Desktop has it open), the subprocess transport is fenced out by
|
||||
# the single-owner lease ("already has a live owner") and the payload
|
||||
# is dropped. Land the DM in the live session as a normal user turn
|
||||
# via prompt.submit instead — same choke point the composer uses, so
|
||||
# role alternation, persistence and streaming all behave as a typed
|
||||
# message would. (Nested per method_ctx rebinding.)
|
||||
def _live_bot_chat_sid(profile_name: str) -> str:
|
||||
from tools.bot_mode_probe import BOT_CHAT_TITLE
|
||||
|
||||
live_home = _profile_home(profile_name)
|
||||
want_home = str(live_home) if live_home is not None else None
|
||||
for live_sid, record in list(_sessions.items()):
|
||||
if not isinstance(record, dict):
|
||||
continue
|
||||
if (record.get("profile_home") or None) != want_home:
|
||||
continue
|
||||
key = _session_lookup_key(record, fallback=live_sid)
|
||||
if _session_live_title(record, key) == BOT_CHAT_TITLE:
|
||||
return live_sid
|
||||
return ""
|
||||
|
||||
live_sid = _live_bot_chat_sid(resolved)
|
||||
if live_sid:
|
||||
submitted = _methods["prompt.submit"](rid, {"session_id": live_sid, "text": message})
|
||||
if "error" in submitted:
|
||||
return submitted
|
||||
return _ok(
|
||||
rid,
|
||||
{"reply": f"Delivered into @{resolved}'s open Bot Chat; the reply will appear there."},
|
||||
)
|
||||
|
||||
fd, tmp = tempfile.mkstemp(prefix="hermes-relay-dm-", suffix=".txt", text=True)
|
||||
try:
|
||||
with os.fdopen(fd, "w", encoding="utf-8") as f:
|
||||
|
||||
Reference in New Issue
Block a user