mini-swe-agent 1.13.4__tar.gz → 1.14.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.
Files changed (63) hide show
  1. {mini_swe_agent-1.13.4/src/mini_swe_agent.egg-info → mini_swe_agent-1.14.1}/PKG-INFO +1 -1
  2. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1/src/mini_swe_agent.egg-info}/PKG-INFO +1 -1
  3. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/__init__.py +1 -1
  4. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/__init__.py +7 -5
  5. mini_swe_agent-1.14.1/src/minisweagent/models/anthropic.py +35 -0
  6. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/litellm_model.py +8 -3
  7. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/openrouter_model.py +6 -1
  8. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/portkey_model.py +6 -1
  9. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/utils/cache_control.py +16 -4
  10. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/utils/key_per_thread.py +2 -0
  11. mini_swe_agent-1.13.4/src/minisweagent/models/anthropic.py +0 -19
  12. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/LICENSE.md +0 -0
  13. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/README.md +0 -0
  14. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/pyproject.toml +0 -0
  15. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/setup.cfg +0 -0
  16. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/mini_swe_agent.egg-info/SOURCES.txt +0 -0
  17. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/mini_swe_agent.egg-info/dependency_links.txt +0 -0
  18. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/mini_swe_agent.egg-info/entry_points.txt +0 -0
  19. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/mini_swe_agent.egg-info/requires.txt +0 -0
  20. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/mini_swe_agent.egg-info/top_level.txt +0 -0
  21. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/__main__.py +0 -0
  22. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/agents/__init__.py +0 -0
  23. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/agents/default.py +0 -0
  24. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/agents/interactive.py +0 -0
  25. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/agents/interactive_textual.py +0 -0
  26. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/README.md +0 -0
  27. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/__init__.py +0 -0
  28. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/default.yaml +0 -0
  29. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/extra/__init__.py +0 -0
  30. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/extra/swebench.yaml +0 -0
  31. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/extra/swebench_roulette.yaml +0 -0
  32. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/github_issue.yaml +0 -0
  33. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/mini.tcss +0 -0
  34. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/mini.yaml +0 -0
  35. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/config/mini_no_temp.yaml +0 -0
  36. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/environments/__init__.py +0 -0
  37. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/environments/docker.py +0 -0
  38. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/environments/extra/__init__.py +0 -0
  39. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/environments/extra/bubblewrap.py +0 -0
  40. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/environments/extra/swerex_docker.py +0 -0
  41. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/environments/local.py +0 -0
  42. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/environments/singularity.py +0 -0
  43. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/extra/__init__.py +0 -0
  44. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/extra/roulette.py +0 -0
  45. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/test_models.py +0 -0
  46. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/models/utils/__init__.py +0 -0
  47. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/py.typed +0 -0
  48. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/__init__.py +0 -0
  49. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/extra/__init__.py +0 -0
  50. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/extra/config.py +0 -0
  51. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/extra/swebench.py +0 -0
  52. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/extra/swebench_single.py +0 -0
  53. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/extra/utils/__init__.py +0 -0
  54. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/extra/utils/batch_progress.py +0 -0
  55. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/github_issue.py +0 -0
  56. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/hello_world.py +0 -0
  57. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/inspector.py +0 -0
  58. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/mini.py +0 -0
  59. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/mini_extra.py +0 -0
  60. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/utils/__init__.py +0 -0
  61. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/run/utils/save.py +0 -0
  62. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/utils/__init__.py +0 -0
  63. {mini_swe_agent-1.13.4 → mini_swe_agent-1.14.1}/src/minisweagent/utils/log.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mini-swe-agent
3
- Version: 1.13.4
3
+ Version: 1.14.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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mini-swe-agent
3
- Version: 1.13.4
3
+ Version: 1.14.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
@@ -8,7 +8,7 @@ This file provides:
8
8
  unless you want the static type checking.
