pygent 0.1.0__tar.gz → 0.1.2__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.
- pygent-0.1.2/PKG-INFO +19 -0
- pygent-0.1.2/README.md +81 -0
- {pygent-0.1.0 → pygent-0.1.2}/pygent/__init__.py +1 -1
- {pygent-0.1.0 → pygent-0.1.2}/pygent/agent.py +7 -4
- pygent-0.1.2/pygent/cli.py +12 -0
- pygent-0.1.2/pygent/openai_compat.py +71 -0
- pygent-0.1.2/pygent/runtime.py +86 -0
- {pygent-0.1.0 → pygent-0.1.2}/pygent/tools.py +1 -1
- pygent-0.1.2/pygent.egg-info/PKG-INFO +19 -0
- {pygent-0.1.0 → pygent-0.1.2}/pygent.egg-info/SOURCES.txt +1 -0
- {pygent-0.1.0 → pygent-0.1.2}/pygent.egg-info/requires.txt +6 -2
- pygent-0.1.2/pyproject.toml +30 -0
- pygent-0.1.0/PKG-INFO +0 -15
- pygent-0.1.0/README.md +0 -40
- pygent-0.1.0/pygent/cli.py +0 -5
- pygent-0.1.0/pygent/runtime.py +0 -53
- pygent-0.1.0/pygent.egg-info/PKG-INFO +0 -15
- pygent-0.1.0/pyproject.toml +0 -25
- {pygent-0.1.0 → pygent-0.1.2}/LICENSE +0 -0
- {pygent-0.1.0 → pygent-0.1.2}/pygent/py.typed +0 -0
- {pygent-0.1.0 → pygent-0.1.2}/pygent.egg-info/dependency_links.txt +0 -0
- {pygent-0.1.0 → pygent-0.1.2}/pygent.egg-info/entry_points.txt +0 -0
- {pygent-0.1.0 → pygent-0.1.2}/pygent.egg-info/top_level.txt +0 -0
- {pygent-0.1.0 → pygent-0.1.2}/setup.cfg +0 -0
- {pygent-0.1.0 → pygent-0.1.2}/tests/test_tools.py +0 -0
- {pygent-0.1.0 → pygent-0.1.2}/tests/test_version.py +0 -0
pygent-0.1.2/PKG-INFO
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: pygent
|
3
|
+
Version: 0.1.2
|
4
|
+
Summary: Pygent is a minimalist coding assistant that runs commands in a Docker container when available and falls back to local execution. See https://marianochaves.github.io/pygent for documentation and https://github.com/marianochaves/pygent for the source code.
|
5
|
+
Author-email: Mariano Chaves <mchaves.software@gmail.com>
|
6
|
+
Project-URL: Documentation, https://marianochaves.github.io/pygent
|
7
|
+
Project-URL: Repository, https://github.com/marianochaves/pygent
|
8
|
+
Requires-Python: >=3.9
|
9
|
+
License-File: LICENSE
|
10
|
+
Requires-Dist: rich>=13.7.0
|
11
|
+
Provides-Extra: llm
|
12
|
+
Requires-Dist: openai>=1.0.0; extra == "llm"
|
13
|
+
Provides-Extra: test
|
14
|
+
Requires-Dist: pytest; extra == "test"
|
15
|
+
Provides-Extra: docs
|
16
|
+
Requires-Dist: mkdocs; extra == "docs"
|
17
|
+
Provides-Extra: docker
|
18
|
+
Requires-Dist: docker>=7.0.0; extra == "docker"
|
19
|
+
Dynamic: license-file
|
pygent-0.1.2/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Pygent
|
2
|
+
|
3
|
+
Pygent is a coding assistant that executes each request inside an isolated Docker container whenever possible. If Docker is unavailable (for instance on some Windows setups) the commands are executed locally instead.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
* Runs commands in ephemeral containers (default image `python:3.12-slim`).
|
8
|
+
* Integrates with OpenAI-compatible models to orchestrate each step.
|
9
|
+
* Persists the conversation history during the session.
|
10
|
+
* Provides a small Python API for use in other projects.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Installing from source is recommended:
|
15
|
+
|
16
|
+
```bash
|
17
|
+
pip install -e .
|
18
|
+
```
|
19
|
+
|
20
|
+
Python ≥ 3.9 is required. The only runtime dependency is `rich`.
|
21
|
+
Install any OpenAI-compatible library such as `openai` or `litellm` separately to enable model access.
|
22
|
+
To run commands in Docker containers also install `pygent[docker]`.
|
23
|
+
|
24
|
+
## Configuration
|
25
|
+
|
26
|
+
Behaviour can be adjusted via environment variables:
|
27
|
+
|
28
|
+
* `OPENAI_API_KEY` – key used to access the OpenAI API.
|
29
|
+
* `PYGENT_MODEL` – model name used for requests (default `gpt-4o-mini-preview`).
|
30
|
+
* `PYGENT_IMAGE` – Docker image to create the container (default `python:3.12-slim`).
|
31
|
+
* `PYGENT_USE_DOCKER` – set to `0` to disable Docker and run locally.
|
32
|
+
|
33
|
+
## CLI usage
|
34
|
+
|
35
|
+
After installing run:
|
36
|
+
|
37
|
+
```bash
|
38
|
+
pygent
|
39
|
+
```
|
40
|
+
|
41
|
+
Use `--docker` to run commands inside a container (requires
|
42
|
+
`pygent[docker]`). Use `--no-docker` or set `PYGENT_USE_DOCKER=0`
|
43
|
+
to force local execution.
|
44
|
+
|
45
|
+
Type messages normally; use `/exit` to end the session. Each command is executed in the container and the result shown in the terminal.
|
46
|
+
|
47
|
+
## API usage
|
48
|
+
|
49
|
+
You can also interact directly with the Python code:
|
50
|
+
|
51
|
+
```python
|
52
|
+
from pygent import Agent
|
53
|
+
|
54
|
+
ag = Agent()
|
55
|
+
ag.step("echo 'Hello World'")
|
56
|
+
# ... more steps
|
57
|
+
ag.runtime.cleanup()
|
58
|
+
```
|
59
|
+
|
60
|
+
See the `examples/` folder for more complete scripts.
|
61
|
+
|
62
|
+
## Development
|
63
|
+
|
64
|
+
1. Install the test dependencies:
|
65
|
+
|
66
|
+
```bash
|
67
|
+
pip install -e .[test]
|
68
|
+
```
|
69
|
+
|
70
|
+
2. Run the test suite:
|
71
|
+
|
72
|
+
```bash
|
73
|
+
pytest
|
74
|
+
```
|
75
|
+
|
76
|
+
Use `mkdocs serve` to build the documentation locally.
|
77
|
+
|
78
|
+
## License
|
79
|
+
|
80
|
+
This project is released under the MIT license. See the `LICENSE` file for details.
|
81
|
+
|
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Orchestration layer: receives messages, calls the OpenAI-compatible backend and dispatches tools."""
|
2
2
|
|
3
3
|
import json
|
4
4
|
import os
|
@@ -8,7 +8,10 @@ import time
|
|
8
8
|
from dataclasses import dataclass, field
|
9
9
|
from typing import Any, Dict, List
|
10
10
|
|
11
|
-
|
11
|
+
try:
|
12
|
+
import openai # type: ignore
|
13
|
+
except ModuleNotFoundError: # pragma: no cover - fallback to bundled client
|
14
|
+
from . import openai_compat as openai
|
12
15
|
from rich.console import Console
|
13
16
|
from rich.panel import Panel
|
14
17
|
|
@@ -55,8 +58,8 @@ class Agent:
|
|
55
58
|
console.print(assistant_msg.content)
|
56
59
|
|
57
60
|
|
58
|
-
def run_interactive() -> None: # pragma: no cover
|
59
|
-
agent = Agent()
|
61
|
+
def run_interactive(use_docker: bool | None = None) -> None: # pragma: no cover
|
62
|
+
agent = Agent(runtime=Runtime(use_docker=use_docker))
|
60
63
|
console.print("[bold green]Pygent[/] iniciado. (digite /exit para sair)")
|
61
64
|
try:
|
62
65
|
while True:
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"""Command-line entry point for Pygent."""
|
2
|
+
import argparse
|
3
|
+
|
4
|
+
from .agent import run_interactive
|
5
|
+
|
6
|
+
def main() -> None: # pragma: no cover
|
7
|
+
parser = argparse.ArgumentParser(prog="pygent")
|
8
|
+
parser.add_argument("--docker", dest="use_docker", action="store_true", help="run commands in a Docker container")
|
9
|
+
parser.add_argument("--no-docker", dest="use_docker", action="store_false", help="run locally")
|
10
|
+
parser.set_defaults(use_docker=None)
|
11
|
+
args = parser.parse_args()
|
12
|
+
run_interactive(use_docker=args.use_docker)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import os
|
2
|
+
import json
|
3
|
+
from dataclasses import dataclass
|
4
|
+
from typing import Any, Dict, List
|
5
|
+
from urllib import request
|
6
|
+
|
7
|
+
OPENAI_BASE_URL = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
|
8
|
+
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
|
9
|
+
|
10
|
+
@dataclass
|
11
|
+
class ToolCallFunction:
|
12
|
+
name: str
|
13
|
+
arguments: str
|
14
|
+
|
15
|
+
@dataclass
|
16
|
+
class ToolCall:
|
17
|
+
id: str
|
18
|
+
type: str
|
19
|
+
function: ToolCallFunction
|
20
|
+
|
21
|
+
@dataclass
|
22
|
+
class Message:
|
23
|
+
role: str
|
24
|
+
content: str | None = None
|
25
|
+
tool_calls: List[ToolCall] | None = None
|
26
|
+
|
27
|
+
@dataclass
|
28
|
+
class Choice:
|
29
|
+
message: Message
|
30
|
+
|
31
|
+
@dataclass
|
32
|
+
class ChatCompletion:
|
33
|
+
choices: List[Choice]
|
34
|
+
|
35
|
+
|
36
|
+
def _post(path: str, payload: Dict[str, Any]) -> Dict[str, Any]:
|
37
|
+
data = json.dumps(payload).encode()
|
38
|
+
headers = {"Content-Type": "application/json"}
|
39
|
+
if OPENAI_API_KEY:
|
40
|
+
headers["Authorization"] = f"Bearer {OPENAI_API_KEY}"
|
41
|
+
req = request.Request(f"{OPENAI_BASE_URL}{path}", data=data, headers=headers)
|
42
|
+
with request.urlopen(req) as resp:
|
43
|
+
return json.loads(resp.read().decode())
|
44
|
+
|
45
|
+
|
46
|
+
class _ChatCompletions:
|
47
|
+
def create(self, model: str, messages: List[Dict[str, Any]], tools: Any = None, tool_choice: str | None = "auto") -> ChatCompletion:
|
48
|
+
payload: Dict[str, Any] = {"model": model, "messages": messages}
|
49
|
+
if tools is not None:
|
50
|
+
payload["tools"] = tools
|
51
|
+
if tool_choice is not None:
|
52
|
+
payload["tool_choice"] = tool_choice
|
53
|
+
raw = _post("/chat/completions", payload)
|
54
|
+
choices: List[Choice] = []
|
55
|
+
for ch in raw.get("choices", []):
|
56
|
+
msg_data = ch.get("message", {})
|
57
|
+
tool_calls = []
|
58
|
+
for tc in msg_data.get("tool_calls", []):
|
59
|
+
func = ToolCallFunction(**tc.get("function", {}))
|
60
|
+
tool_calls.append(ToolCall(id=tc.get("id", ""), type=tc.get("type", ""), function=func))
|
61
|
+
msg = Message(role=msg_data.get("role", ""), content=msg_data.get("content"), tool_calls=tool_calls or None)
|
62
|
+
choices.append(Choice(message=msg))
|
63
|
+
return ChatCompletion(choices=choices)
|
64
|
+
|
65
|
+
|
66
|
+
class _Chat:
|
67
|
+
def __init__(self) -> None:
|
68
|
+
self.completions = _ChatCompletions()
|
69
|
+
|
70
|
+
|
71
|
+
chat = _Chat()
|
@@ -0,0 +1,86 @@
|
|
1
|
+
"""Run commands in a Docker container, falling back to local execution if needed."""
|
2
|
+
from __future__ import annotations
|
3
|
+
|
4
|
+
import os
|
5
|
+
import shutil
|
6
|
+
import subprocess
|
7
|
+
import tempfile
|
8
|
+
import uuid
|
9
|
+
from pathlib import Path
|
10
|
+
from typing import Union
|
11
|
+
|
12
|
+
try: # Docker may not be available (e.g. Windows without Docker)
|
13
|
+
import docker # type: ignore
|
14
|
+
except Exception: # pragma: no cover - optional dependency
|
15
|
+
docker = None
|
16
|
+
|
17
|
+
|
18
|
+
class Runtime:
|
19
|
+
"""Executes commands in a Docker container or locally if Docker is unavailable."""
|
20
|
+
|
21
|
+
def __init__(self, image: str | None = None, use_docker: bool | None = None) -> None:
|
22
|
+
self.base_dir = Path(tempfile.mkdtemp(prefix="pygent_"))
|
23
|
+
self.image = image or os.getenv("PYGENT_IMAGE", "python:3.12-slim")
|
24
|
+
env_opt = os.getenv("PYGENT_USE_DOCKER")
|
25
|
+
if use_docker is None:
|
26
|
+
use_docker = (env_opt != "0") if env_opt is not None else True
|
27
|
+
self._use_docker = bool(docker) and use_docker
|
28
|
+
if self._use_docker:
|
29
|
+
try:
|
30
|
+
self.client = docker.from_env()
|
31
|
+
self.container = self.client.containers.run(
|
32
|
+
self.image,
|
33
|
+
name=f"pygent-{uuid.uuid4().hex[:8]}",
|
34
|
+
command="sleep infinity",
|
35
|
+
volumes={str(self.base_dir): {"bind": "/workspace", "mode": "rw"}},
|
36
|
+
working_dir="/workspace",
|
37
|
+
detach=True,
|
38
|
+
tty=True,
|
39
|
+
network_disabled=True,
|
40
|
+
mem_limit="512m",
|
41
|
+
pids_limit=256,
|
42
|
+
)
|
43
|
+
except Exception:
|
44
|
+
self._use_docker = False
|
45
|
+
if not self._use_docker:
|
46
|
+
self.client = None
|
47
|
+
self.container = None
|
48
|
+
|
49
|
+
# ---------------- public API ----------------
|
50
|
+
def bash(self, cmd: str, timeout: int = 30) -> str:
|
51
|
+
"""Run a command in the container or locally and return the output."""
|
52
|
+
if self._use_docker and self.container is not None:
|
53
|
+
res = self.container.exec_run(
|
54
|
+
cmd,
|
55
|
+
workdir="/workspace",
|
56
|
+
demux=True,
|
57
|
+
tty=False,
|
58
|
+
timeout=timeout,
|
59
|
+
)
|
60
|
+
stdout, stderr = (
|
61
|
+
res.output if isinstance(res.output, tuple) else (res.output, b"")
|
62
|
+
)
|
63
|
+
return (stdout or b"").decode() + (stderr or b"").decode()
|
64
|
+
proc = subprocess.run(
|
65
|
+
cmd,
|
66
|
+
shell=True,
|
67
|
+
cwd=self.base_dir,
|
68
|
+
capture_output=True,
|
69
|
+
text=True,
|
70
|
+
timeout=timeout,
|
71
|
+
)
|
72
|
+
return proc.stdout + proc.stderr
|
73
|
+
|
74
|
+
def write_file(self, rel_path: Union[str, Path], content: str) -> str:
|
75
|
+
p = self.base_dir / rel_path
|
76
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
77
|
+
p.write_text(content)
|
78
|
+
return f"Wrote {p.relative_to(self.base_dir)}"
|
79
|
+
|
80
|
+
def cleanup(self) -> None:
|
81
|
+
if self._use_docker and self.container is not None:
|
82
|
+
try:
|
83
|
+
self.container.kill()
|
84
|
+
finally:
|
85
|
+
self.container.remove(force=True)
|
86
|
+
shutil.rmtree(self.base_dir, ignore_errors=True)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: pygent
|
3
|
+
Version: 0.1.2
|
4
|
+
Summary: Pygent is a minimalist coding assistant that runs commands in a Docker container when available and falls back to local execution. See https://marianochaves.github.io/pygent for documentation and https://github.com/marianochaves/pygent for the source code.
|
5
|
+
Author-email: Mariano Chaves <mchaves.software@gmail.com>
|
6
|
+
Project-URL: Documentation, https://marianochaves.github.io/pygent
|
7
|
+
Project-URL: Repository, https://github.com/marianochaves/pygent
|
8
|
+
Requires-Python: >=3.9
|
9
|
+
License-File: LICENSE
|
10
|
+
Requires-Dist: rich>=13.7.0
|
11
|
+
Provides-Extra: llm
|
12
|
+
Requires-Dist: openai>=1.0.0; extra == "llm"
|
13
|
+
Provides-Extra: test
|
14
|
+
Requires-Dist: pytest; extra == "test"
|
15
|
+
Provides-Extra: docs
|
16
|
+
Requires-Dist: mkdocs; extra == "docs"
|
17
|
+
Provides-Extra: docker
|
18
|
+
Requires-Dist: docker>=7.0.0; extra == "docker"
|
19
|
+
Dynamic: license-file
|
@@ -0,0 +1,30 @@
|
|
1
|
+
[project]
|
2
|
+
name = "pygent"
|
3
|
+
version = "0.1.2"
|
4
|
+
description = "Pygent is a minimalist coding assistant that runs commands in a Docker container when available and falls back to local execution. See https://marianochaves.github.io/pygent for documentation and https://github.com/marianochaves/pygent for the source code."
|
5
|
+
authors = [ { name = "Mariano Chaves", email = "mchaves.software@gmail.com" } ]
|
6
|
+
requires-python = ">=3.9"
|
7
|
+
dependencies = [
|
8
|
+
"rich>=13.7.0" # colored output (optional)
|
9
|
+
]
|
10
|
+
|
11
|
+
[project.optional-dependencies]
|
12
|
+
llm = ["openai>=1.0.0"] # OpenAI-compatible library (optional)
|
13
|
+
test = ["pytest"]
|
14
|
+
docs = ["mkdocs"]
|
15
|
+
docker = ["docker>=7.0.0"]
|
16
|
+
|
17
|
+
[project.urls]
|
18
|
+
Documentation = "https://marianochaves.github.io/pygent"
|
19
|
+
Repository = "https://github.com/marianochaves/pygent"
|
20
|
+
|
21
|
+
[project.scripts]
|
22
|
+
pygent = "pygent.cli:main"
|
23
|
+
|
24
|
+
|
25
|
+
[tool.setuptools.package-data]
|
26
|
+
"pygent" = ["py.typed"]
|
27
|
+
|
28
|
+
[build-system]
|
29
|
+
requires = ["setuptools>=64", "wheel"]
|
30
|
+
build-backend = "setuptools.build_meta"
|
pygent-0.1.0/PKG-INFO
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: pygent
|
3
|
-
Version: 0.1.0
|
4
|
-
Summary: A minimal agentic coding assistant that runs each task in a secure container.
|
5
|
-
Author-email: Mariano Chaves <mchaves.software@gmail.com>
|
6
|
-
Requires-Python: >=3.9
|
7
|
-
License-File: LICENSE
|
8
|
-
Requires-Dist: openai>=1.0.0
|
9
|
-
Requires-Dist: docker>=7.0.0
|
10
|
-
Requires-Dist: rich>=13.7.0
|
11
|
-
Provides-Extra: test
|
12
|
-
Requires-Dist: pytest; extra == "test"
|
13
|
-
Provides-Extra: docs
|
14
|
-
Requires-Dist: mkdocs; extra == "docs"
|
15
|
-
Dynamic: license-file
|
pygent-0.1.0/README.md
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# Pygent
|
2
|
-
|
3
|
-
Pygent é um assistente de código minimalista que executa cada tarefa em um
|
4
|
-
container Docker isolado. O objetivo é facilitar execução de comandos de forma
|
5
|
-
segura e reprodutível, mantendo o histórico de mensagens da conversa.
|
6
|
-
|
7
|
-
## Instalação
|
8
|
-
|
9
|
-
Recomendação mais simples é usar `pip`:
|
10
|
-
|
11
|
-
```bash
|
12
|
-
pip install -e .
|
13
|
-
```
|
14
|
-
|
15
|
-
O projeto requer Python ≥ 3.9 e depende de `docker`, `openai` e `rich`.
|
16
|
-
|
17
|
-
## Uso via CLI
|
18
|
-
|
19
|
-
Após instalado, inicie a interface interativa com:
|
20
|
-
|
21
|
-
```bash
|
22
|
-
pygent
|
23
|
-
```
|
24
|
-
|
25
|
-
Digita mensagens normalmente e utilize `/exit` para sair.
|
26
|
-
|
27
|
-
## Uso via API
|
28
|
-
|
29
|
-
Também é possível integrar diretamente com o código Python:
|
30
|
-
|
31
|
-
```python
|
32
|
-
from pygent import Agent
|
33
|
-
|
34
|
-
ag = Agent()
|
35
|
-
ag.step("echo hello") # roda dentro do container
|
36
|
-
ag.runtime.cleanup()
|
37
|
-
```
|
38
|
-
|
39
|
-
Veja a pasta `examples/` para scripts mais completos.
|
40
|
-
|
pygent-0.1.0/pygent/cli.py
DELETED
pygent-0.1.0/pygent/runtime.py
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
"""Isola as execuções num container Docker efêmero."""
|
2
|
-
from __future__ import annotations
|
3
|
-
|
4
|
-
import os
|
5
|
-
import shutil
|
6
|
-
import tempfile
|
7
|
-
import subprocess
|
8
|
-
import uuid
|
9
|
-
from pathlib import Path
|
10
|
-
from typing import Union
|
11
|
-
|
12
|
-
import docker
|
13
|
-
|
14
|
-
|
15
|
-
class Runtime:
|
16
|
-
"""Cada instância corresponde a um diretório + container dedicados."""
|
17
|
-
|
18
|
-
def __init__(self, image: str | None = None) -> None:
|
19
|
-
self.base_dir = Path(tempfile.mkdtemp(prefix="pygent_"))
|
20
|
-
self.image = image or os.getenv("PYGENT_IMAGE", "python:3.12-slim")
|
21
|
-
self.client = docker.from_env()
|
22
|
-
self.container = self.client.containers.run(
|
23
|
-
self.image,
|
24
|
-
name=f"pygent-{uuid.uuid4().hex[:8]}",
|
25
|
-
command="sleep infinity",
|
26
|
-
volumes={str(self.base_dir): {"bind": "/workspace", "mode": "rw"}},
|
27
|
-
working_dir="/workspace",
|
28
|
-
detach=True,
|
29
|
-
tty=True,
|
30
|
-
network_disabled=True,
|
31
|
-
mem_limit="512m",
|
32
|
-
pids_limit=256,
|
33
|
-
)
|
34
|
-
|
35
|
-
# ---------------- public API ----------------
|
36
|
-
def bash(self, cmd: str, timeout: int = 30) -> str:
|
37
|
-
"""Roda comando dentro do container e devolve saída combinada."""
|
38
|
-
res = self.container.exec_run(cmd, workdir="/workspace", demux=True, tty=False, timeout=timeout)
|
39
|
-
stdout, stderr = res.output if isinstance(res.output, tuple) else (res.output, b"")
|
40
|
-
return (stdout or b"").decode() + (stderr or b"").decode()
|
41
|
-
|
42
|
-
def write_file(self, rel_path: Union[str, Path], content: str) -> str:
|
43
|
-
p = self.base_dir / rel_path
|
44
|
-
p.parent.mkdir(parents=True, exist_ok=True)
|
45
|
-
p.write_text(content)
|
46
|
-
return f"Wrote {p.relative_to(self.base_dir)}"
|
47
|
-
|
48
|
-
def cleanup(self) -> None:
|
49
|
-
try:
|
50
|
-
self.container.kill()
|
51
|
-
finally:
|
52
|
-
self.container.remove(force=True)
|
53
|
-
shutil.rmtree(self.base_dir, ignore_errors=True)
|
@@ -1,15 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: pygent
|
3
|
-
Version: 0.1.0
|
4
|
-
Summary: A minimal agentic coding assistant that runs each task in a secure container.
|
5
|
-
Author-email: Mariano Chaves <mchaves.software@gmail.com>
|
6
|
-
Requires-Python: >=3.9
|
7
|
-
License-File: LICENSE
|
8
|
-
Requires-Dist: openai>=1.0.0
|
9
|
-
Requires-Dist: docker>=7.0.0
|
10
|
-
Requires-Dist: rich>=13.7.0
|
11
|
-
Provides-Extra: test
|
12
|
-
Requires-Dist: pytest; extra == "test"
|
13
|
-
Provides-Extra: docs
|
14
|
-
Requires-Dist: mkdocs; extra == "docs"
|
15
|
-
Dynamic: license-file
|
pygent-0.1.0/pyproject.toml
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
[project]
|
2
|
-
name = "pygent"
|
3
|
-
version = "0.1.0"
|
4
|
-
description = "A minimal agentic coding assistant that runs each task in a secure container."
|
5
|
-
authors = [ { name = "Mariano Chaves", email = "mchaves.software@gmail.com" } ]
|
6
|
-
requires-python = ">=3.9"
|
7
|
-
dependencies = [
|
8
|
-
"openai>=1.0.0", # interface com modelos da OpenAI
|
9
|
-
"docker>=7.0.0", # manipular containers
|
10
|
-
"rich>=13.7.0" # saídas coloridas (opcional)
|
11
|
-
]
|
12
|
-
|
13
|
-
[project.scripts]
|
14
|
-
pygent = "pygent.cli:main"
|
15
|
-
|
16
|
-
[project.optional-dependencies]
|
17
|
-
test = ["pytest"]
|
18
|
-
docs = ["mkdocs"]
|
19
|
-
|
20
|
-
[tool.setuptools.package-data]
|
21
|
-
"pygent" = ["py.typed"]
|
22
|
-
|
23
|
-
[build-system]
|
24
|
-
requires = ["setuptools>=64", "wheel"]
|
25
|
-
build-backend = "setuptools.build_meta"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|