aboutsummaryrefslogtreecommitdiffstats
path: root/idatui/errors.py
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-24 14:41:23 +0200
committerblasty <blasty@local>2026-07-24 14:41:23 +0200
commit0decb747ac9239faf5119b7faa80596995746ef9 (patch)
tree7996725bc0d3c62d9c25d1f5bc3f12979711a52c /idatui/errors.py
parenttests: pass url=""/db=None to IdaTui in the worker pilot path (diff)
downloadida-tui-0decb747ac9239faf5119b7faa80596995746ef9.tar.gz
ida-tui-0decb747ac9239faf5119b7faa80596995746ef9.tar.xz
ida-tui-0decb747ac9239faf5119b7faa80596995746ef9.zip
refactor: extract shared error hierarchy + Session into idatui/errors.py
The IDAError/IDAConnectionError/IDAToolError/... exceptions and the Session dataclass were defined in client.py (the ida-pro-mcp HTTP client), but the idalib worker path (worker_client/domain/app) needs them without the HTTP transport. Move them to a transport-agnostic errors.py; client.py re-exports them so the deprecated mcp tooling and stress tests are unchanged (verified: errors.IDAToolError IS client.IDAToolError, so cross-module `except` still works). worker_client, domain (TYPE_CHECKING-guarded IDAClient hint), app, and __init__ now import the shared types from errors.py. This decouples the worker path from client.py at runtime -- the prerequisite for deleting the mcp transport.
Diffstat (limited to 'idatui/errors.py')
-rw-r--r--idatui/errors.py76
1 files changed, 76 insertions, 0 deletions
diff --git a/idatui/errors.py b/idatui/errors.py
new file mode 100644
index 0000000..29b09ae
--- /dev/null
+++ b/idatui/errors.py
@@ -0,0 +1,76 @@
+"""Transport-agnostic error hierarchy and the Session model.
+
+These were originally defined in client.py (the ida-pro-mcp HTTP client), but the
+idalib worker path (worker_client / domain / app) needs the same exception types
+and Session dataclass without dragging in the HTTP transport. They live here so
+both backends share one definition; client.py re-exports them for backwards
+compatibility with the (deprecated) mcp tooling and the stress tests.
+"""
+from __future__ import annotations
+
+from dataclasses import dataclass
+from typing import Any
+
+
+# --------------------------------------------------------------------------- #
+# Exceptions
+# --------------------------------------------------------------------------- #
+class IDAError(Exception):
+ """Base class for all client errors."""
+
+
+class IDAConnectionError(IDAError):
+ """The transport could not be established or was lost."""
+
+
+class IDATimeoutError(IDAError):
+ """A request exceeded its deadline."""
+
+
+class IDAProtocolError(IDAError):
+ """Malformed or unexpected HTTP / JSON-RPC framing."""
+
+
+class IDARPCError(IDAError):
+ """The JSON-RPC envelope carried an ``error`` object."""
+
+ def __init__(self, code: int, message: str, data: Any = None):
+ super().__init__(f"JSON-RPC error {code}: {message}")
+ self.code = code
+ self.message = message
+ self.data = data
+
+
+class IDAToolError(IDAError):
+ """A tool call returned ``result.isError == true`` (a hard failure)."""
+
+ def __init__(self, tool: str, message: str):
+ super().__init__(f"tool {tool!r} failed: {message}")
+ self.tool = tool
+ self.message = message
+
+
+class IDASessionError(IDAError):
+ """No IDB session is open, or several are and none was pinned."""
+
+
+# --------------------------------------------------------------------------- #
+# Session model
+# --------------------------------------------------------------------------- #
+@dataclass(frozen=True)
+class Session:
+ session_id: str
+ filename: str
+ input_path: str
+ is_active: bool = False
+ is_analyzing: bool = False
+
+ @classmethod
+ def from_dict(cls, d: dict) -> "Session":
+ return cls(
+ session_id=d.get("session_id", ""),
+ filename=d.get("filename", ""),
+ input_path=d.get("input_path", ""),
+ is_active=bool(d.get("is_active", False)),
+ is_analyzing=bool(d.get("is_analyzing", False)),
+ )