9
9
  """
10
10
 
11
- __version__ = "1.13.4"
11
+ __version__ = "1.14.1"
12
12
 
13
13
  import os
14
14
  from pathlib import Path
@@ -55,6 +55,13 @@ def get_model(input_model_name: str | None = None, config: dict | None = None) -
55
55
  if (from_env := os.getenv("MSWEA_MODEL_API_KEY")) and not str(type(model_class)).endswith("DeterministicModel"):
56
56
  config.setdefault("model_kwargs", {})["api_key"] = from_env
57
57
 
58
+ if (
59
+ any(s in resolved_model_name.lower() for s in ["anthropic", "sonnet", "opus", "claude"])
60
+ and "set_cache_control" not in config
61
+ ):
62
+ # Select cache control for Anthropic models by default
63
+ config["set_cache_control"] = "default_end"
64
+
58
65
  return model_class(**config)
59
66
 
60
67
 
@@ -98,11 +105,6 @@ def get_model_class(model_name: str, model_class: str = "") -> type:
98
105
  msg = f"Unknown model class: {model_class} (resolved to {full_path}, available: {_MODEL_CLASS_MAPPING})"
99
106
  raise ValueError(msg)
100
107
 
101
- if any(s in model_name.lower() for s in ["anthropic", "sonnet", "opus", "claude"]):
102
- from minisweagent.models.anthropic import AnthropicModel
103
-
104
- return AnthropicModel
105
-
106
108
  # Default to LitellmModel
107
109
  from minisweagent.models.litellm_model import LitellmModel
108
110
 
@@ -0,0 +1,35 @@
1
+ import os
2
+ import warnings
3
+ from typing import Literal
4
+
5
+ from minisweagent.models.litellm_model import LitellmModel, LitellmModelConfig
6
+ from minisweagent.models.utils.cache_control import set_cache_control
7
+ from minisweagent.models.utils.key_per_thread import get_key_per_thread
8
+
9
+
10
+ class AnthropicModelConfig(LitellmModelConfig):
11
+ set_cache_control: Literal["default_end"] | None = "default_end"
12
+ """Set explicit cache control markers, for example for Anthropic models"""
13
+
14
+
15
+ class AnthropicModel(LitellmModel):
16
+ """This class is now only a thin wrapper around the LitellmModel class.
17
+ It is largely kept for backwards compatibility.
18
+ It will not be selected by `get_model` and `get_model_class` unless explicitly specified.
19
+ """
20
+
21
+ def __init__(self, *, config_class: type = AnthropicModelConfig, **kwargs):
22
+ super().__init__(config_class=config_class, **kwargs)
23
+
24
+ def query(self, messages: list[dict], **kwargs) -> dict:
25
+ api_key = None
26
+ # Legacy only
27
+ if rotating_keys := os.getenv("ANTHROPIC_API_KEYS"):
28
+ warnings.warn(
29
+ "ANTHROPIC_API_KEYS is deprecated and will be removed in the future. "
30
+ "Simply use the ANTHROPIC_API_KEY environment variable instead. "
31
+ "Key rotation is no longer required."
32
+ )
33
+ api_key = get_key_per_thread(rotating_keys.split("::"))
34
+ messages = set_cache_control(messages, mode="default_end")
35
+ return super().query(messages, api_key=api_key, **kwargs)
@@ -3,7 +3,7 @@ import logging
3
3
  import os
4
4
  from dataclasses import asdict, dataclass, field
5
5
  from pathlib import Path
6
- from typing import Any
6
+ from typing import Any, Literal
7
7
 
8
8
  import litellm
9
9
  from tenacity import (
@@ -15,6 +15,7 @@ from tenacity import (
15
15
  )
16
16
 
17
17
  from minisweagent.models import GLOBAL_MODEL_STATS
18
+ from minisweagent.models.utils.cache_control import set_cache_control
18
19
 
19
20
  logger = logging.getLogger("litellm_model")
20
21
 
@@ -24,11 +25,13 @@ class LitellmModelConfig:
24
25
  model_name: str
25
26
  model_kwargs: dict[str, Any] = field(default_factory=dict)
26
27
  litellm_model_registry: Path | str | None = os.getenv("LITELLM_MODEL_REGISTRY_PATH")
28
+ set_cache_control: Literal["default_end"] | None = None
29
+ """Set explicit cache control markers, for example for Anthropic models"""
27
30
 
28
31
 
29
32
  class LitellmModel:
30
- def __init__(self, **kwargs):
31
- self.config = LitellmModelConfig(**kwargs)
33
+ def __init__(self, *, config_class: type = LitellmModelConfig, **kwargs):
34
+ self.config = config_class(**kwargs)
32
35
  self.cost = 0.0
33
36
  self.n_calls = 0
34
37
  if self.config.litellm_model_registry and Path(self.config.litellm_model_registry).is_file():
@@ -60,6 +63,8 @@ class LitellmModel:
60
63
  raise e
61
64
 
62
65
  def query(self, messages: list[dict[str, str]], **kwargs) -> dict:
66
+ if self.config.set_cache_control:
67
+ messages = set_cache_control(messages, mode=self.config.set_cache_control)
63
68
  response = self._query(messages, **kwargs)
64
69
  try:
65
70
  cost = litellm.cost_calculator.completion_cost(response)
@@ -2,7 +2,7 @@ import json
2
2
  import logging
3
3
  import os
4
4
  from dataclasses import asdict, dataclass, field
5
- from typing import Any
5
+ from typing import Any, Literal
6
6
 
7
7
  import requests
8
8
  from tenacity import (
@@ -14,6 +14,7 @@ from tenacity import (
14
14
  )
15
15
 
16
16
  from minisweagent.models import GLOBAL_MODEL_STATS
17
+ from minisweagent.models.utils.cache_control import set_cache_control
17
18
 
18
19
  logger = logging.getLogger("openrouter_model")
19
20
 
@@ -22,6 +23,8 @@ logger = logging.getLogger("openrouter_model")
22
23
  class OpenRouterModelConfig:
23
24
  model_name: str
24
25
  model_kwargs: dict[str, Any] = field(default_factory=dict)
26
+ set_cache_control: Literal["default_end"] | None = None
27
+ """Set explicit cache control markers, for example for Anthropic models"""
25
28
 
26
29
 
27
30
  class OpenRouterAPIError(Exception):
@@ -90,6 +93,8 @@ class OpenRouterModel:
90
93
  raise OpenRouterAPIError(f"Request failed: {e}") from e
91
94
 
92
95
  def query(self, messages: list[dict[str, str]], **kwargs) -> dict:
96
+ if self.config.set_cache_control:
97
+ messages = set_cache_control(messages, mode=self.config.set_cache_control)
93
98
  response = self._query(messages, **kwargs)
94
99
 
95
100
  # Extract cost from usage information
@@ -3,7 +3,7 @@ import logging
3
3
  import os
4
4
  from dataclasses import asdict, dataclass, field
5
5
  from pathlib import Path
6
- from typing import Any
6
+ from typing import Any, Literal
7
7
 
8
8
  import litellm
9
9
  from tenacity import (
@@ -15,6 +15,7 @@ from tenacity import (
15
15
  )
16
16
 
17
17
  from minisweagent.models import GLOBAL_MODEL_STATS
18
+ from minisweagent.models.utils.cache_control import set_cache_control
18
19
 
19
20
  logger = logging.getLogger("portkey_model")
20
21
 
@@ -37,6 +38,8 @@ class PortkeyModelConfig:
37
38
  doesn't match the Portkey model name.
38
39
  Note that this might change if we get better support for Portkey and change how we calculate costs.
39
40
  """
