mini-swe-agent 1.9.0__py3-none-any.whl → 1.9.1__py3-none-any.whl

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: mini-swe-agent
3
- Version: 1.9.0
3
+ Version: 1.9.1
4
4
  Summary: Nano SWE Agent - A simple AI software engineering agent
5
5
  Author-email: Kilian Lieret <kilian.lieret@posteo.de>, "Carlos E. Jimenez" <carlosej@princeton.edu>
6
6
  License: MIT License
@@ -48,6 +48,7 @@ Requires-Dist: typer
48
48
  Requires-Dist: platformdirs
49
49
  Requires-Dist: textual
50
50
  Requires-Dist: prompt_toolkit
51
+ Requires-Dist: openai<=1.99.5
51
52
  Provides-Extra: full
52
53
  Requires-Dist: mini-swe-agent[dev]; extra == "full"
53
54
  Requires-Dist: swe-rex>=1.4.0; extra == "full"
@@ -1,11 +1,11 @@
1
- mini_swe_agent-1.9.0.dist-info/licenses/LICENSE.md,sha256=D3luWPkdHAe7LBsdD4vzqDAXw6Xewb3G-uczss0uh1s,1094
2
- minisweagent/__init__.py,sha256=qO_mqMrgTR4dyM2Eih8wQvc_Gd_0SJ6vpZ6khgGIM9g,1909
1
+ mini_swe_agent-1.9.1.dist-info/licenses/LICENSE.md,sha256=D3luWPkdHAe7LBsdD4vzqDAXw6Xewb3G-uczss0uh1s,1094
2
+ minisweagent/__init__.py,sha256=28OQ0MKY6EvqfdiNiDiiP-a1aGELpGBdUjRR5rsc3-Y,1997
3
3
  minisweagent/__main__.py,sha256=FIyAOiw--c3FQ2g240FOM1FdL0lk_PxSpixu0pQ7WFo,194
4
4
  minisweagent/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  minisweagent/agents/__init__.py,sha256=cpjJLzg1IGxLM-tZpoMJV9S33ye13XtdBO0x7DU_Lrk,48
6
6
  minisweagent/agents/default.py,sha256=znoeQPSnSLNvrvVC07kwgEb-rqi0yxf3Kv7JPeMDNsI,5624
7
- minisweagent/agents/interactive.py,sha256=7HW2cffaV5f66DIjxvtIbL8mo_S5aZSwgNLSmHp6VC0,7450
8
- minisweagent/agents/interactive_textual.py,sha256=yYVtgHXdrKkirMyyHehYs5S3e7ddzqtoMSx8rU8_zBo,17944
7
+ minisweagent/agents/interactive.py,sha256=NBeNamRuqww9ZRhOg1q8xPO9ziUw2gpAVV6hCPbpBxU,7470
8
+ minisweagent/agents/interactive_textual.py,sha256=rvD1zoEQSjWd1MklCRGT01cCFoMh46iFrDPBklAWW_A,17984
9
9
  minisweagent/config/README.md,sha256=ABd9anA4aRWtx7Oh37z36Wv6ARvcxD2w9lPUE24R2mY,435
10
10
  minisweagent/config/__init__.py,sha256=0KzHaaIqWgRy2zbwIzhrg6BJPDzOvYi3jb4eBNY4sAU,823
11
11
  minisweagent/config/default.yaml,sha256=OHK9-7PkCa9ZzgYykF1zGYC_AWkiAdOrEpDuurF-1Rk,5143
@@ -16,12 +16,12 @@ minisweagent/config/mini_no_temp.yaml,sha256=n0W-017tBmMx57U9SLt7Fy9WJxI9x2vdTWB
16
16
  minisweagent/config/extra/__init__.py,sha256=e1MoAlDn_wc9HnXNoncf1P-B4DQ-iRf6n7Q_txjZGRI,52
17
17
  minisweagent/config/extra/swebench.yaml,sha256=5FKblpcNTHmVUNE1JLHo5_AsupvlwsrLj8I3R2mRItk,7680
18
18
  minisweagent/environments/__init__.py,sha256=tTnNjNAhMvIuB1mlesreBV5TLdQBp79qj_Mxr7HGzNk,1180
