fix(bot-mode): carry the relay sender into a live Bot Chat turn

When the target Bot Chat is already open on this gateway, the relay handler delivers through
`prompt.submit` with `queued: true`, and that branch dropped the envelope's sender. The model
still saw the text prefix, but the turn reached the agent unattributed, the exact case the
subprocess branch fixes.

The relay handler now stamps the author on the submit as a `DeliveryAuthor`, an in-process object
a JSON client cannot build, so `prompt.submit` accepts it the way it accepts a hosted-room callback
and refuses a dict with error 4124. The busy queue keeps an authored envelope in its own slot, the
drain hands the author to the turn runner, and the runner passes it to an agent that declares the
keyword. A plain prompt after an authored dm carries no author.

Local deliveries to a desktop-owned Bot Chat take the live-owner mailbox instead. The admission
intent and the mailbox record now carry the author, a retry under the same id with a different
author is refused, and the owner gateway hands the author to the turn it runs. Isolated compute
turns still run unattributed, because the compute-host frame has no author field.
This commit is contained in:
Erosika
2026-09-08 10:55:46 -04:00
committed by Teknium
parent 366f9446c9
commit 6881e4d3fc
12 changed files with 231 additions and 68 deletions
+3 -3
View File
@@ -121,7 +121,7 @@ def _write(path: Path, record: dict[str, Any]) -> None:
def deliver_to_live_owner(
profile_home: Path | str, owner: dict[str, Any], message: str,
*, delivery_id: str | None = None,
*, delivery_id: str | None = None, author: dict[str, Any] | None = None,
) -> dict[str, Any]:
"""Return durable admission immediately, without waiting for the owner.
@@ -136,7 +136,7 @@ def deliver_to_live_owner(
path = root / f"{key}.json"
existing = _read(path)
if existing is not None:
if existing["owner"] != pinned or existing["message"] != message:
if existing["owner"] != pinned or existing["message"] != message or existing.get("author") != author:
raise ValueError("delivery id already belongs to a different payload")
return existing
# Wall time can roll back. Permanent receipts retain the admission
@@ -146,7 +146,7 @@ def deliver_to_live_owner(
if (record := _read(candidate)) is not None), default=0) + 1
record = dict(delivery_id=key, id=key, owner=pinned, **pinned,
message=message, status="queued", created_at=time.time_ns(),
sequence=sequence)
sequence=sequence, **({"author": dict(author)} if author else {}))
_write(path, record)
return record