trymockagent 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,45 @@
1
+ Metadata-Version: 2.4
2
+ Name: trymockagent
3
+ Version: 0.1.0
4
+ Summary: Python client for the MockAgent API
5
+ Requires-Python: >=3.9
6
+ Description-Content-Type: text/markdown
7
+
8
+ # trymockagent
9
+
10
+ Dependency-free Python client for the MockAgent API. Supports Python 3.9+.
11
+
12
+ After publishing the package, install it with:
13
+
14
+ ```bash
15
+ pip install trymockagent
16
+ ```
17
+
18
+ ```python
19
+ import os
20
+ import uuid
21
+
22
+ from trymockagent import MockAgent, MockAgentError
23
+
24
+ mock = MockAgent(
25
+ tool_id="YOUR_TOOL_ID",
26
+ api_key=os.getenv("MOCKAGENT_API_KEY"), # optional unless the tool requires a key
27
+ )
28
+ run_id = str(uuid.uuid4())
29
+
30
+ try:
31
+ result = mock.call({"user_id": "vip", "reason": "duplicate"}, run_id=run_id)
32
+ print(result)
33
+ # If this tool has final-answer QA criteria configured:
34
+ qa = mock.submit_final_answer("The VIP refund was processed.", run_id=run_id)
35
+ print(qa)
36
+ except MockAgentError as error:
37
+ print(error.status, error.body, error.retryable, error.retry_after_seconds)
38
+ raise
39
+ ```
40
+
41
+ `get_tool()` fetches the tool's schema and description. `call(arguments,
42
+ run_id=...)` posts JSON and forwards the run ID in `x-mockagent-run-id`.
43
+ `submit_final_answer(text, run_id=...)` submits configured final-answer checks.
44
+ No automatic retries are made; inspect the exception and follow the response's
45
+ retry guidance. Set `base_url` for a self-hosted MockAgent instance.
@@ -0,0 +1,5 @@
1
+ trymockagent.py,sha256=_4kcE5D3m2CtRlT5tgPNB-WWU1twQfTms9BTNJE1xgY,4787
2
+ trymockagent-0.1.0.dist-info/METADATA,sha256=qd26vj55MMKJWuRymbTnUbJqFGBNqpyqJPtDG8jpcPs,1397
3
+ trymockagent-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
4
+ trymockagent-0.1.0.dist-info/top_level.txt,sha256=U8dogot8XZ7oxMHCIWidT1gt_IJrulaS1kkk-KmT4rk,13
5
+ trymockagent-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ trymockagent
trymockagent.py ADDED
@@ -0,0 +1,131 @@
1
+ """A dependency-free Python client for the MockAgent API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from typing import Any, Dict, Optional
7
+ from urllib.error import HTTPError, URLError
8
+ from urllib.parse import quote
9
+ from urllib.request import Request, urlopen
10
+
11
+
12
+ class MockAgentError(Exception):
13
+ """An HTTP, network, or response-format error from MockAgent."""
14
+
15
+ def __init__(
16
+ self,
17
+ message: str,
18
+ *,
19
+ status: Optional[int] = None,
20
+ body: Any = None,
21
+ retry_after_seconds: Optional[int] = None,
22
+ cause: Optional[BaseException] = None,
23
+ ) -> None:
24
+ super().__init__(message)
25
+ self.status = status
26
+ self.body = body
27
+ self.retry_after_seconds = retry_after_seconds
28
+ self.retryable = body.get("retryable") if isinstance(body, dict) else None
29
+ if cause is not None:
30
+ self.__cause__ = cause
31
+
32
+
33
+ class MockAgent:
34
+ """Call one MockAgent tool and submit final-answer QA for its runs."""
35
+
36
+ def __init__(
37
+ self,
38
+ tool_id: str,
39
+ *,
40
+ api_key: Optional[str] = None,
41
+ base_url: str = "https://mockagent.online",
42
+ timeout: Optional[float] = 30,
43
+ ) -> None:
44
+ if not tool_id:
45
+ raise ValueError("tool_id is required.")
46
+ self.tool_id = tool_id
47
+ self.api_key = api_key
48
+ self.base_url = base_url.rstrip("/")
49
+ self.timeout = timeout
50
+ self.tool_url = "{}/api/v1/mock/{}".format(self.base_url, quote(tool_id, safe=""))
51
+
52
+ def get_tool(self) -> Any:
53
+ """Fetch the tool's description and expected JSON schema."""
54
+ return self._request(self.tool_url, "GET")
55
+
56
+ def call(self, arguments: Any, *, run_id: Optional[str] = None) -> Any:
57
+ """Post tool-call arguments, optionally associating them with a run."""
58
+ headers = {"x-mockagent-run-id": run_id} if run_id else {}
59
+ return self._request(self.tool_url, "POST", arguments, headers)
60
+
61
+ def submit_final_answer(self, final_answer: str, *, run_id: str) -> Any:
62
+ """Submit the final answer for configured checks on this run."""
63
+ if not run_id:
64
+ raise ValueError("run_id is required to submit a final answer.")
65
+ return self._request(
66
+ self.tool_url + "/final-answer",
67
+ "POST",
68
+ {"final_answer": final_answer},
69
+ {"x-mockagent-run-id": run_id},
70
+ )
71
+
72
+ def _request(
73
+ self,
74
+ url: str,
75
+ method: str,
76
+ body: Any = None,
77
+ extra_headers: Optional[Dict[str, str]] = None,
78
+ ) -> Any:
79
+ headers = dict(extra_headers or {})
80
+ if body is not None:
81
+ headers["Content-Type"] = "application/json"
82
+ if self.api_key:
83
+ headers["Authorization"] = "Bearer " + self.api_key
84
+ encoded_body = None if body is None else json.dumps(body).encode("utf-8")
85
+ request = Request(url, data=encoded_body, headers=headers, method=method)
86
+
87
+ try:
88
+ with urlopen(request, timeout=self.timeout) as response:
89
+ status = response.status
90
+ response_headers = response.headers
91
+ raw_body = response.read()
92
+ except HTTPError as error:
93
+ status = error.code
94
+ response_headers = error.headers
95
+ try:
96
+ raw_body = error.read()
97
+ finally:
98
+ error.close()
99
+ except URLError as error:
100
+ raise MockAgentError(
101
+ "Could not connect to MockAgent.",
102
+ cause=error,
103
+ ) from error
104
+
105
+ text = raw_body.decode("utf-8")
106
+ try:
107
+ parsed_body = json.loads(text) if text else None
108
+ except json.JSONDecodeError as error:
109
+ raise MockAgentError(
110
+ "MockAgent returned a non-JSON response.",
111
+ status=status,
112
+ body=text,
113
+ cause=error,
114
+ ) from error
115
+
116
+ if status < 200 or status >= 300:
117
+ message = "MockAgent request failed ({})".format(status)
118
+ if isinstance(parsed_body, dict):
119
+ message = parsed_body.get("error") or parsed_body.get("message") or message
120
+ retry_after = response_headers.get("Retry-After")
121
+ try:
122
+ retry_after_seconds = int(retry_after) if retry_after is not None else None
123
+ except ValueError:
124
+ retry_after_seconds = None
125
+ raise MockAgentError(
126
+ message,
127
+ status=status,
128
+ body=parsed_body,
129
+ retry_after_seconds=retry_after_seconds,
130
+ )
131
+ return parsed_body