19
- minisweagent/environments/docker.py,sha256=mj9I1HhwwyWBEm_lGVWEvBDyDzRKypiKoln5uSY58zw,4146
19
+ minisweagent/environments/docker.py,sha256=tL0XL2kIxNGLswcmPTDklpoa3RGkQJr7HkEEE2rxzNQ,4049
20
20
  minisweagent/environments/local.py,sha256=dV05j4jPrmY0k5O_UtF_qrRqqdilyPUUkbn-YUhRC3M,1236
21
- minisweagent/environments/singularity.py,sha256=sVZ1L_4ud7WbJxYIhi4WPNOK3dosqfYKZxak1V9LEjg,2765
21
+ minisweagent/environments/singularity.py,sha256=dHH_SS4MOm3cP7k1kSErvIjVijTL_-VFTOHtCyjUKVw,2671
22
22
  minisweagent/environments/extra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  minisweagent/environments/extra/swerex_docker.py,sha256=wu2F_9moa8yj5IgCEquFOoxEXJ8Vi6BF19rJvRdoJIs,1665
24
- minisweagent/models/__init__.py,sha256=J4bnvfMByTVG0cL_6p51sm8gdargXhARfbG5c0UZ8Z4,2890
24
+ minisweagent/models/__init__.py,sha256=wZguR-mGijqlxovIYfs1WcCiaHyYPywml0AacBJtg5c,2890
25
25
  minisweagent/models/anthropic.py,sha256=D8nHvvbgzPjla0He8p0O9kaXASPWg1Sai0pHsAj_Yn8,855
26
26
  minisweagent/models/litellm_model.py,sha256=tEwAV2dzslJ4HFDXApXSPo5OWsiz8soy52P8-r9p4Xg,2538
27
27
  minisweagent/models/test_models.py,sha256=ItCA6ddntzkYA7dzSuUEaLMV-AE8TBuXBFP8CzpiO3U,1351
@@ -32,20 +32,20 @@ minisweagent/run/__init__.py,sha256=WIoYgHVl7iZF2YncrfV3IttupG6P5KogroKHKECka3A,
32
32
  minisweagent/run/github_issue.py,sha256=GWOkGM09jOYV93p6xIM_kKWmC1yP_d5lprafWlqoBN0,2748
33
33
  minisweagent/run/hello_world.py,sha256=erLnEwNmPFLxq3-8zyv66Vy1kIqMqQf97vISX7LrQXg,959
34
34
  minisweagent/run/inspector.py,sha256=QnY3oYzm-yq3w9Jzs112Lco2Rg84vSocAWrQRVz_1lc,7127
35
- minisweagent/run/mini.py,sha256=d-dtnddRDvs0Ub3mFuXJYsNh3sSfRnSPjp6877Y9O2I,4215
35
+ minisweagent/run/mini.py,sha256=09WKk4ERzhQ_hoSg0kNUYGtCRjLqMrLOSUqQtxjVwlo,4459
36
36
  minisweagent/run/mini_extra.py,sha256=ecA1PnTWElpO60G9RktvVLtUOf3bZ_ESmnSttS6izhQ,1465
37
37
  minisweagent/run/extra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  minisweagent/run/extra/config.py,sha256=CEsEr8AdEm64Jods2ZRURChHKMILSatkBLkLmRywkrw,3672
39
- minisweagent/run/extra/swebench.py,sha256=mth9nqayjDZw07CHcXUD-ABmISLkVkJDl7G-MQ-8CjY,10828
40
- minisweagent/run/extra/swebench_single.py,sha256=xbKjCLgDBPTKWAZa2H4gGWy6k3kadJYTJBGn-kytlu4,3023
39
+ minisweagent/run/extra/swebench.py,sha256=3zGn7PUZCCf5vcVYy6vsIgjdJHUVh8cr-ztJwTsUWUo,10826
40
+ minisweagent/run/extra/swebench_single.py,sha256=RGfs0FPD_3cznR5Y-J90CopYCC0_Vg9NYusRB1wKllc,3309
41
41
  minisweagent/run/extra/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
42
  minisweagent/run/extra/utils/batch_progress.py,sha256=xhJ7FmsaTBGz-yh8pzYl4yMoUGjn7GA24eYrP-nHj60,6804
43
43
  minisweagent/run/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