41
+ set_cache_control: Literal["default_end"] | None = None
42
+ """Set explicit cache control markers, for example for Anthropic models"""
40
43
 
41
44
 
42
45
  class PortkeyModel:
@@ -85,6 +88,8 @@ class PortkeyModel:
85
88
  )
86
89
 
87
90
  def query(self, messages: list[dict[str, str]], **kwargs) -> dict:
91
+ if self.config.set_cache_control:
92
+ messages = set_cache_control(messages, mode=self.config.set_cache_control)
88
93
  response = self._query(messages, **kwargs)
89
94
  response_for_cost_calc = response.model_copy()
90
95
  if self.config.litellm_model_name_override:
@@ -1,3 +1,8 @@
1
+ import copy
2
+ import warnings
3
+ from typing import Literal
4
+
5
+
1
6
  def _get_content_text(entry: dict) -> str:
2
7
  if isinstance(entry["content"], str):
3
8
  return entry["content"]
@@ -29,14 +34,21 @@ def _set_cache_control(entry: dict) -> None:
29
34
  entry["cache_control"] = {"type": "ephemeral"}
30
35
 
31
36
 
32
- def set_cache_control(messages: list[dict], last_n_messages_offset: int = 0) -> list[dict]:
37
+ def set_cache_control(
38
+ messages: list[dict], *, mode: Literal["default_end"] | None = "default_end", last_n_messages_offset: int = 0
39
+ ) -> list[dict]:
33
40
  """This messages processor adds manual cache control marks to the messages."""
