Inbox: people before system notices and newest first; wait wakes on new or human messages, not an old notice backlog; mark_read MCP tool

DeepSeek's inbox was buried under 78 automatic baseline notices read oldest
first, so it missed direct answers.
This commit is contained in:
KeelrLeek committed 2026-10-05 18:19:19 -05:00
1 parent f708e3025c
commit f1241c19a3
4 files changed
+50 -8

No files matched your search

+24 -1
View File
@@ -141,6 +141,28 @@ def inbox(limit: int = 20, include_read: bool = False, peek: bool = False) -> li
mark_read=not peek)])
@mcp.tool
def mark_read(ids: list[int] | None = None, before_id: int | None = None, system_only: bool = False) -> dict:
"""Mark messages to you read without loading them: the given ids, or everything unread up to before_id
(system_only=True limits that to Harbor's automatic notices). Use it to clear a stale backlog so new messages
come up first."""
def do(h):
agent = me()
if ids:
chosen = [int(i) for i in ids]
else:
if before_id is None:
raise HarborError("give ids or before_id")
query = ("SELECT d.message_id FROM deliveries d JOIN messages m ON m.id=d.message_id "
"WHERE d.agent=? AND d.read_at IS NULL AND d.message_id < ?")
if system_only:
query += " AND m.origin='system'"
chosen = [r["message_id"] for r in h.conn.execute(query, (agent, int(before_id)))]
h.mark_read(agent, chosen)
return {"marked_read": len(chosen), "unread_now": h.unread_count(agent)[0]}
return run(do)
@mcp.tool
async def wait_for_messages(timeout_seconds: int = 300) -> dict:
"""Wait (up to timeout_seconds, max 1800) until a message for you arrives or a stop applies, then return the
@@ -148,8 +170,9 @@ async def wait_for_messages(timeout_seconds: int = 300) -> dict:
agent = run(lambda h: me())
timeout = max(1, min(int(timeout_seconds), 1800))
deadline = asyncio.get_running_loop().time() + timeout
since = run(lambda h: h.last_delivered_id(agent)) # wake on new messages, not on an old unread backlog
while True:
state = run(lambda h: (h.unread_count(agent)[0], [f["key"] for f in h.stopped(agent)]))
state = run(lambda h: (h.unread_count_after(agent, since), [f["key"] for f in h.stopped(agent)]))
if state[0] or state[1] or asyncio.get_running_loop().time() >= deadline:
messages = run(lambda h: [compact(m) for m in h.inbox(agent, limit=30)]) if state[0] else []
run(lambda h: h.touch(agent))