44
  minisweagent/run/utils/save.py,sha256=MzIvUyCiqbq3EaQc8cKtaD0MEkcyXmUyl4ZcxYzZW_Y,1680
45
45
  minisweagent/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
- minisweagent/utils/log.py,sha256=cObZMmhncD1HoRiAnEGQ65jGUgXXofMu59SH9naXIuI,915
47
- mini_swe_agent-1.9.0.dist-info/METADATA,sha256=NKTT4AES1ZOPVoW5cTPtzRYXv5hFLyiKgHo1Fxd2NBA,13798
48
- mini_swe_agent-1.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
49
- mini_swe_agent-1.9.0.dist-info/entry_points.txt,sha256=d1_yRbTaGjs1UXHa6JQK0sKDGBIVGm8oeW0k2kfbJgQ,182
50
- mini_swe_agent-1.9.0.dist-info/top_level.txt,sha256=zKF4t8bFpV87fdVABZt2Da-vnb4Vkh_CxkwQx5YT4Ew,13
51
- mini_swe_agent-1.9.0.dist-info/RECORD,,
46
+ minisweagent/utils/log.py,sha256=ruDMNKMrVC9NPvCeHwO3QYz5jsVNUGQB2dRAEAPAWp8,996
47
+ mini_swe_agent-1.9.1.dist-info/METADATA,sha256=iJsC920Z-2YoGsdpRgwk1wwKvq9SWi9qcTHSQjqPetc,13828
48
+ mini_swe_agent-1.9.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
49
+ mini_swe_agent-1.9.1.dist-info/entry_points.txt,sha256=d1_yRbTaGjs1UXHa6JQK0sKDGBIVGm8oeW0k2kfbJgQ,182
50
+ mini_swe_agent-1.9.1.dist-info/top_level.txt,sha256=zKF4t8bFpV87fdVABZt2Da-vnb4Vkh_CxkwQx5YT4Ew,13
51
+ mini_swe_agent-1.9.1.dist-info/RECORD,,
minisweagent/__init__.py CHANGED
@@ -8,7 +8,7 @@ This file provides:
8
8
  unless you want the static type checking.
9
9
  """
10
10
 
11
- __version__ = "1.9.0"
11
+ __version__ = "1.9.1"
12
12
 
13
13
  import os
14
14
  from pathlib import Path
@@ -18,6 +18,8 @@ import dotenv
18
18
  from platformdirs import user_config_dir
19
19
  from rich.console import Console
20
20
 
21
+ from minisweagent.utils.log import logger
22
+
21
23
  package_dir = Path(__file__).resolve().parent
22
24
 
23
25
  global_config_dir = Path(os.getenv("MSWEA_GLOBAL_CONFIG_DIR") or user_config_dir("mini-swe-agent"))
@@ -68,4 +70,13 @@ class Agent(Protocol):
68
70
  def run(self, task: str, **kwargs) -> tuple[str, str]: ...
69
71
 
70
72
 
71
- __all__ = ["Agent", "Model", "Environment", "package_dir", "__version__", "global_config_file", "global_config_dir"]
73
+ __all__ = [
74
+ "Agent",
75
+ "Model",
76
+ "Environment",
77
+ "package_dir",
78
+ "__version__",
79
+ "global_config_file",
80
+ "global_config_dir",
81
+ "logger",
82
+ ]
@@ -39,9 +39,9 @@ class InteractiveAgent(DefaultAgent):
39
39
  super().__init__(*args, config_class=config_class, **kwargs)
40
40
  self.cost_last_confirmed = 0.0
41
41
 
42
- def add_message(self, role: str, content: str):
42
+ def add_message(self, role: str, content: str, **kwargs):
43
43
  # Extend supermethod to print messages
44
- super().add_message(role, content)
44
+ super().add_message(role, content, **kwargs)
45
45
  if role == "assistant":
46
46
  console.print(
47
47
  f"\n[red][bold]mini-swe-agent[/bold] (step [bold]{self.model.n_calls}[/bold], [bold]${self.model.cost:.2f}[/bold]):[/red]\n",
@@ -44,8 +44,8 @@ class _TextualAgent(DefaultAgent):
44
44
  super().__init__(*args, config_class=TextualAgentConfig, **kwargs)
45
45
  self._current_action_from_human = False
46
46
 
47
- def add_message(self, role: str, content: str):
48
- super().add_message(role, content)
47
+ def add_message(self, role: str, content: str, **kwargs):
48
+ super().add_message(role, content, **kwargs)
49
49
  if self.app.agent_state != "UNINITIALIZED":
50
50
  self.app.call_from_thread(self.app.on_message_added)
51
51
 
@@ -276,8 +276,8 @@ class TextualAgent(App):
276
276
 
277
277
  self._vscroll = VerticalScroll()
278
278
 
279
- def run(self, task: str) -> tuple[str, str]:
280
- threading.Thread(target=lambda: self.agent.run(task), daemon=True).start()
279
+ def run(self, task: str, **kwargs) -> tuple[str, str]:
280
+ threading.Thread(target=lambda: self.agent.run(task, **kwargs), daemon=True).start()
281
281
  super().run()
282
282
  return self.exit_status, self.result
283
283
 
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import os
2
3
  import shlex
3
4
  import subprocess
@@ -5,8 +6,6 @@ import uuid
5
6
  from dataclasses import asdict, dataclass, field
6
7
  from typing import Any
7
8
 
8
- from minisweagent.utils.log import get_logger
9
-
10
9
 
11
10
  @dataclass
12
11
  class DockerEnvironmentConfig:
@@ -35,7 +34,7 @@ class DockerEnvironment:
35
34
  """This class executes bash commands in a Docker container using direct docker commands.