41
+ # ONLY ADD TO THE LAST MESSAGE
42
+ if mode != "default_end":
43
+ raise ValueError(f"Invalid mode: {mode}")
44
+ if last_n_messages_offset:
45
+ warnings.warn("last_n_messages_offset is deprecated and will be removed in the future. It has no effect.")
46
+
47
+ messages = copy.deepcopy(messages)
34
48
  new_messages = []
35
- n_tagged = 0
36
49
  for i_entry, entry in enumerate(reversed(messages)):
37
50
  _clear_cache_control(entry)
38
- if n_tagged < 2 and entry["role"] in ["user"] and i_entry >= last_n_messages_offset:
51
+ if i_entry == 0:
39
52
  _set_cache_control(entry)
40
- n_tagged += 1
41
53
  new_messages.append(entry)
42
54
  return list(reversed(new_messages))
@@ -3,6 +3,7 @@ agents to not mess up prompt caching.
3
3
  """
4
4
 
5
5
  import threading
6
+ import warnings
6
7
  from typing import Any
7
8
 
8
9
  _THREADS_THAT_USED_API_KEYS: list[Any] = []
@@ -10,6 +11,7 @@ _THREADS_THAT_USED_API_KEYS: list[Any] = []
10
11
 
11
12
  def get_key_per_thread(api_keys: list[Any]) -> Any:
12
13
  """Choose key based on thread name. Returns None if no keys are available."""
14
+ warnings.warn("get_key_per_thread is deprecated and will be removed in the future")
13
15
  thread_name = threading.current_thread().name
14
16
  if thread_name not in _THREADS_THAT_USED_API_KEYS:
15
17
  _THREADS_THAT_USED_API_KEYS.append(thread_name)
@@ -1,19 +0,0 @@
1
- import os
2
-
3
- from minisweagent.models.litellm_model import LitellmModel
4
- from minisweagent.models.utils.cache_control import set_cache_control
5
- from minisweagent.models.utils.key_per_thread import get_key_per_thread
6
-
7
-
8
- class AnthropicModel(LitellmModel):
9
- """For the use of anthropic models, we need to add explicit cache control marks
10
- to the messages or we lose out on the benefits of the cache.
11
- Because break points are limited per key, we also need to rotate between different keys
12
- if running with multiple agents in parallel threads.
13
- """
14
-
15
- def query(self, messages: list[dict], **kwargs) -> dict:
16
- api_key = None
17
- if rotating_keys := os.getenv("ANTHROPIC_API_KEYS"):
18
- api_key = get_key_per_thread(rotating_keys.split("::"))
19
- return super().query(set_cache_control(messages), api_key=api_key, **kwargs)