pygent 0.1.1__tar.gz → 0.1.3__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.
@@ -1,18 +1,21 @@
1
1
  Metadata-Version: 2.4
2
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.
3
+ Version: 0.1.3
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
5
  Author-email: Mariano Chaves <mchaves.software@gmail.com>
6
6
  Project-URL: Documentation, https://marianochaves.github.io/pygent
7
7
  Project-URL: Repository, https://github.com/marianochaves/pygent
8
8
  Requires-Python: >=3.9
9
9
  License-File: LICENSE
10
- Requires-Dist: openai>=1.0.0
11
10
  Requires-Dist: rich>=13.7.0
11
+ Provides-Extra: llm
12
+ Requires-Dist: openai>=1.0.0; extra == "llm"
12
13
  Provides-Extra: test
13
14
  Requires-Dist: pytest; extra == "test"
14
15
  Provides-Extra: docs
15
16
  Requires-Dist: mkdocs; extra == "docs"
16
17
  Provides-Extra: docker
17
18
  Requires-Dist: docker>=7.0.0; extra == "docker"
19
+ Provides-Extra: ui
20
+ Requires-Dist: gradio; extra == "ui"
18
21
  Dynamic: license-file
pygent-0.1.3/README.md ADDED
@@ -0,0 +1,104 @@
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
+ * Optional web interface via `pygent-ui`.
12
+
13
+ ## Installation
14
+
15
+ Installing from source is recommended:
16
+
17
+ ```bash
18
+ pip install -e .
19
+ ```
20
+
21
+ Python ≥ 3.9 is required. The only runtime dependency is `rich`.
22
+ Install any OpenAI-compatible library such as `openai` or `litellm` separately to enable model access.
23
+ To run commands in Docker containers also install `pygent[docker]`.
24
+
25
+ ## Configuration
26
+
27
+ Behaviour can be adjusted via environment variables:
28
+
29
+ * `OPENAI_API_KEY` &ndash; key used to access the OpenAI API.
30
+ Set this to your API key or a key from any compatible provider.
31
+ * `OPENAI_BASE_URL` &ndash; base URL for OpenAI-compatible APIs
32
+ (defaults to ``https://api.openai.com/v1``).
33
+ * `PYGENT_MODEL` &ndash; model name used for requests (default `gpt-4.1-mini`).
34
+ * `PYGENT_IMAGE` &ndash; Docker image to create the container (default `python:3.12-slim`).
35
+ * `PYGENT_USE_DOCKER` &ndash; set to `0` to disable Docker and run locally.
36
+
37
+ ## CLI usage
38
+
39
+ After installing run:
40
+
41
+ ```bash
42
+ pygent
43
+ ```
44
+
45
+ Use `--docker` to run commands inside a container (requires
46
+ `pygent[docker]`). Use `--no-docker` or set `PYGENT_USE_DOCKER=0`
47
+ to force local execution.
48
+
49
+ Type messages normally; use `/exit` to end the session. Each command is executed
50
+ in the container and the result shown in the terminal.
51
+ For a minimal web interface run `pygent-ui` instead (requires `pygent[ui]`).
52
+
53
+
54
+ ## API usage
55
+
56
+ You can also interact directly with the Python code:
57
+
58
+ ```python
59
+ from pygent import Agent
60
+
61
+ ag = Agent()
62
+ ag.step("echo 'Hello World'")
63
+ # ... more steps
64
+ ag.runtime.cleanup()
65
+ ```
66
+
67
+ See the `examples/` folder for more complete scripts.
68
+
69
+ ### Using OpenAI and other providers
70
+
71
+ Set your OpenAI key:
72
+
73
+ ```bash
74
+ export OPENAI_API_KEY="sk-..."
75
+ ```
76
+
77
+ To use a different provider, set `OPENAI_BASE_URL` to the provider
78
+ endpoint and keep `OPENAI_API_KEY` pointing to the correct key:
79
+
80
+ ```bash
81
+ export OPENAI_BASE_URL="https://openrouter.ai/api/v1"
82
+ export OPENAI_API_KEY="your-provider-key"
83
+ ```
84
+
85
+ ## Development
86
+
87
+ 1. Install the test dependencies:
88
+
89
+ ```bash
90
+ pip install -e .[test]
91
+ ```
92
+
93
+ 2. Run the test suite:
94
+
95
+ ```bash
96
+ pytest
97
+ ```
98
+
99
+ Use `mkdocs serve` to build the documentation locally.
100
+
101
+ ## License
102
+
103
+ This project is released under the MIT license. See the `LICENSE` file for details.
104
+
@@ -1,4 +1,4 @@
1
- """Pacote Pygent."""
1
+ """Pygent package."""
2
2
  from importlib import metadata as _metadata
3
3
 
4
4
  try:
@@ -1,4 +1,4 @@
1
- """Camada de orquestração: recebe mensagens, chama OpenAI, delega ferramentas."""
1
+ """Orchestration layer: receives messages, calls the OpenAI-compatible backend and dispatches tools."""
2
2
 
3
3
  import json
4
4
  import os
@@ -8,14 +8,17 @@ import time
8
8
  from dataclasses import dataclass, field
9
9
  from typing import Any, Dict, List
10
10
 
11
- import openai
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
 
15
18
  from .runtime import Runtime
16
19
  from .tools import TOOL_SCHEMAS, execute_tool
17
20
 
18
- MODEL = os.getenv("PYGENT_MODEL", "gpt-4o-mini-preview")
21
+ MODEL = os.getenv("PYGENT_MODEL", "gpt-4.1-mini")
19
22
  SYSTEM_MSG = (
20
23
  "You are Pygent, a sandboxed coding assistant.\n"
21
24
  "Respond with JSON when you need to use a tool."
@@ -1,12 +1,12 @@
1
- """Ponto de entrada da CLI do Pygent."""
1
+ """Command-line entry point for Pygent."""
2
2
  import argparse
3
3
 
4
4
  from .agent import run_interactive
5
5
 
6
6
  def main() -> None: # pragma: no cover
7
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")
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
10
  parser.set_defaults(use_docker=None)
11
11
  args = parser.parse_args()
12
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()
@@ -1,4 +1,4 @@
1
- """Executa comandos em um container Docker, caindo para execução local se necessário."""
1
+ """Run commands in a Docker container, falling back to local execution if needed."""
2
2
  from __future__ import annotations
3
3
 
4
4
  import os
@@ -16,7 +16,7 @@ except Exception: # pragma: no cover - optional dependency
16
16
 
17
17
 
18
18
  class Runtime:
19
- """Executa comandos em um container Docker ou localmente se Docker faltar."""
19
+ """Executes commands in a Docker container or locally if Docker is unavailable."""
20
20
 
21
21
  def __init__(self, image: str | None = None, use_docker: bool | None = None) -> None:
22
22
  self.base_dir = Path(tempfile.mkdtemp(prefix="pygent_"))
@@ -48,7 +48,7 @@ class Runtime:
48
48
 
49
49
  # ---------------- public API ----------------
50
50
  def bash(self, cmd: str, timeout: int = 30) -> str:
51
- """Roda comando no container ou localmente e devolve a saída."""
51
+ """Run a command in the container or locally and return the output."""
52
52
  if self._use_docker and self.container is not None:
53
53
  res = self.container.exec_run(
54
54
  cmd,
@@ -1,4 +1,4 @@
1
- """Mapa de ferramentas disponíveis para o agente."""
1
+ """Map of tools available to the agent."""
2
2
  from __future__ import annotations
3
3
  import json
4
4
  from typing import Any, Dict
@@ -0,0 +1,36 @@
1
+ from .agent import Agent, _chat
2
+ from .runtime import Runtime
3
+ from .tools import execute_tool
4
+
5
+
6
+ def run_gui(use_docker: bool | None = None) -> None:
7
+ """Launch a simple Gradio chat interface."""
8
+ try:
9
+ import gradio as gr
10
+ except ModuleNotFoundError as exc: # pragma: no cover - optional
11
+ raise SystemExit(
12
+ "Gradio is required for the GUI. Install with 'pip install pygent[ui]'"
13
+ ) from exc
14
+
15
+ agent = Agent(runtime=Runtime(use_docker=use_docker))
16
+
17
+ def _respond(message: str, history: list[tuple[str, str]] | None) -> str:
18
+ agent.history.append({"role": "user", "content": message})
19
+ assistant_msg = _chat(agent.history)
20
+ agent.history.append(assistant_msg)
21
+ reply = assistant_msg.content or ""
22
+ if assistant_msg.tool_calls:
23
+ for call in assistant_msg.tool_calls:
24
+ output = execute_tool(call, agent.runtime)
25
+ agent.history.append({"role": "tool", "content": output, "tool_call_id": call.id})
26
+ reply += f"\n\n[tool:{call.function.name}]\n{output}"
27
+ return reply
28
+
29
+ try:
30
+ gr.ChatInterface(_respond, title="Pygent").launch()
31
+ finally:
32
+ agent.runtime.cleanup()
33
+
34
+
35
+ def main() -> None: # pragma: no cover
36
+ run_gui()
@@ -1,18 +1,21 @@
1
1
  Metadata-Version: 2.4
2
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.
3
+ Version: 0.1.3
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
5
  Author-email: Mariano Chaves <mchaves.software@gmail.com>
6
6
  Project-URL: Documentation, https://marianochaves.github.io/pygent
7
7
  Project-URL: Repository, https://github.com/marianochaves/pygent
8
8
  Requires-Python: >=3.9
9
9
  License-File: LICENSE
10
- Requires-Dist: openai>=1.0.0
11
10
  Requires-Dist: rich>=13.7.0
11
+ Provides-Extra: llm
12
+ Requires-Dist: openai>=1.0.0; extra == "llm"
12
13
  Provides-Extra: test
13
14
  Requires-Dist: pytest; extra == "test"
14
15
  Provides-Extra: docs
15
16
  Requires-Dist: mkdocs; extra == "docs"
16
17
  Provides-Extra: docker
17
18
  Requires-Dist: docker>=7.0.0; extra == "docker"
19
+ Provides-Extra: ui
20
+ Requires-Dist: gradio; extra == "ui"
18
21
  Dynamic: license-file
@@ -4,9 +4,11 @@ pyproject.toml
4
4
  pygent/__init__.py
5
5
  pygent/agent.py
6
6
  pygent/cli.py
7
+ pygent/openai_compat.py
7
8
  pygent/py.typed
8
9
  pygent/runtime.py
9
10
  pygent/tools.py
11
+ pygent/ui.py
10
12
  pygent.egg-info/PKG-INFO
11
13
  pygent.egg-info/SOURCES.txt
12
14
  pygent.egg-info/dependency_links.txt
@@ -1,2 +1,3 @@
1
1
  [console_scripts]
2
2
  pygent = pygent.cli:main
3
+ pygent-ui = pygent.ui:main
@@ -1,4 +1,3 @@
1
- openai>=1.0.0
2
1
  rich>=13.7.0
3
2
 
4
3
  [docker]
@@ -7,5 +6,11 @@ docker>=7.0.0
7
6
  [docs]
8
7
  mkdocs
9
8
 
9
+ [llm]
10
+ openai>=1.0.0
11
+
10
12
  [test]
11
13
  pytest
14
+
15
+ [ui]
16
+ gradio
@@ -1,25 +1,28 @@
1
1
  [project]
2
2
  name = "pygent"
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."
3
+ version = "0.1.3"
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
5
  authors = [ { name = "Mariano Chaves", email = "mchaves.software@gmail.com" } ]
6
6
  requires-python = ">=3.9"
7
7
  dependencies = [
8
- "openai>=1.0.0", # interface com modelos da OpenAI
9
- "rich>=13.7.0" # saídas coloridas (opcional)
8
+ "rich>=13.7.0" # colored output (optional)
10
9
  ]
11
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
+ ui = ["gradio"]
17
+
12
18
  [project.urls]
13
19
  Documentation = "https://marianochaves.github.io/pygent"
14
20
  Repository = "https://github.com/marianochaves/pygent"
15
21
 
16
22
  [project.scripts]
17
23
  pygent = "pygent.cli:main"
24
+ pygent-ui = "pygent.ui:main"
18
25
 
19
- [project.optional-dependencies]
20
- test = ["pytest"]
21
- docs = ["mkdocs"]
22
- docker = ["docker>=7.0.0"]
23
26
 
24
27
  [tool.setuptools.package-data]
25
28
  "pygent" = ["py.typed"]
pygent-0.1.1/README.md DELETED
@@ -1,79 +0,0 @@
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` &ndash; chave para acesso à API da OpenAI.
27
- * `PYGENT_MODEL` &ndash; modelo utilizado nas chamadas (padrão `gpt-4o-mini-preview`).
28
- * `PYGENT_IMAGE` &ndash; imagem Docker para criar o container (padrão `python:3.12-slim`).
29
- * `PYGENT_USE_DOCKER` &ndash; 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
-
File without changes
File without changes
File without changes
File without changes
File without changes