36
35
  See `DockerEnvironmentConfig` for keyword arguments.
37
36
  """
38
- self.logger = get_logger("minisweagent.environment")
37
+ self.logger = logging.getLogger("minisweagent.environment")
39
38
  self.container_id: str | None = None
40
39
  self.config = config_class(**kwargs)
41
40
  self._start_container()
@@ -97,7 +96,6 @@ class DockerEnvironment:
97
96
  def cleanup(self):
98
97
  """Stop and remove the Docker container."""
99
98
  if getattr(self, "container_id", None) is not None: # if init fails early, container_id might not be set
100
- self.logger.info(f"Stopping container {self.container_id}")
101
99
  cmd = f"(timeout 60 {self.config.executable} stop {self.container_id} || {self.config.executable} rm -f {self.container_id}) >/dev/null 2>&1 &"
102
100
  subprocess.Popen(cmd, shell=True)
103
101
 
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
+ import logging
3
4
  import os
4
5
  import shutil
5
6
  import subprocess
@@ -9,8 +10,6 @@ from dataclasses import asdict, dataclass, field
9
10
  from pathlib import Path
10
11
  from typing import Any
11
12
 
12
- from minisweagent.utils.log import get_logger
13
-
14
13
 
15
14
  @dataclass
16
15
  class SingularityEnvironmentConfig:
@@ -29,7 +28,7 @@ class SingularityEnvironmentConfig:
29
28
  class SingularityEnvironment:
30
29
  def __init__(self, **kwargs):
31
30
  """Singularity environment. See `SingularityEnvironmentConfig` for kwargs."""
32
- self.logger = get_logger("minisweagent.environment")
31
+ self.logger = logging.getLogger("minisweagent.environment")
33
32
  self.config = SingularityEnvironmentConfig(**kwargs)
34
33
  self.sandbox_dir = Path(tempfile.gettempdir()) / f"minisweagent-{uuid.uuid4().hex[:8]}"
35
34
  subprocess.run(
@@ -71,7 +70,6 @@ class SingularityEnvironment:
71
70
 
72
71
  def cleanup(self):
73
72
  if self.sandbox_dir.exists():
74
- self.logger.info(f"Removing sandbox {self.sandbox_dir}")
75
73
  shutil.rmtree(self.sandbox_dir)
76
74
 
77
75
  def __del__(self):
@@ -63,10 +63,10 @@ def get_model_name(input_model_name: str | None = None, config: dict | None = No
63
63
  config = {}
64
64
  if input_model_name:
65
65
  return input_model_name
66
- if from_env := os.getenv("MSWEA_MODEL_NAME"):
67
- return from_env
68
66
  if from_config := config.get("model_name"):
69
67
  return from_config
68
+ if from_env := os.getenv("MSWEA_MODEL_NAME"):
69
+ return from_env
70
70
  raise ValueError("No default model set. Please run `mini-extra config setup` to set one.")
71
71
 
72
72
 
@@ -24,7 +24,7 @@ from minisweagent.environments import get_environment
24
24
  from minisweagent.models import get_model
25
25
  from minisweagent.run.extra.utils.batch_progress import RunBatchProgressManager
26
26
  from minisweagent.run.utils.save import save_traj
27
- from minisweagent.utils.log import add_file_handlers, logger
27
+ from minisweagent.utils.log import add_file_handler, logger
28
28
 
29
29
  _HELP_TEXT = """Run mini-SWE-agent on SWEBench instances.
