cage-bro 0.1.0__tar.gz

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,99 @@
1
+ Metadata-Version: 2.4
2
+ Name: cage-bro
3
+ Version: 0.1.0
4
+ Summary: Python SDK for cage-bro sandbox
5
+ License-Expression: Apache-2.0
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: httpx>=0.24.0
9
+ Provides-Extra: dev
10
+ Requires-Dist: pytest; extra == "dev"
11
+ Requires-Dist: pytest-asyncio; extra == "dev"
12
+
13
+ # cage-bro
14
+
15
+ Python SDK for [cage-bro](https://github.com/aeroxy/cage-bro) — a sandboxed execution environment for AI agents.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pip install cage-bro
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```python
26
+ from cage_bro import CageBro
27
+
28
+ cage = CageBro("http://localhost:8080")
29
+
30
+ # Run shell commands
31
+ result = cage.shell_exec("ls -la")
32
+ print(result["stdout"])
33
+
34
+ # Execute code
35
+ result = cage.python("print(2 + 2)")
36
+ print(result["stdout"])
37
+
38
+ # Read/write files
39
+ cage.file_write("hello.txt", "world")
40
+ content = cage.file_read("hello.txt")
41
+ ```
42
+
43
+ ## API
44
+
45
+ ### Sandbox
46
+
47
+ | Method | Description |
48
+ |---|---|
49
+ | `info()` | Get sandbox info |
50
+ | `health()` | Health check |
51
+
52
+ ### Shell
53
+
54
+ | Method | Description |
55
+ |---|---|
56
+ | `shell_exec(command, timeout_ms=None)` | Execute a shell command |
57
+ | `shell_create_session(shell=None)` | Create a persistent shell session |
58
+
59
+ ### Files
60
+
61
+ | Method | Description |
62
+ |---|---|
63
+ | `file_read(path)` | Read a file |
64
+ | `file_write(path, content)` | Write to a file |
65
+ | `file_edit(path, old_text, new_text)` | Edit a file (find & replace) |
66
+ | `file_list(path=".")` | List directory contents |
67
+ | `file_search(query, path=None)` | Search files for text |
68
+ | `file_delete(path)` | Delete a file or directory |
69
+
70
+ ### Code Execution
71
+
72
+ | Method | Description |
73
+ |---|---|
74
+ | `python(code, timeout_ms=None)` | Execute Python code |
75
+ | `node(code, timeout_ms=None)` | Execute Node.js code |
76
+
77
+ ### Browser
78
+
79
+ | Method | Description |
80
+ |---|---|
81
+ | `browser_launch(port=None, stealth=True)` | Launch the browser |
82
+ | `browser_navigate(url)` | Navigate to a URL |
83
+ | `browser_screenshot()` | Take a screenshot |
84
+ | `browser_click(selector)` | Click an element |
85
+ | `browser_type(selector, text)` | Type text into an element |
86
+ | `browser_evaluate(expression)` | Evaluate JavaScript |
87
+ | `browser_content()` | Get current page content |
88
+ | `browser_close()` | Close the browser |
89
+
90
+ ## Context Manager
91
+
92
+ ```python
93
+ with CageBro("http://localhost:8080") as cage:
94
+ cage.shell_exec("echo hello")
95
+ ```
96
+
97
+ ## License
98
+
99
+ Apache-2.0
@@ -0,0 +1,87 @@
1
+ # cage-bro
2
+
3
+ Python SDK for [cage-bro](https://github.com/aeroxy/cage-bro) — a sandboxed execution environment for AI agents.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install cage-bro
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from cage_bro import CageBro
15
+
16
+ cage = CageBro("http://localhost:8080")
17
+
18
+ # Run shell commands
19
+ result = cage.shell_exec("ls -la")
20
+ print(result["stdout"])
21
+
22
+ # Execute code
23
+ result = cage.python("print(2 + 2)")
24
+ print(result["stdout"])
25
+
26
+ # Read/write files
27
+ cage.file_write("hello.txt", "world")
28
+ content = cage.file_read("hello.txt")
29
+ ```
30
+
31
+ ## API
32
+
33
+ ### Sandbox
34
+
35
+ | Method | Description |
36
+ |---|---|
37
+ | `info()` | Get sandbox info |
38
+ | `health()` | Health check |
39
+
40
+ ### Shell
41
+
42
+ | Method | Description |
43
+ |---|---|
44
+ | `shell_exec(command, timeout_ms=None)` | Execute a shell command |
45
+ | `shell_create_session(shell=None)` | Create a persistent shell session |
46
+
47
+ ### Files
48
+
49
+ | Method | Description |
50
+ |---|---|
51
+ | `file_read(path)` | Read a file |
52
+ | `file_write(path, content)` | Write to a file |
53
+ | `file_edit(path, old_text, new_text)` | Edit a file (find & replace) |
54
+ | `file_list(path=".")` | List directory contents |
55
+ | `file_search(query, path=None)` | Search files for text |
56
+ | `file_delete(path)` | Delete a file or directory |
57
+
58
+ ### Code Execution
59
+
60
+ | Method | Description |
61
+ |---|---|
62
+ | `python(code, timeout_ms=None)` | Execute Python code |
63
+ | `node(code, timeout_ms=None)` | Execute Node.js code |
64
+
65
+ ### Browser
66
+
67
+ | Method | Description |
68
+ |---|---|
69
+ | `browser_launch(port=None, stealth=True)` | Launch the browser |
70
+ | `browser_navigate(url)` | Navigate to a URL |
71
+ | `browser_screenshot()` | Take a screenshot |
72
+ | `browser_click(selector)` | Click an element |
73
+ | `browser_type(selector, text)` | Type text into an element |
74
+ | `browser_evaluate(expression)` | Evaluate JavaScript |
75
+ | `browser_content()` | Get current page content |
76
+ | `browser_close()` | Close the browser |
77
+
78
+ ## Context Manager
79
+
80
+ ```python
81
+ with CageBro("http://localhost:8080") as cage:
82
+ cage.shell_exec("echo hello")
83
+ ```
84
+
85
+ ## License
86
+
87
+ Apache-2.0
@@ -0,0 +1,4 @@
1
+ from .client import CageBro
2
+
3
+ __version__ = "0.1.0"
4
+ __all__ = ["CageBro"]
@@ -0,0 +1,145 @@
1
+ import httpx
2
+ from typing import Optional, Dict, Any, List
3
+
4
+
5
+ class CageBro:
6
+ """Python client for cage-bro sandbox API."""
7
+
8
+ def __init__(self, base_url: str = "http://localhost:8080", timeout: float = 30.0):
9
+ self.base_url = base_url.rstrip("/")
10
+ self._client = httpx.Client(base_url=self.base_url, timeout=timeout)
11
+
12
+ def close(self):
13
+ self._client.close()
14
+
15
+ def __enter__(self):
16
+ return self
17
+
18
+ def __exit__(self, *args):
19
+ self.close()
20
+
21
+ # --- Sandbox ---
22
+
23
+ def info(self) -> Dict[str, Any]:
24
+ """Get sandbox info."""
25
+ return self._client.get("/v1/sandbox/info").json()
26
+
27
+ def health(self) -> Dict[str, Any]:
28
+ """Health check."""
29
+ return self._client.get("/health").json()
30
+
31
+ # --- Shell ---
32
+
33
+ def shell_exec(self, command: str, timeout_ms: Optional[int] = None) -> Dict[str, Any]:
34
+ """Execute a shell command."""
35
+ payload: Dict[str, Any] = {"command": command}
36
+ if timeout_ms:
37
+ payload["timeout_ms"] = timeout_ms
38
+ return self._client.post("/v1/shell/exec", json=payload).json()
39
+
40
+ def shell_create_session(self, shell: Optional[str] = None) -> Dict[str, Any]:
41
+ """Create a persistent shell session."""
42
+ payload = {}
43
+ if shell:
44
+ payload["shell"] = shell
45
+ return self._client.post("/v1/shell/session", json=payload).json()
46
+
47
+ # --- Files ---
48
+
49
+ def file_read(self, path: str) -> str:
50
+ """Read a file and return its content."""
51
+ resp = self._client.post("/v1/file/read", json={"path": path})
52
+ data = resp.json()
53
+ if "error" in data:
54
+ raise FileNotFoundError(data["error"])
55
+ return data["content"]
56
+
57
+ def file_write(self, path: str, content: str) -> None:
58
+ """Write content to a file."""
59
+ resp = self._client.post("/v1/file/write", json={"path": path, "content": content})
60
+ data = resp.json()
61
+ if "error" in data:
62
+ raise IOError(data["error"])
63
+
64
+ def file_edit(self, path: str, old_text: str, new_text: str) -> None:
65
+ """Edit a file by replacing old_text with new_text."""
66
+ resp = self._client.post("/v1/file/edit", json={
67
+ "path": path, "old_text": old_text, "new_text": new_text
68
+ })
69
+ data = resp.json()
70
+ if "error" in data:
71
+ raise IOError(data["error"])
72
+
73
+ def file_list(self, path: str = ".") -> List[Dict[str, Any]]:
74
+ """List directory contents."""
75
+ resp = self._client.post("/v1/file/list", json={"path": path})
76
+ return resp.json().get("entries", [])
77
+
78
+ def file_search(self, query: str, path: Optional[str] = None) -> List[Dict[str, Any]]:
79
+ """Search files for text."""
80
+ payload: Dict[str, Any] = {"query": query}
81
+ if path:
82
+ payload["path"] = path
83
+ resp = self._client.post("/v1/file/search", json=payload)
84
+ return resp.json().get("results", [])
85
+
86
+ def file_delete(self, path: str) -> None:
87
+ """Delete a file or directory."""
88
+ resp = self._client.post("/v1/file/delete", json={"path": path})
89
+ data = resp.json()
90
+ if "error" in data:
91
+ raise IOError(data["error"])
92
+
93
+ # --- Code ---
94
+
95
+ def python(self, code: str, timeout_ms: Optional[int] = None) -> Dict[str, Any]:
96
+ """Execute Python code."""
97
+ payload: Dict[str, Any] = {"code": code}
98
+ if timeout_ms:
99
+ payload["timeout_ms"] = timeout_ms
100
+ return self._client.post("/v1/code/python", json=payload).json()
101
+
102
+ def node(self, code: str, timeout_ms: Optional[int] = None) -> Dict[str, Any]:
103
+ """Execute Node.js code."""
104
+ payload: Dict[str, Any] = {"code": code}
105
+ if timeout_ms:
106
+ payload["timeout_ms"] = timeout_ms
107
+ return self._client.post("/v1/code/node", json=payload).json()
108
+
109
+ # --- Browser ---
110
+
111
+ def browser_launch(self, port: Optional[int] = None, stealth: bool = True) -> Dict[str, Any]:
112
+ """Launch the browser."""
113
+ payload: Dict[str, Any] = {"stealth": stealth}
114
+ if port:
115
+ payload["port"] = port
116
+ return self._client.post("/v1/browser/launch", json=payload).json()
117
+
118
+ def browser_navigate(self, url: str) -> Dict[str, Any]:
119
+ """Navigate to a URL."""
120
+ return self._client.post("/v1/browser/navigate", json={"url": url}).json()
121
+
122
+ def browser_screenshot(self) -> Dict[str, Any]:
123
+ """Take a screenshot."""
124
+ return self._client.post("/v1/browser/screenshot", json={}).json()
125
+
126
+ def browser_click(self, selector: str) -> Dict[str, Any]:
127
+ """Click an element."""
128
+ return self._client.post("/v1/browser/click", json={"selector": selector}).json()
129
+
130
+ def browser_type(self, selector: str, text: str) -> Dict[str, Any]:
131
+ """Type text into an element."""
132
+ return self._client.post("/v1/browser/type", json={"selector": selector, "text": text}).json()
133
+
134
+ def browser_evaluate(self, expression: str) -> Any:
135
+ """Evaluate JavaScript."""
136
+ resp = self._client.post("/v1/browser/evaluate", json={"expression": expression})
137
+ return resp.json().get("result")
138
+
139
+ def browser_content(self) -> Dict[str, Any]:
140
+ """Get current page content."""
141
+ return self._client.post("/v1/browser/content", json={}).json()
142
+
143
+ def browser_close(self) -> None:
144
+ """Close the browser."""
145
+ self._client.post("/v1/browser/close", json={})
@@ -0,0 +1,99 @@
1
+ Metadata-Version: 2.4
2
+ Name: cage-bro
3
+ Version: 0.1.0
4
+ Summary: Python SDK for cage-bro sandbox
5
+ License-Expression: Apache-2.0
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: httpx>=0.24.0
9
+ Provides-Extra: dev
10
+ Requires-Dist: pytest; extra == "dev"
11
+ Requires-Dist: pytest-asyncio; extra == "dev"
12
+
13
+ # cage-bro
14
+
15
+ Python SDK for [cage-bro](https://github.com/aeroxy/cage-bro) — a sandboxed execution environment for AI agents.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pip install cage-bro
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```python
26
+ from cage_bro import CageBro
27
+
28
+ cage = CageBro("http://localhost:8080")
29
+
30
+ # Run shell commands
31
+ result = cage.shell_exec("ls -la")
32
+ print(result["stdout"])
33
+
34
+ # Execute code
35
+ result = cage.python("print(2 + 2)")
36
+ print(result["stdout"])
37
+
38
+ # Read/write files
39
+ cage.file_write("hello.txt", "world")
40
+ content = cage.file_read("hello.txt")
41
+ ```
42
+
43
+ ## API
44
+
45
+ ### Sandbox
46
+
47
+ | Method | Description |
48
+ |---|---|
49
+ | `info()` | Get sandbox info |
50
+ | `health()` | Health check |
51
+
52
+ ### Shell
53
+
54
+ | Method | Description |
55
+ |---|---|
56
+ | `shell_exec(command, timeout_ms=None)` | Execute a shell command |
57
+ | `shell_create_session(shell=None)` | Create a persistent shell session |
58
+
59
+ ### Files
60
+
61
+ | Method | Description |
62
+ |---|---|
63
+ | `file_read(path)` | Read a file |
64
+ | `file_write(path, content)` | Write to a file |
65
+ | `file_edit(path, old_text, new_text)` | Edit a file (find & replace) |
66
+ | `file_list(path=".")` | List directory contents |
67
+ | `file_search(query, path=None)` | Search files for text |
68
+ | `file_delete(path)` | Delete a file or directory |
69
+
70
+ ### Code Execution
71
+
72
+ | Method | Description |
73
+ |---|---|
74
+ | `python(code, timeout_ms=None)` | Execute Python code |
75
+ | `node(code, timeout_ms=None)` | Execute Node.js code |
76
+
77
+ ### Browser
78
+
79
+ | Method | Description |
80
+ |---|---|
81
+ | `browser_launch(port=None, stealth=True)` | Launch the browser |
82
+ | `browser_navigate(url)` | Navigate to a URL |
83
+ | `browser_screenshot()` | Take a screenshot |
84
+ | `browser_click(selector)` | Click an element |
85
+ | `browser_type(selector, text)` | Type text into an element |
86
+ | `browser_evaluate(expression)` | Evaluate JavaScript |
87
+ | `browser_content()` | Get current page content |
88
+ | `browser_close()` | Close the browser |
89
+
90
+ ## Context Manager
91
+
92
+ ```python
93
+ with CageBro("http://localhost:8080") as cage:
94
+ cage.shell_exec("echo hello")
95
+ ```
96
+
97
+ ## License
98
+
99
+ Apache-2.0
@@ -0,0 +1,9 @@
1
+ README.md
2
+ pyproject.toml
3
+ cage_bro/__init__.py
4
+ cage_bro/client.py
5
+ cage_bro.egg-info/PKG-INFO
6
+ cage_bro.egg-info/SOURCES.txt
7
+ cage_bro.egg-info/dependency_links.txt
8
+ cage_bro.egg-info/requires.txt
9
+ cage_bro.egg-info/top_level.txt
@@ -0,0 +1,5 @@
1
+ httpx>=0.24.0
2
+
3
+ [dev]
4
+ pytest
5
+ pytest-asyncio
@@ -0,0 +1 @@
1
+ cage_bro
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cage-bro"
7
+ version = "0.1.0"
8
+ description = "Python SDK for cage-bro sandbox"
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ requires-python = ">=3.8"
12
+ dependencies = [
13
+ "httpx>=0.24.0",
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ dev = [
18
+ "pytest",
19
+ "pytest-asyncio",
20
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+