pygent 0.1.5__tar.gz → 0.1.6__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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygent
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
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
@@ -8,8 +8,7 @@ Project-URL: Repository, https://github.com/marianochaves/pygent
8
8
  Requires-Python: >=3.9
9
9
  License-File: LICENSE
10
10
  Requires-Dist: rich>=13.7.0
11
- Provides-Extra: llm
12
- Requires-Dist: openai>=1.0.0; extra == "llm"
11
+ Requires-Dist: openai>=1.0.0
13
12
  Provides-Extra: test
14
13
  Requires-Dist: pytest; extra == "test"
15
14
  Provides-Extra: docs
@@ -18,8 +18,7 @@ Installing from source is recommended:
18
18
  pip install -e .
19
19
  ```
20
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.
21
+ Python ≥ 3.9 is required. The package now bundles the `openai` client for model access.
23
22
  To run commands in Docker containers also install `pygent[docker]`.
24
23
 
25
24
  ## Configuration
@@ -35,7 +35,7 @@ class Agent:
35
35
  {"role": "system", "content": SYSTEM_MSG}
36
36
  ])
37
37
 
38
- def step(self, user_msg: str) -> None:
38
+ def step(self, user_msg: str):
39
39
  self.history.append({"role": "user", "content": user_msg})
40
40
  assistant_msg = self.model.chat(self.history, self.model_name, TOOL_SCHEMAS)
41
41
  self.history.append(assistant_msg)
@@ -47,6 +47,18 @@ class Agent:
47
47
  console.print(Panel(output, title=f"tool:{call.function.name}"))
48
48
  else:
49
49
  console.print(assistant_msg.content)
50
+ return assistant_msg
51
+
52
+ def run_until_stop(self, user_msg: str, max_steps: int = 10) -> None:
53
+ """Run steps automatically until the model calls the ``stop`` tool or
54
+ the step limit is reached."""
55
+ msg = user_msg
56
+ for _ in range(max_steps):
57
+ assistant_msg = self.step(msg)
58
+ calls = assistant_msg.tool_calls or []
59
+ if any(c.function.name == "stop" for c in calls):
60
+ break
61
+ msg = "continue"
50
62
 
51
63
 
52
64
  def run_interactive(use_docker: bool | None = None) -> None: # pragma: no cover
@@ -35,6 +35,14 @@ TOOL_SCHEMAS = [
35
35
  },
36
36
  },
37
37
  },
38
+ {
39
+ "type": "function",
40
+ "function": {
41
+ "name": "stop",
42
+ "description": "Stop the autonomous loop.",
43
+ "parameters": {"type": "object", "properties": {}},
44
+ },
45
+ },
38
46
  ]
39
47
 
40
48
  # --------------- dispatcher ---------------
@@ -47,4 +55,6 @@ def execute_tool(call: Any, rt: Runtime) -> str: # pragma: no cover, Any→open
47
55
  return rt.bash(**args)
48
56
  if name == "write_file":
49
57
  return rt.write_file(**args)
58
+ if name == "stop":
59
+ return "Stopping."
50
60
  return f"⚠️ unknown tool {name}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygent
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
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
@@ -8,8 +8,7 @@ Project-URL: Repository, https://github.com/marianochaves/pygent
8
8
  Requires-Python: >=3.9
9
9
  License-File: LICENSE
10
10
  Requires-Dist: rich>=13.7.0
11
- Provides-Extra: llm
12
- Requires-Dist: openai>=1.0.0; extra == "llm"
11
+ Requires-Dist: openai>=1.0.0
13
12
  Provides-Extra: test
14
13
  Requires-Dist: pytest; extra == "test"
15
14
  Provides-Extra: docs
@@ -17,6 +17,7 @@ pygent.egg-info/dependency_links.txt
17
17
  pygent.egg-info/entry_points.txt
18
18
  pygent.egg-info/requires.txt
19
19
  pygent.egg-info/top_level.txt
20
+ tests/test_autorun.py
20
21
  tests/test_custom_model.py
21
22
  tests/test_tools.py
22
23
  tests/test_version.py
@@ -1,4 +1,5 @@
1
1
  rich>=13.7.0
2
+ openai>=1.0.0
2
3
 
3
4
  [docker]
4
5
  docker>=7.0.0
@@ -6,9 +7,6 @@ docker>=7.0.0
6
7
  [docs]
7
8
  mkdocs
8
9
 
9
- [llm]
10
- openai>=1.0.0
11
-
12
10
  [test]
13
11
  pytest
14
12
 
@@ -1,15 +1,15 @@
1
1
  [project]
2
2
  name = "pygent"
3
- version = "0.1.5"
3
+ version = "0.1.6"
4
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
- "rich>=13.7.0" # colored output (optional)
8
+ "rich>=13.7.0", # colored output (optional)
9
+ "openai>=1.0.0",
9
10
  ]
10
11
 
11
12
  [project.optional-dependencies]
12
- llm = ["openai>=1.0.0"] # OpenAI-compatible library (optional)
13
13
  test = ["pytest"]
14
14
  docs = ["mkdocs"]
15
15
  docker = ["docker>=7.0.0"]
@@ -0,0 +1,69 @@
1
+ import os
2
+ import sys
3
+ import types
4
+
5
+ sys.modules.setdefault('openai', types.ModuleType('openai'))
6
+ sys.modules.setdefault('docker', types.ModuleType('docker'))
7
+ rich_mod = types.ModuleType('rich')
8
+ console_mod = types.ModuleType('console')
9
+ console_mod.Console = lambda *a, **k: type('C', (), {'print': lambda *a, **k: None})()
10
+ panel_mod = types.ModuleType('panel')
11
+ panel_mod.Panel = lambda *a, **k: None
12
+ sys.modules.setdefault('rich', rich_mod)
13
+ sys.modules.setdefault('rich.console', console_mod)
14
+ sys.modules.setdefault('rich.panel', panel_mod)
15
+
16
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
17
+
18
+ from pygent import Agent, openai_compat
19
+
20
+ class DummyModel:
21
+ def __init__(self):
22
+ self.count = 0
23
+ def chat(self, messages, model, tools):
24
+ self.count += 1
25
+ if self.count == 1:
26
+ return openai_compat.Message(
27
+ role='assistant',
28
+ content=None,
29
+ tool_calls=[
30
+ openai_compat.ToolCall(
31
+ id='1',
32
+ type='function',
33
+ function=openai_compat.ToolCallFunction(
34
+ name='bash',
35
+ arguments='{"cmd": "ls"}'
36
+ )
37
+ )
38
+ ]
39
+ )
40
+ else:
41
+ return openai_compat.Message(
42
+ role='assistant',
43
+ content=None,
44
+ tool_calls=[
45
+ openai_compat.ToolCall(
46
+ id='2',
47
+ type='function',
48
+ function=openai_compat.ToolCallFunction(
49
+ name='stop',
50
+ arguments='{}'
51
+ )
52
+ )
53
+ ]
54
+ )
55
+
56
+ class DummyRuntime:
57
+ def bash(self, cmd: str):
58
+ return f"ran {cmd}"
59
+ def write_file(self, path: str, content: str):
60
+ return f"wrote {path}"
61
+
62
+
63
+ def test_run_until_stop():
64
+ ag = Agent(runtime=DummyRuntime(), model=DummyModel())
65
+ ag.run_until_stop('start', max_steps=5)
66
+ assert any(call.function.name == 'stop'
67
+ for msg in ag.history
68
+ if hasattr(msg, 'tool_calls') and msg.tool_calls
69
+ for call in msg.tool_calls)
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
File without changes