30
30
 
@@ -198,7 +198,7 @@ def main(
198
198
  output_path = Path(output)
199
199
  output_path.mkdir(parents=True, exist_ok=True)
200
200
  logger.info(f"Results will be saved to {output_path}")
201
- add_file_handlers(output_path / "minisweagent.log")
201
+ add_file_handler(output_path / "minisweagent.log")
202
202
 
203
203
  dataset_path = DATASET_MAPPING.get(subset, subset)
204
204
  logger.info(f"Loading dataset {dataset_path}, split {split}...")
@@ -1,5 +1,6 @@
1
1
  """Run on a single SWE-Bench instance."""
2
2
 
3
+ import traceback
3
4
  from pathlib import Path
4
5
 
5
6
  import typer
@@ -58,11 +59,15 @@ def main(
58
59
  **({"mode": "yolo"} | config.get("agent", {})),
59
60
  )
60
61
 
61
- exit_status, result = None, None
62
+ exit_status, result, extra_info = None, None, None
62
63
  try:
63
64
  exit_status, result = agent.run(instance["problem_statement"]) # type: ignore[arg-type]
65
+ except Exception as e:
66
+ logger.error(f"Error processing instance {instance_spec}: {e}", exc_info=True)
67
+ exit_status, result = type(e).__name__, str(e)
68
+ extra_info = {"traceback": traceback.format_exc()}
64
69
  finally:
65
- save_traj(agent, output, exit_status=exit_status, result=result) # type: ignore[arg-type]
70
+ save_traj(agent, output, exit_status=exit_status, result=result, extra_info=extra_info) # type: ignore[arg-type]
66
71
 
67
72
 
68
73
  if __name__ == "__main__":
minisweagent/run/mini.py CHANGED
@@ -4,6 +4,7 @@
4
4
  # Read this first: https://mini-swe-agent.com/latest/usage/mini/ (usage)
5
5
 
6
6
  import os
7
+ import traceback
7
8
  from pathlib import Path
8
9
  from typing import Any
9
10
 
@@ -22,6 +23,7 @@ from minisweagent.environments.local import LocalEnvironment
22
23
  from minisweagent.models import get_model
23
24
  from minisweagent.run.extra.config import configure_if_first_time
24
25
  from minisweagent.run.utils.save import save_traj
26
+ from minisweagent.utils.log import logger
25
27
 
26
28
  DEFAULT_CONFIG = Path(os.getenv("MSWEA_MINI_CONFIG_PATH", builtin_config_dir / "mini.yaml"))
27
29
  DEFAULT_OUTPUT = global_config_dir / "last_mini_run.traj.json"
@@ -41,29 +43,19 @@ More information about the usage: [bold green]https://mini-swe-agent.com/latest/
41
43
  """
42
44
 
43
45
 
46
+ # fmt: off
44
47
  @app.command(help=_HELP_TEXT)
45
48
  def main(
46
- visual: bool = typer.Option(
47
- False,
48
- "-v",
49
- "--visual",
50
- help="Toggle (pager-style) UI (Textual) depending on the MSWEA_VISUAL_MODE_DEFAULT environment setting",
51
- ),
52
- model_name: str | None = typer.Option(
53
- None,
54
- "-m",
55
- "--model",
56
- help="Model to use",
57
- ),
49
+ visual: bool = typer.Option(False, "-v", "--visual", help="Toggle (pager-style) UI (Textual) depending on the MSWEA_VISUAL_MODE_DEFAULT environment setting",),
50
+ model_name: str | None = typer.Option( None, "-m", "--model", help="Model to use",),
58
51
  task: str | None = typer.Option(None, "-t", "--task", help="Task/problem statement", show_default=False),
59
52
  yolo: bool = typer.Option(False, "-y", "--yolo", help="Run without confirmation"),
60
53
  cost_limit: float | None = typer.Option(None, "-l", "--cost-limit", help="Cost limit. Set to 0 to disable."),
61
54
  config_spec: Path = typer.Option(DEFAULT_CONFIG, "-c", "--config", help="Path to config file"),
62
55
  output: Path | None = typer.Option(DEFAULT_OUTPUT, "-o", "--output", help="Output trajectory file"),
63
- exit_immediately: bool = typer.Option(
64
- False, "--exit-immediately", help="Exit immediately when the agent wants to finish instead of prompting."
65
- ),
56
+ exit_immediately: bool = typer.Option( False, "--exit-immediately", help="Exit immediately when the agent wants to finish instead of prompting."),
66
57
  ) -> Any:
58
+ # fmt: on
67
59
  configure_if_first_time()
68
60
  config = yaml.safe_load(get_config_path(config_spec).read_text())
69
61
 
@@ -92,13 +84,18 @@ def main(
92
84
  agent_class = InteractiveAgent
93
85
  if visual == (os.getenv("MSWEA_VISUAL_MODE_DEFAULT", "false") == "false"):
94
86
  agent_class = TextualAgent
95
- exit_status, result = None, None
87
+
96
88
  agent = agent_class(model, env, **config.get("agent", {}))
89
+ exit_status, result, extra_info = None, None, None
97
90
  try:
98
91
  exit_status, result = agent.run(task) # type: ignore[arg-type]
92
+ except Exception as e:
93
+ logger.error(f"Error running agent: {e}", exc_info=True)
94
+ exit_status, result = type(e).__name__, str(e)
95
+ extra_info = {"traceback": traceback.format_exc()}
99
96
  finally:
100
97
  if output:
101
- save_traj(agent, output, exit_status=exit_status, result=result) # type: ignore[arg-type]
98
+ save_traj(agent, output, exit_status=exit_status, result=result, extra_info=extra_info) # type: ignore[arg-type]
102
99
  return agent
103
100
 
104
101
 
minisweagent/utils/log.py CHANGED
@@ -1,32 +1,36 @@
1
1
  import logging
2
2
  from pathlib import Path
3
3
 
4
- MINI_LOGGERS = {}
5
- _EXTRA_HANDLERS = []
4
+ from rich.logging import RichHandler
6
5
 
7
6
 
8
- def get_logger(name: str) -> logging.Logger:
9
- if name in MINI_LOGGERS:
10
- return MINI_LOGGERS[name]
11
- logger = logging.getLogger(name)
7
+ def _setup_root_logger() -> None:
8
+ logger = logging.getLogger("minisweagent")
12
9
  logger.setLevel(logging.DEBUG)
13
- handler = logging.StreamHandler()
14
- formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s")
15
- handler.setFormatter(formatter)
16
- logger.addHandler(handler)
17
- for handler in _EXTRA_HANDLERS:
18
- logger.addHandler(handler)
19
- MINI_LOGGERS[name] = logger
20
- return logger
10
+ _handler = RichHandler(
11
+ show_path=False,
12
+ show_time=False,
13
+ show_level=False,
14
+ markup=True,
15
+ )
16
+ _formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s")
17
+ _handler.setFormatter(_formatter)
18
+ logger.addHandler(_handler)
21
19
 
22
20
 
23
- def add_file_handlers(path: Path):
21
+ def add_file_handler(path: Path | str, level: int = logging.DEBUG, *, print_path: bool = True) -> None:
22
+ logger = logging.getLogger("minisweagent")
24
23
  handler = logging.FileHandler(path)
24
+ handler.setLevel(level)
25
25
  formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
26
26
  handler.setFormatter(formatter)
27
- _EXTRA_HANDLERS.append(handler)
28
- for logger in MINI_LOGGERS.values():
29
- logger.addHandler(handler)
27
+ logger.addHandler(handler)
28
+ if print_path:
29
+ print(f"Logging to '{path}'")
30
+
31
+
32
+ _setup_root_logger()
33
+ logger = logging.getLogger("minisweagent")
30
34
 
31
35
 
32
- logger = get_logger("minisweagent")
36
+ __all__ = ["logger"]