feat(omp-rpc): added error handling and history bounds to RPC client

- Added error handling callbacks (on_protocol_error, on_listener_error) and error history tracking (protocol_errors, listener_errors properties) for RPC failures.
- Added max_event_history and max_stderr_chunks parameters to bound retained history in long-lived hosts, preventing unbounded memory growth.
- Added assistant_text_with_thinking() and message_text_with_thinking() helper functions for backward compatibility with thinking block inclusion.
- Improved error correlation for id-less parse/unknown-command failures to waiting requests and changed prompt scheduling failures to raise instead of timing out.
- Refactored event dispatch to _dispatch_listeners() with exception handling and error recording for robust listener failure management.
This commit is contained in:
can1357
2026-04-08 05:21:01 +02:00
parent 776546e09d
commit 528d8225b7
6 changed files with 504 additions and 44 deletions
+12 -4
View File
@@ -702,7 +702,7 @@ def image_from_path(path: str | Path, mime_type: str | None = None) -> ImageCont
}
def message_text(message: AgentMessage) -> str | None:
def message_text(message: AgentMessage, *, include_thinking: bool = False) -> str | None:
role = message.get("role")
if role not in {"user", "developer", "assistant", "toolResult", "custom", "hookMessage"}:
return None
@@ -720,15 +720,23 @@ def message_text(message: AgentMessage) -> str | None:
block_type = block.get("type")
if block_type == "text" and isinstance(block.get("text"), str):
fragments.append(cast(str, block["text"]))
elif block_type == "thinking" and isinstance(block.get("thinking"), str):
elif include_thinking and block_type == "thinking" and isinstance(block.get("thinking"), str):
fragments.append(cast(str, block["thinking"]))
return "".join(fragments) or None
def assistant_text(message: AgentMessage) -> str | None:
def message_text_with_thinking(message: AgentMessage) -> str | None:
return message_text(message, include_thinking=True)
def assistant_text(message: AgentMessage, *, include_thinking: bool = False) -> str | None:
if message.get("role") != "assistant":
return None
return message_text(message)
return message_text(message, include_thinking=include_thinking)
def assistant_text_with_thinking(message: AgentMessage) -> str | None:
return assistant_text(message, include_thinking=True)
def parse_model_info(payload: JsonObject | None) -> ModelInfo | None: