pygent 0.1.0__tar.gz → 0.1.1__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.1/PKG-INFO +18 -0
- pygent-0.1.1/README.md +79 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent/agent.py +2 -2
- pygent-0.1.1/pygent/cli.py +12 -0
- pygent-0.1.1/pygent/runtime.py +86 -0
- pygent-0.1.1/pygent.egg-info/PKG-INFO +18 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent.egg-info/requires.txt +3 -1
- {pygent-0.1.0 → pygent-0.1.1}/pyproject.toml +7 -3
- 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 → pygent-0.1.1}/LICENSE +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent/__init__.py +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent/py.typed +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent/tools.py +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent.egg-info/SOURCES.txt +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent.egg-info/dependency_links.txt +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent.egg-info/entry_points.txt +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/pygent.egg-info/top_level.txt +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/setup.cfg +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/tests/test_tools.py +0 -0
- {pygent-0.1.0 → pygent-0.1.1}/tests/test_version.py +0 -0
pygent-0.1.1/PKG-INFO
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: pygent
|
3
|
+
Version: 0.1.1
|
4
|
+
Summary: Pygent é um assistente de código minimalista que executa comandos em contêiner Docker quando disponível, com fallback para execução local. Veja https://marianochaves.github.io/pygent para a documentação e https://github.com/marianochaves/pygent para o código-fonte.
|
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: openai>=1.0.0
|
11
|
+
Requires-Dist: rich>=13.7.0
|
12
|
+
Provides-Extra: test
|
13
|
+
Requires-Dist: pytest; extra == "test"
|
14
|
+
Provides-Extra: docs
|
15
|
+
Requires-Dist: mkdocs; extra == "docs"
|
16
|
+
Provides-Extra: docker
|
17
|
+
Requires-Dist: docker>=7.0.0; extra == "docker"
|
18
|
+
Dynamic: license-file
|
pygent-0.1.1/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Pygent
|
2
|
+
|
3
|
+
Pygent é um assistente de código que executa cada solicitação em um container Docker isolado sempre que possível. Caso Docker não esteja disponível (por exemplo em algumas instalações do Windows), o Pygent ainda funciona executando os comandos localmente.
|
4
|
+
|
5
|
+
## Recursos
|
6
|
+
|
7
|
+
* Execução de comandos em containers efêmeros (imagem padrão `python:3.12-slim`).
|
8
|
+
* Integração com modelos da OpenAI para orquestração das etapas.
|
9
|
+
* Histórico persistente das interações durante a sessão.
|
10
|
+
* API Python simples para integração em outros projetos.
|
11
|
+
|
12
|
+
## Instalação
|
13
|
+
|
14
|
+
Recomenda-se instalar a partir do código fonte:
|
15
|
+
|
16
|
+
```bash
|
17
|
+
pip install -e .
|
18
|
+
```
|
19
|
+
|
20
|
+
É necessário possuir Python ≥ 3.9. As dependências de runtime são `openai` e `rich`. Para executar dentro de containers Docker instale também `pygent[docker]`.
|
21
|
+
|
22
|
+
## Configuração
|
23
|
+
|
24
|
+
O comportamento pode ser ajustado via variáveis de ambiente:
|
25
|
+
|
26
|
+
* `OPENAI_API_KEY` – chave para acesso à API da OpenAI.
|
27
|
+
* `PYGENT_MODEL` – modelo utilizado nas chamadas (padrão `gpt-4o-mini-preview`).
|
28
|
+
* `PYGENT_IMAGE` – imagem Docker para criar o container (padrão `python:3.12-slim`).
|
29
|
+
* `PYGENT_USE_DOCKER` – defina `0` para desabilitar Docker e executar localmente.
|
30
|
+
|
31
|
+
## Uso via CLI
|
32
|
+
|
33
|
+
Após instalar, execute:
|
34
|
+
|
35
|
+
```bash
|
36
|
+
pygent
|
37
|
+
```
|
38
|
+
|
39
|
+
Use `--docker` para executar os comandos dentro de um container (requere
|
40
|
+
`pygent[docker]`). Utilize `--no-docker` ou defina `PYGENT_USE_DOCKER=0`
|
41
|
+
para forçar a execução local.
|
42
|
+
|
43
|
+
Digite mensagens normalmente; utilize `/exit` para encerrar a sessão. Todo comando é executado dentro do container e o resultado é exibido no terminal.
|
44
|
+
|
45
|
+
## Uso via API
|
46
|
+
|
47
|
+
Também é possível interagir diretamente com o código Python:
|
48
|
+
|
49
|
+
```python
|
50
|
+
from pygent import Agent
|
51
|
+
|
52
|
+
ag = Agent()
|
53
|
+
ag.step("echo 'Ola Mundo'")
|
54
|
+
# ... demias passos
|
55
|
+
ag.runtime.cleanup()
|
56
|
+
```
|
57
|
+
|
58
|
+
Confira a pasta `examples/` para scripts mais completos.
|
59
|
+
|
60
|
+
## Desenvolvimento
|
61
|
+
|
62
|
+
1. Instale as dependências de teste:
|
63
|
+
|
64
|
+
```bash
|
65
|
+
pip install -e .[test]
|
66
|
+
```
|
67
|
+
|
68
|
+
2. Rode o conjunto de testes:
|
69
|
+
|
70
|
+
```bash
|
71
|
+
pytest
|
72
|
+
```
|
73
|
+
|
74
|
+
Para gerar a documentação localmente utilize `mkdocs serve`.
|
75
|
+
|
76
|
+
## Licença
|
77
|
+
|
78
|
+
Este projeto é distribuído sob a licença MIT. Consulte o arquivo `LICENSE` para mais detalhes.
|
79
|
+
|
@@ -55,8 +55,8 @@ class Agent:
|
|
55
55
|
console.print(assistant_msg.content)
|
56
56
|
|
57
57
|
|
58
|
-
def run_interactive() -> None: # pragma: no cover
|
59
|
-
agent = Agent()
|
58
|
+
def run_interactive(use_docker: bool | None = None) -> None: # pragma: no cover
|
59
|
+
agent = Agent(runtime=Runtime(use_docker=use_docker))
|
60
60
|
console.print("[bold green]Pygent[/] iniciado. (digite /exit para sair)")
|
61
61
|
try:
|
62
62
|
while True:
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"""Ponto de entrada da CLI do 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="executar em container Docker")
|
9
|
+
parser.add_argument("--no-docker", dest="use_docker", action="store_false", help="executar localmente")
|
10
|
+
parser.set_defaults(use_docker=None)
|
11
|
+
args = parser.parse_args()
|
12
|
+
run_interactive(use_docker=args.use_docker)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
"""Executa comandos em um container Docker, caindo para execução local se necessário."""
|
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
|
+
"""Executa comandos em um container Docker ou localmente se Docker faltar."""
|
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
|
+
"""Roda comando no container ou localmente e devolve a saída."""
|
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,18 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: pygent
|
3
|
+
Version: 0.1.1
|
4
|
+
Summary: Pygent é um assistente de código minimalista que executa comandos em contêiner Docker quando disponível, com fallback para execução local. Veja https://marianochaves.github.io/pygent para a documentação e https://github.com/marianochaves/pygent para o código-fonte.
|
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: openai>=1.0.0
|
11
|
+
Requires-Dist: rich>=13.7.0
|
12
|
+
Provides-Extra: test
|
13
|
+
Requires-Dist: pytest; extra == "test"
|
14
|
+
Provides-Extra: docs
|
15
|
+
Requires-Dist: mkdocs; extra == "docs"
|
16
|
+
Provides-Extra: docker
|
17
|
+
Requires-Dist: docker>=7.0.0; extra == "docker"
|
18
|
+
Dynamic: license-file
|
@@ -1,21 +1,25 @@
|
|
1
1
|
[project]
|
2
2
|
name = "pygent"
|
3
|
-
version = "0.1.
|
4
|
-
description = "
|
3
|
+
version = "0.1.1"
|
4
|
+
description = "Pygent é um assistente de código minimalista que executa comandos em contêiner Docker quando disponível, com fallback para execução local. Veja https://marianochaves.github.io/pygent para a documentação e https://github.com/marianochaves/pygent para o código-fonte."
|
5
5
|
authors = [ { name = "Mariano Chaves", email = "mchaves.software@gmail.com" } ]
|
6
6
|
requires-python = ">=3.9"
|
7
7
|
dependencies = [
|
8
8
|
"openai>=1.0.0", # interface com modelos da OpenAI
|
9
|
-
"docker>=7.0.0", # manipular containers
|
10
9
|
"rich>=13.7.0" # saídas coloridas (opcional)
|
11
10
|
]
|
12
11
|
|
12
|
+
[project.urls]
|
13
|
+
Documentation = "https://marianochaves.github.io/pygent"
|
14
|
+
Repository = "https://github.com/marianochaves/pygent"
|
15
|
+
|
13
16
|
[project.scripts]
|
14
17
|
pygent = "pygent.cli:main"
|
15
18
|
|
16
19
|
[project.optional-dependencies]
|
17
20
|
test = ["pytest"]
|
18
21
|
docs = ["mkdocs"]
|
22
|
+
docker = ["docker>=7.0.0"]
|
19
23
|
|
20
24
|
[tool.setuptools.package-data]
|
21
25
|
"pygent" = ["py.typed"]
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|