From 78525d6a57f5ef9e2fee15777572f20f21aea6e5 Mon Sep 17 00:00:00 2001 From: Viraj <35092918+angrybayblade@users.noreply.github.com> Date: Tue, 9 Jul 2024 20:07:26 +0530 Subject: [PATCH] Release `v0.3.17` (#276) Co-authored-by: Karan Vaidya --- .github/workflows/release.yaml | 38 +++- python/composio/tools/env/docker/workspace.py | 61 +++--- python/plugins/autogen/setup.py | 4 +- python/plugins/camel/setup.py | 4 +- python/plugins/claude/setup.py | 4 +- python/plugins/crew_ai/setup.py | 4 +- python/plugins/griptape/setup.py | 4 +- python/plugins/julep/setup.py | 4 +- python/plugins/langchain/setup.py | 4 +- python/plugins/llamaindex/setup.py | 4 +- python/plugins/lyzr/setup.py | 4 +- python/plugins/openai/setup.py | 4 +- python/setup.py | 2 +- python/swe/README.md | 8 +- python/swe/composio_swe/__init__.py | 1 - python/swe/composio_swe/agents/__init__.py | 1 - python/swe/composio_swe/agents/utils.py | 75 -------- python/swe/composio_swe/cli.py | 176 ------------------ python/swe/composio_swe/exceptions.py | 5 - python/swe/examples/crewai_agent.py | 6 +- python/swe/examples/llama_agent.py | 6 +- python/swe/setup.py | 27 ++- python/swe/swekit/__init__.py | 1 + .../swe/{composio_swe => swekit}/__main__.py | 4 +- python/swe/swekit/agents/__init__.py | 1 + .../{composio_swe => swekit}/agents/base.py | 6 +- .../benchmark/__init__.py | 0 .../benchmark/complete_eval_workflow.sh | 0 .../benchmark/constants.py | 0 .../benchmark/get_score_card.py | 0 .../benchmark/run_evaluation.py | 164 ++++++++++------ .../benchmark/setup_test_bed.py | 6 +- .../benchmark/utils.py | 9 +- .../benchmark/visualize.py | 0 python/swe/swekit/cli.py | 51 +++++ .../config/__init__.py | 0 .../config/constants.py | 2 +- .../config/context.py | 6 +- .../{composio_swe => swekit}/config/store.py | 0 python/swe/swekit/exceptions.py | 5 + python/swe/swekit/py.typed | 0 .../scaffold/__init__.py | 2 +- .../scaffold/_scaffold.py | 6 +- .../scaffold/templates/__init__.py | 0 .../templates/crewai/__init__.template | 0 .../scaffold/templates/crewai/agent.template | 0 .../templates/crewai/benchmark.template | 15 +- .../scaffold/templates/crewai/inputs.template | 0 .../scaffold/templates/crewai/main.template | 0 .../templates/crewai/prompts.template | 0 python/swe/tests/test_cli.py | 16 +- 51 files changed, 319 insertions(+), 421 deletions(-) delete mode 100644 python/swe/composio_swe/__init__.py delete mode 100644 python/swe/composio_swe/agents/__init__.py delete mode 100644 python/swe/composio_swe/agents/utils.py delete mode 100644 python/swe/composio_swe/cli.py delete mode 100644 python/swe/composio_swe/exceptions.py create mode 100644 python/swe/swekit/__init__.py rename python/swe/{composio_swe => swekit}/__main__.py (57%) create mode 100644 python/swe/swekit/agents/__init__.py rename python/swe/{composio_swe => swekit}/agents/base.py (95%) rename python/swe/{composio_swe => swekit}/benchmark/__init__.py (100%) rename python/swe/{composio_swe => swekit}/benchmark/complete_eval_workflow.sh (100%) rename python/swe/{composio_swe => swekit}/benchmark/constants.py (100%) rename python/swe/{composio_swe => swekit}/benchmark/get_score_card.py (100%) rename python/swe/{composio_swe => swekit}/benchmark/run_evaluation.py (60%) rename python/swe/{composio_swe => swekit}/benchmark/setup_test_bed.py (99%) rename python/swe/{composio_swe => swekit}/benchmark/utils.py (96%) rename python/swe/{composio_swe => swekit}/benchmark/visualize.py (100%) create mode 100644 python/swe/swekit/cli.py rename python/swe/{composio_swe => swekit}/config/__init__.py (100%) rename python/swe/{composio_swe => swekit}/config/constants.py (90%) rename python/swe/{composio_swe => swekit}/config/context.py (98%) rename python/swe/{composio_swe => swekit}/config/store.py (100%) create mode 100644 python/swe/swekit/exceptions.py create mode 100644 python/swe/swekit/py.typed rename python/swe/{composio_swe => swekit}/scaffold/__init__.py (68%) rename python/swe/{composio_swe => swekit}/scaffold/_scaffold.py (83%) rename python/swe/{composio_swe => swekit}/scaffold/templates/__init__.py (100%) rename python/swe/{composio_swe => swekit}/scaffold/templates/crewai/__init__.template (100%) rename python/swe/{composio_swe => swekit}/scaffold/templates/crewai/agent.template (100%) rename python/swe/{composio_swe => swekit}/scaffold/templates/crewai/benchmark.template (70%) rename python/swe/{composio_swe => swekit}/scaffold/templates/crewai/inputs.template (100%) rename python/swe/{composio_swe => swekit}/scaffold/templates/crewai/main.template (100%) rename python/swe/{composio_swe => swekit}/scaffold/templates/crewai/prompts.template (100%) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3efd9a1e2d..369ef27c92 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -48,7 +48,7 @@ jobs: matrix: os: [ubuntu-latest] python-version: ["3.10"] - package: [autogen, claude,crew_ai, griptape, julep, langchain, lyzr, openai, llamaindex] + package: [autogen, camel, claude, crew_ai, griptape, julep, langchain, llamaindex, lyzr, openai] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 @@ -74,3 +74,39 @@ jobs: password: ${{ secrets.PYPI_PASSWORD }} skip-existing: true packages-dir: python/plugins/${{ matrix.package }}/dist/ + + publish-swe: + needs: publish-core + name: Create SWE Toolkit Release + defaults: + run: + working-directory: ./python/swe + strategy: + max-parallel: 1 + matrix: + os: [ubuntu-latest] + python-version: ["3.10"] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Build + run: | + sudo apt-get update --fix-missing + sudo apt-get autoremove + sudo apt-get autoclean + python -m pip install --upgrade pip + pip install twine build + + # Build dist + python -m build + - name: Publish SWE Kit to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: ${{ secrets.PYPI_USERNAME }} + password: ${{ secrets.PYPI_PASSWORD }} + skip-existing: true + packages-dir: python/swe/dist/ \ No newline at end of file diff --git a/python/composio/tools/env/docker/workspace.py b/python/composio/tools/env/docker/workspace.py index 64b62b6bd8..b4dc007975 100644 --- a/python/composio/tools/env/docker/workspace.py +++ b/python/composio/tools/env/docker/workspace.py @@ -25,9 +25,29 @@ from composio.tools.local.handler import LocalClient -script_path = os.path.dirname(os.path.realpath(__file__)) -composio_core_path = Path(script_path).parent.parent.parent.parent.absolute() -composio_local_store_path = Path.home() / ".composio" +COMPOSIO_PATH = Path(__file__).parent.parent.parent.parent.resolve() +COMPOSIO_CACHE = Path.home() / ".composio" + +CONTAINER_BASE_KWARGS = { + "command": "/bin/bash -l -m", + "tty": True, + "detach": True, + "stdin_open": True, + "auto_remove": False, +} +CONTAINER_DEVELOPMENT_MODE_KWARGS = { + "environment": {ENV_COMPOSIO_DEV_MODE: 1}, + "volumes": { + COMPOSIO_PATH: { + "bind": "/opt/composio-core", + "mode": "rw", + }, + COMPOSIO_CACHE: { + "bind": "/root/.composio", + "mode": "rw", + }, + }, +} class DockerWorkspace(Workspace): @@ -41,34 +61,15 @@ def __init__(self, image: t.Optional[str] = None) -> None: super().__init__() self._image = image or os.environ.get(ENV_COMPOSIO_SWE_AGENT, DEFAULT_IMAGE) self.logger.info(f"Creating docker workspace with image: {self._image}") - composio_swe_env = os.environ.get(ENV_COMPOSIO_DEV_MODE, 0) - container_args = { - "image": self._image, - "command": "/bin/bash -l -m", - "name": self.id, - "tty": True, - "detach": True, - "stdin_open": True, - "auto_remove": False, - } try: - if composio_swe_env != 0: - container_args.update( - { - "environment": {ENV_COMPOSIO_DEV_MODE: 1}, - "volumes": { - composio_core_path: { - "bind": "/opt/composio-core", - "mode": "rw", - }, - composio_local_store_path: { - "bind": "/root/.composio", - "mode": "rw", - }, - }, - } - ) - self._container = self.client.containers.run(**container_args) + container_kwargs = { + "image": self._image, + "name": self.id, + **CONTAINER_BASE_KWARGS, + } + if os.environ.get(ENV_COMPOSIO_DEV_MODE, 0) != 0: + container_kwargs.update(CONTAINER_DEVELOPMENT_MODE_KWARGS) + self._container = self.client.containers.run(**container_kwargs) self._container.start() except Exception as e: raise Exception("exception in starting container: ", e) from e diff --git a/python/plugins/autogen/setup.py b/python/plugins/autogen/setup.py index 13756b6eaa..5d718f6c8d 100644 --- a/python/plugins/autogen/setup.py +++ b/python/plugins/autogen/setup.py @@ -9,7 +9,7 @@ setup( name="composio_autogen", - version="0.3.16", + version="0.3.17", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Autogen agent.", @@ -22,6 +22,6 @@ "Operating System :: OS Independent", ], python_requires=">=3.9,<4", - install_requires=["composio_core==0.3.16", "pyautogen>=0.2.19"], + install_requires=["composio_core==0.3.17", "pyautogen>=0.2.19"], include_package_data=True, ) diff --git a/python/plugins/camel/setup.py b/python/plugins/camel/setup.py index 5677d231fb..fb65541357 100644 --- a/python/plugins/camel/setup.py +++ b/python/plugins/camel/setup.py @@ -9,7 +9,7 @@ setup( name="composio_camel", - version="0.3.16", + version="0.3.17", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Claude LLMs.", @@ -22,6 +22,6 @@ "Operating System :: OS Independent", ], python_requires=">=3.9,<4", - install_requires=["composio_core==0.3.16", "camel-ai>=0.1.5.4"], + install_requires=["composio_core==0.3.17", "camel-ai>=0.1.5.4"], include_package_data=True, ) diff --git a/python/plugins/claude/setup.py b/python/plugins/claude/setup.py index e0022f125a..95de8e0e71 100644 --- a/python/plugins/claude/setup.py +++ b/python/plugins/claude/setup.py @@ -9,7 +9,7 @@ setup( name="composio_claude", - version="0.3.16", + version="0.3.17", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Claude LLMs.", @@ -22,6 +22,6 @@ "Operating System :: OS Independent", ], python_requires=">=3.9,<4", - install_requires=["composio_openai==0.3.16", "anthropic>=0.25.7"], + install_requires=["composio_openai==0.3.17", "anthropic>=0.25.7"], include_package_data=True, ) diff --git a/python/plugins/crew_ai/setup.py b/python/plugins/crew_ai/setup.py index 9b778a8714..201f7c5fdb 100644 --- a/python/plugins/crew_ai/setup.py +++ b/python/plugins/crew_ai/setup.py @@ -9,7 +9,7 @@ setup( name="composio_crewai", - version="0.3.16", + version="0.3.17", author="Himanshu", author_email="himanshu@composio.dev", description="Use Composio to get an array of tools with your CrewAI agent.", @@ -22,6 +22,6 @@ "Operating System :: OS Independent", ], python_requires=">=3.9,<4", - install_requires=["composio_langchain==0.3.16"], + install_requires=["composio_langchain==0.3.17"], include_package_data=True, ) diff --git a/python/plugins/griptape/setup.py b/python/plugins/griptape/setup.py index c84218dda4..c3ee1dde4a 100644 --- a/python/plugins/griptape/setup.py +++ b/python/plugins/griptape/setup.py @@ -9,7 +9,7 @@ setup( name="composio_griptape", - version="0.3.16", + version="0.3.17", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Griptape wokflow.", @@ -22,6 +22,6 @@ "Operating System :: OS Independent", ], python_requires=">=3.9,<4", - install_requires=["composio_core==0.3.16", "griptape>=0.24.2"], + install_requires=["composio_core==0.3.17", "griptape>=0.24.2"], include_package_data=True, ) diff --git a/python/plugins/julep/setup.py b/python/plugins/julep/setup.py index 7651651ae6..f7044263d2 100644 --- a/python/plugins/julep/setup.py +++ b/python/plugins/julep/setup.py @@ -9,7 +9,7 @@ setup( name="composio_julep", - version="0.3.16", + version="0.3.17", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Julep wokflow.", @@ -22,6 +22,6 @@ "Operating System :: OS Independent", ], python_requires=">=3.9,<4", - install_requires=["composio_openai==0.3.16", "julep>=0.3.2"], + install_requires=["composio_openai==0.3.17", "julep>=0.3.2"], include_package_data=True, ) diff --git a/python/plugins/langchain/setup.py b/python/plugins/langchain/setup.py index 40ad7babf1..ebdd0aa6a6 100644 --- a/python/plugins/langchain/setup.py +++ b/python/plugins/langchain/setup.py @@ -9,7 +9,7 @@ setup( name="composio_langchain", - version="0.3.16", + version="0.3.17", author="Karan", author_email="karan@composio.dev", description="Use Composio to get an array of tools with your LangChain agent.", @@ -27,7 +27,7 @@ "langchain-openai>=0.0.2.post1", "pydantic>=2.6.4", "langchainhub>=0.1.15", - "composio_core==0.3.16", + "composio_core==0.3.17", ], include_package_data=True, ) diff --git a/python/plugins/llamaindex/setup.py b/python/plugins/llamaindex/setup.py index 4a14e3fe9f..8c9130f73d 100644 --- a/python/plugins/llamaindex/setup.py +++ b/python/plugins/llamaindex/setup.py @@ -9,7 +9,7 @@ setup( name="composio_llamaindex", - version="0.3.16", + version="0.3.17", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your LlamaIndex agent.", @@ -24,7 +24,7 @@ python_requires=">=3.9,<4", install_requires=[ "llama_index>=0.10.43", - "composio_langchain==0.3.16", + "composio_langchain==0.3.17", ], include_package_data=True, ) diff --git a/python/plugins/lyzr/setup.py b/python/plugins/lyzr/setup.py index a987d80b3f..1a82c894aa 100644 --- a/python/plugins/lyzr/setup.py +++ b/python/plugins/lyzr/setup.py @@ -9,7 +9,7 @@ setup( name="composio_lyzr", - version="0.3.16", + version="0.3.17", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your Lyzr workflow.", @@ -25,7 +25,7 @@ install_requires=[ "lyzr-automata>=0.1.3", "pydantic>=2.6.4", - "composio_core==0.3.16", + "composio_core==0.3.17", "langchain>=0.1.0", ], include_package_data=True, diff --git a/python/plugins/openai/setup.py b/python/plugins/openai/setup.py index 0e806b7038..d0e3df9f00 100644 --- a/python/plugins/openai/setup.py +++ b/python/plugins/openai/setup.py @@ -9,7 +9,7 @@ setup( name="composio_openai", - version="0.3.16", + version="0.3.17", author="Sawradip", author_email="sawradip@composio.dev", description="Use Composio to get an array of tools with your OpenAI Function Call.", @@ -22,6 +22,6 @@ "Operating System :: OS Independent", ], python_requires=">=3.9,<4", - install_requires=["composio_core==0.3.16"], + install_requires=["composio_core==0.3.17"], include_package_data=True, ) diff --git a/python/setup.py b/python/setup.py index e71a7accf6..464664125d 100644 --- a/python/setup.py +++ b/python/setup.py @@ -10,7 +10,7 @@ setup( name="composio_core", - version="0.3.16", + version="0.3.17", author="Utkarsh", author_email="utkarsh@composio.dev", description="Core package to act as a bridge between composio platform and other services.", diff --git a/python/swe/README.md b/python/swe/README.md index 0f73d01889..e33bf932e3 100644 --- a/python/swe/README.md +++ b/python/swe/README.md @@ -13,7 +13,7 @@ ## Overview -`Composio SWE` is a framework for building SWE agents on by utilising composio tooling ecosystem. Composio-SWE allows you to +`swekit` is a framework for building SWE agents on by utilising composio tooling ecosystem. SWE Kit allows you to - Scaffold agents which works out-of-the-box with choice of your agentic framework, `crewai`, `llamaindex`, etc... - Tools to add or optimise your agent's abilities @@ -26,7 +26,7 @@ Before getting started, ensure you have the following set up: 1. **Installation**: ``` - pip install composio-swe composio-core + pip install swekit composio-core ``` 2. **Install agentic framework of your choice and the Composio plugin for the same**: @@ -41,7 +41,7 @@ Before getting started, ensure you have the following set up: The agent requires a github access token to work with your repositories, You can create one at https://github.com/settings/tokens with necessary permissions and export it as an environment variable using `export GITHUB_ACCESS_TOKEN=` 4. **LLM Configuration**: - You also need to setup API key for the LLM provider you're planning to use. By default the agents scaffolded by `composio-swe` uses `openai` client, so export `OPENAI_API_KEY` before running your agent + You also need to setup API key for the LLM provider you're planning to use. By default the agents scaffolded by `swekit` uses `openai` client, so export `OPENAI_API_KEY` before running your agent ## Getting Started @@ -50,7 +50,7 @@ Before getting started, ensure you have the following set up: 1. Scaffold your agent using: ``` - composio-swe scaffold crewai -o + swekit scaffold crewai -o ``` This creates a new agent in `/agent` with four key files: diff --git a/python/swe/composio_swe/__init__.py b/python/swe/composio_swe/__init__.py deleted file mode 100644 index fa969d90a4..0000000000 --- a/python/swe/composio_swe/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Composio SWE (Software Engineering) agent framework.""" diff --git a/python/swe/composio_swe/agents/__init__.py b/python/swe/composio_swe/agents/__init__.py deleted file mode 100644 index 37d0afe559..0000000000 --- a/python/swe/composio_swe/agents/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Composio SWE Agent.""" diff --git a/python/swe/composio_swe/agents/utils.py b/python/swe/composio_swe/agents/utils.py deleted file mode 100644 index 6f940f0a68..0000000000 --- a/python/swe/composio_swe/agents/utils.py +++ /dev/null @@ -1,75 +0,0 @@ -""" -Agent runtime utilities. -""" - -import os -import typing as t - -from langchain_anthropic import ChatAnthropic -from langchain_openai import AzureChatOpenAI, ChatOpenAI -from llama_index.core.llms.function_calling import FunctionCallingLLM -from llama_index.llms.anthropic import Anthropic -from llama_index.llms.openai import OpenAI - - -def get_langchain_llm() -> t.Union[ChatOpenAI, AzureChatOpenAI, ChatAnthropic]: - helicone_api_key = os.environ.get("HELICONE_API_KEY") - if os.environ.get("ANTHROPIC_API_KEY"): - if helicone_api_key: - return ChatAnthropic( - model_name="claude-3-5-sonnet-20240620", - anthropic_api_url="https://anthropic.helicone.ai/", - default_headers={ - "Helicone-Auth": f"Bearer {helicone_api_key}", - }, - ) # type: ignore - return ChatAnthropic(model_name="claude-3-5-sonnet-20240620") # type: ignore - if os.environ.get("OPENAI_API_KEY"): - if helicone_api_key: - return ChatOpenAI( - model="gpt-4-turbo", - base_url="https://oai.helicone.ai/v1", - default_headers={ - "Helicone-Auth": f"Bearer {helicone_api_key}", - }, - ) - return ChatOpenAI(model="gpt-4-turbo") - if os.environ.get("AZURE_OPENAI_API_KEY"): - return AzureChatOpenAI(model="test") - - raise RuntimeError( - "Could not find API key for any supported LLM models, " - "please export either `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` " - "or `AZURE_OPENAI_API_KEY`" - ) - - -def get_llama_llm() -> FunctionCallingLLM: - """ - This Python function is named `get_llama_llm` and it returns an object of type `FunctionCallingLLM`. - """ - helicone_api_key = os.environ.get("HELICONE_API_KEY") - if os.environ.get("ANTHROPIC_API_KEY"): - if helicone_api_key: - return Anthropic( - model="claude-3-5-sonnet-20240620", - base_url="https://anthropic.helicone.ai/", - default_headers={ - "Helicone-Auth": f"Bearer {helicone_api_key}", - }, - ) # type: ignore - return Anthropic(model="claude-3-5-sonnet-20240620") # type: ignore - if os.environ.get("OPENAI_API_KEY"): - if helicone_api_key: - return OpenAI( - model="gpt-4-turbo", - api_base="https://oai.helicone.ai/v1", - default_headers={ - "Helicone-Auth": f"Bearer {helicone_api_key}", - }, - ) - return OpenAI(model="gpt-4-turbo") - raise RuntimeError( - "Could not find API key for any supported LLM models, " - "please export either `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` " - ) diff --git a/python/swe/composio_swe/cli.py b/python/swe/composio_swe/cli.py deleted file mode 100644 index cd544d3397..0000000000 --- a/python/swe/composio_swe/cli.py +++ /dev/null @@ -1,176 +0,0 @@ -"""CLI for composio-swe.""" - -import os -import typing as t -from pathlib import Path -from urllib.parse import urlparse - -import click -import git -from composio_swe.config.constants import ( - KEY_API_KEY, - KEY_AZURE_ENDPOINT, - KEY_GIT_ACCESS_TOKEN, - KEY_MODEL_ENV, - MODEL_ENV_AZURE, - MODEL_ENV_OPENAI, -) -from composio_swe.config.context import Context, pass_context -from composio_swe.config.store import IssueConfig -from composio_swe.exceptions import ComposioSWEError -from composio_swe.scaffold import AgenticFramework, scaffold - -from composio.cli.utils.params import EnumParam, PathParam - - -def get_git_root(): - """Try and guess the git repo, since the conf.yml can be at the repo root""" - try: - repo = git.Repo(search_parent_directories=True) - origin_url = repo.remotes.origin.url - parsed_url = urlparse(origin_url) - repo_name = parsed_url.path.strip("/").split("/")[-1] - if repo_name.endswith(".git"): - repo_name = repo_name[:-4] - return repo_name - except git.InvalidGitRepositoryError: - return None - except AttributeError as exc: - raise KeyError("No 'origin' remote found in the repository") from exc - - -@click.group(name="composio-swe") -def swe() -> None: - """Composio Coder CLI for managing the coding workspace and tasks.""" - - -@swe.command( - name="setup", - help="🔑 Setup model configuration in the current directory", -) -@pass_context -def setup(ctx: Context): - """Setup model configuration in the current directory.""" - model_env = click.prompt( - "🔑 Choose the model environment to be used for initiating agent", - type=click.Choice(["openai", "azure"], case_sensitive=False), - ) - if model_env == MODEL_ENV_OPENAI: - api_key = click.prompt("🔑 Please enter openai API key", type=str) - ctx.model_env = {KEY_MODEL_ENV: MODEL_ENV_OPENAI, KEY_API_KEY: api_key} - if model_env == MODEL_ENV_AZURE: - api_key = click.prompt("🔑 Please enter azure key", type=str) - endpoint_url = click.prompt("🌐 Please enter Azure endpoint URL", type=str) - ctx.model_env = { - KEY_MODEL_ENV: MODEL_ENV_AZURE, - KEY_API_KEY: api_key, - KEY_AZURE_ENDPOINT: endpoint_url, - } - - click.echo("🍀 Model configuration saved") - - -@swe.command( - name="add_issue", - help="➕ Add an issue configuration to the current directory", -) -@pass_context -def add_issue(ctx: Context): - """Add an issue configuration to the current directory.""" - git_access_token = os.environ.get(KEY_GIT_ACCESS_TOKEN) - if not git_access_token or not git_access_token.strip(): - click.echo(f"❗ Error: {KEY_GIT_ACCESS_TOKEN} is not set in the environment.\n") - click.echo( - f"🔑 Please export your GIT access token: {KEY_GIT_ACCESS_TOKEN} and try again !\n" - ) - return - curr_repo_name = get_git_root() - repo_name = click.prompt( - "Enter the repo name to start solving the issue", - type=str, - default="", - show_default=False, - ) - if not repo_name or not repo_name.strip(): - if curr_repo_name: - click.echo( - f"no git repo-given. Initializing git repo from current directory: {curr_repo_name}\n" - ) - repo_name = curr_repo_name - else: - click.echo("❗!! Error: no git repo found or given. Exiting setup...") - return - issue_id = click.prompt("Please enter issue id", type=str) - base_commit_id = click.prompt( - "Please enter base commit id", type=str, default="", show_default=False - ) - issue_description = click.prompt("Please enter issue description", type=str) - ctx.issue_config = IssueConfig.model_validate( - { - "repo_name": repo_name, - "base_commit_id": base_commit_id, - "issue_desc": issue_description, - "issue_id": issue_id, - } - ) - - click.echo("🍀 Issue configuration saved\n") - - -@swe.command( - name="solve", - help="👷 Start solving the configured issue", -) -@pass_context -def solve(ctx: Context): - """Start solving the configured issue.""" - raise NotImplementedError() - - -@swe.command( - name="workflow", - help="📋 Show the workflow: setup -> add_issue -> solve", -) -@click.help_option("--help", "-h", "-help") -def show_workflow(): - # Add the workflow description - click.echo("\nWorkflow:") - click.echo(" 1. 🔑 setup: Setup model configuration in the current directory") - click.echo(" 2. ➕ add_issue: Add an issue configuration to the current directory") - click.echo(" 3. 👷 solve: Start solving the configured issue\n") - - -@swe.command(name="scaffold") -@click.argument("framework", type=EnumParam(cls=AgenticFramework)) -@click.option( - "-n", - "--name", - type=str, - help="Name of agent", -) -@click.option( - "-o", - "--outdir", - type=PathParam(), - help="Output directory for the agent", -) -@click.help_option("--help") -def _scaffold( - framework: AgenticFramework, - name: t.Optional[str] = None, - outdir: t.Optional[Path] = None, -) -> None: - """Scaffold and agent using Composio SWE tools""" - try: - output = scaffold( - framework=framework, - name=name, - outdir=outdir, - ) - click.echo(f"🤖 Scaffolded agent @ {output}") - except ComposioSWEError as e: - raise click.ClickException(str(e)) from e - - -if __name__ == "__main__": - swe() diff --git a/python/swe/composio_swe/exceptions.py b/python/swe/composio_swe/exceptions.py deleted file mode 100644 index 9c2054e5f6..0000000000 --- a/python/swe/composio_swe/exceptions.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Composio SWE Exceptions.""" - - -class ComposioSWEError(Exception): - """Base exception for handling SWE errors.""" diff --git a/python/swe/examples/crewai_agent.py b/python/swe/examples/crewai_agent.py index 959d96a3d3..072b5d39ee 100644 --- a/python/swe/examples/crewai_agent.py +++ b/python/swe/examples/crewai_agent.py @@ -3,11 +3,11 @@ """ from composio_crewai import App, ComposioToolSet -from composio_swe.agents.base import BaseSWEAgent, SWEArgs -from composio_swe.agents.utils import get_langchain_llm -from composio_swe.config.store import IssueConfig from crewai import Agent, Task from langchain_core.agents import AgentAction, AgentFinish +from swekit.agents.base import BaseSWEAgent, SWEArgs +from swekit.agents.utils import get_langchain_llm +from swekit.config.store import IssueConfig from swe.examples.prompts import AGENT_BACKSTORY_TMPL, ISSUE_DESC_TMPL diff --git a/python/swe/examples/llama_agent.py b/python/swe/examples/llama_agent.py index 972aaedd58..26665a6b09 100644 --- a/python/swe/examples/llama_agent.py +++ b/python/swe/examples/llama_agent.py @@ -1,9 +1,9 @@ from composio_llamaindex import Action, App, ComposioToolSet -from composio_swe.agents.base import BaseSWEAgent, SWEArgs -from composio_swe.agents.utils import get_llama_llm -from composio_swe.config.store import IssueConfig from llama_index.core.agent import FunctionCallingAgentWorker from llama_index.core.llms import ChatMessage, MessageRole +from swekit.agents.base import BaseSWEAgent, SWEArgs +from swekit.agents.utils import get_llama_llm +from swekit.config.store import IssueConfig from swe.examples.prompts import AGENT_BACKSTORY_TMPL, ISSUE_DESC_TMPL diff --git a/python/swe/setup.py b/python/swe/setup.py index 172ec4705b..e168ef07a8 100644 --- a/python/swe/setup.py +++ b/python/swe/setup.py @@ -1,5 +1,5 @@ """ -Setup configuration for Composio SWE Agent plugin +Setup configuration for SWE Kit. """ from pathlib import Path @@ -8,8 +8,8 @@ setup( - name="composio_swe", - version="0.0.1", + name="swekit", + version="0.1.0-rc0", author="Shubhra", author_email="shubhra@composio.dev", description="Tools for running a SWE agent using Composio platform", @@ -22,30 +22,27 @@ "Operating System :: OS Independent", ], python_requires=">=3.9,<4", - packages=find_packages(include=["composio_swe*"]), + packages=find_packages(include=["swekit*"]), entry_points={ "console_scripts": [ - "composio-swe=composio_swe.cli:swe", + "swekit=swekit.cli:swekit", ], }, + package_data={ + "swekit": [ + "py.typed", + "scaffold/templates/crewai/*", + ], + }, + include_package_data=True, install_requires=[ "pydantic>=2.7.4", "swebench==1.1.0", "datasets>=2.20.0", "gitpython>=3.1.43", - "crewai==0.30.11", - "composio_crewai>=0.3.9", "composio_core>=0.3.9", "unidiff==0.7.5", "tqdm==4.66.4", - "langchain-core", - "langchain-openai", - "langchain-anthropic", - "llama-index-llms-anthropic", "rich", ], - dependency_links=[ - "git+https://github.com/ComposioHQ/SWE-bench-docker.git", - ], - include_package_data=True, ) diff --git a/python/swe/swekit/__init__.py b/python/swe/swekit/__init__.py new file mode 100644 index 0000000000..50815adfdf --- /dev/null +++ b/python/swe/swekit/__init__.py @@ -0,0 +1 @@ +"""Composio SWE (Software Engineering) kit.""" diff --git a/python/swe/composio_swe/__main__.py b/python/swe/swekit/__main__.py similarity index 57% rename from python/swe/composio_swe/__main__.py rename to python/swe/swekit/__main__.py index f061058ce0..7f574904c0 100644 --- a/python/swe/composio_swe/__main__.py +++ b/python/swe/swekit/__main__.py @@ -1,7 +1,7 @@ """Pyrunner entrypoint.""" -from composio_swe.cli import swe +from swekit.cli import swekit if __name__ == "__main__": - swe() + swekit() diff --git a/python/swe/swekit/agents/__init__.py b/python/swe/swekit/agents/__init__.py new file mode 100644 index 0000000000..f321472e4e --- /dev/null +++ b/python/swe/swekit/agents/__init__.py @@ -0,0 +1 @@ +"""SWE Kit agents.""" diff --git a/python/swe/composio_swe/agents/base.py b/python/swe/swekit/agents/base.py similarity index 95% rename from python/swe/composio_swe/agents/base.py rename to python/swe/swekit/agents/base.py index a0102e867c..0c44964ce2 100644 --- a/python/swe/composio_swe/agents/base.py +++ b/python/swe/swekit/agents/base.py @@ -9,9 +9,9 @@ from pathlib import Path from composio_crewai import ComposioToolSet -from composio_swe.config.store import IssueConfig -from composio_swe.exceptions import ComposioSWEError from pydantic import BaseModel, Field +from swekit.config.store import IssueConfig +from swekit.exceptions import SWEKitError from composio import Action from composio.utils import logging @@ -84,7 +84,7 @@ def setup_and_solve( isinstance(get_patch_resp, dict) and get_patch_resp.get("status") == "failure" ): - raise ComposioSWEError(get_patch_resp["details"]) + raise SWEKitError(get_patch_resp["details"]) self.logger.info(f"Get patch response: {get_patch_resp}") patch = get_patch_resp.get("stdout") # type: ignore self.logger.info(f"Final Patch: {patch}") diff --git a/python/swe/composio_swe/benchmark/__init__.py b/python/swe/swekit/benchmark/__init__.py similarity index 100% rename from python/swe/composio_swe/benchmark/__init__.py rename to python/swe/swekit/benchmark/__init__.py diff --git a/python/swe/composio_swe/benchmark/complete_eval_workflow.sh b/python/swe/swekit/benchmark/complete_eval_workflow.sh similarity index 100% rename from python/swe/composio_swe/benchmark/complete_eval_workflow.sh rename to python/swe/swekit/benchmark/complete_eval_workflow.sh diff --git a/python/swe/composio_swe/benchmark/constants.py b/python/swe/swekit/benchmark/constants.py similarity index 100% rename from python/swe/composio_swe/benchmark/constants.py rename to python/swe/swekit/benchmark/constants.py diff --git a/python/swe/composio_swe/benchmark/get_score_card.py b/python/swe/swekit/benchmark/get_score_card.py similarity index 100% rename from python/swe/composio_swe/benchmark/get_score_card.py rename to python/swe/swekit/benchmark/get_score_card.py diff --git a/python/swe/composio_swe/benchmark/run_evaluation.py b/python/swe/swekit/benchmark/run_evaluation.py similarity index 60% rename from python/swe/composio_swe/benchmark/run_evaluation.py rename to python/swe/swekit/benchmark/run_evaluation.py index 07dffe07de..826b85ac67 100644 --- a/python/swe/composio_swe/benchmark/run_evaluation.py +++ b/python/swe/swekit/benchmark/run_evaluation.py @@ -7,26 +7,25 @@ import typing as t from pathlib import Path -import utils as eval_utils +import swekit.benchmark.utils as eval_utils from composio_crewai import ComposioToolSet -from composio_swe.config.constants import LOCAL_CACHE_DIRECTORY_NAME, LOGS_DIR -from composio_swe.config.store import IssueConfig from pydantic import BaseModel, Field +from swekit.config.constants import LOCAL_CACHE_DIRECTORY_NAME, LOGS_DIR +from swekit.config.store import IssueConfig from tqdm import tqdm from composio import Action from composio.utils.logging import WithLogger -from swe.examples.crewai_agent import CrewaiAgent, SWEArgs -logger = WithLogger.logger - - -def default_agent_func(workspace_id, issue_config): - return CrewaiAgent( - args=SWEArgs(agent_logs_dir=Path("")), - workspace_id=workspace_id, - ).setup_and_solve(issue_config=issue_config, workspace_id=workspace_id) +def _get_logs_dir() -> Path: + """Logs dir factory.""" + return ( + Path.home() + / LOCAL_CACHE_DIRECTORY_NAME + / LOGS_DIR + / str(int(datetime.datetime.now().timestamp())) + ) class EvaluationArgs(BaseModel): @@ -36,9 +35,11 @@ class EvaluationArgs(BaseModel): dry_run: bool = Field( default=False, description="dry-run will only print short issue description" ) - include_hints: bool = Field(default=False) + include_hints: bool = Field( + default=False, + ) logs_dir: Path = Field( - default=f"{Path.home()}/{LOCAL_CACHE_DIRECTORY_NAME}/{LOGS_DIR}/{int(datetime.datetime.now().timestamp())}", + default_factory=_get_logs_dir, description="Logs directory", ) generate_report: bool = Field( @@ -46,15 +47,16 @@ class EvaluationArgs(BaseModel): ) -class EvaluationManager: +class EvaluationManager(WithLogger): def __init__(self, eval_args: EvaluationArgs): + super().__init__() self.issues = eval_utils.get_issues_dataset(eval_args.test_range) self.dry_run = eval_args.dry_run self.include_hints = eval_args.include_hints self.logs_dir = os.path.expanduser(eval_args.logs_dir) self.repo_to_workspace_map = {} self.repo_to_image_id_map = {} - logs_dir = Path(args.logs_dir) + logs_dir = Path(eval_args.logs_dir) if not logs_dir.exists(): logs_dir.mkdir(parents=True) @@ -71,7 +73,7 @@ def get_issue_config(self, issue) -> IssueConfig: def get_patch_for_issue(self, workspace_id: str, issue): composio_toolset = ComposioToolSet(workspace_id=workspace_id) - logger.info( + self.logger.info( f"Agent run finished, getting path for issue: {issue['instance_id']}" ) get_patch_resp = composio_toolset.execute_action( @@ -83,14 +85,14 @@ def get_patch_for_issue(self, workspace_id: str, issue): and get_patch_resp.get("status") == "failure" ): raise Exception(get_patch_resp) - logger.info(f"Get patch response: {get_patch_resp}") + self.logger.info(f"Get patch response: {get_patch_resp}") patch = get_patch_resp.get("stdout") # type: ignore - logger.info(f"Final Patch: {patch}") + self.logger.info(f"Final Patch: {patch}") return patch def save_agent_run(self, issue_config, issue_patch): Path(str(self.logs_dir)).mkdir(parents=True, exist_ok=True) - task_output_log = f"{self.logs_dir}/agent_logs_{datetime.datetime.now().strftime('%m_%d_%Y_%H_%M_%S')}.json.log" + task_output_log = f"{self.logs_dir}/agent_logs_{datetime.datetime.now().strftime('%m_%d_%Y_%H_%M_%S')}.json" with open(task_output_log, "w", encoding="utf-8") as f: f.write( json.dumps( @@ -114,24 +116,30 @@ def show_info_and_exit(self): "Include Hints": self.include_hints, "Logs Directory": str(self.logs_dir), "Total Issues": len(self.issues), - "Test Range": self.issues.num_rows - if hasattr(self.issues, "num_rows") - else "Unknown", - "Dataset Description": self.issues.info.description - if hasattr(self.issues, "info") and self.issues.info.description - else "No description available", - "Number of Features": len(self.issues.features) - if hasattr(self.issues, "features") - else "Unknown", - "Features": list(self.issues.features.keys()) - if hasattr(self.issues, "features") - else "Unknown", + "Test Range": ( + self.issues.num_rows if hasattr(self.issues, "num_rows") else "Unknown" + ), + "Dataset Description": ( + self.issues.info.description + if hasattr(self.issues, "info") and self.issues.info.description + else "No description available" + ), + "Number of Features": ( + len(self.issues.features) + if hasattr(self.issues, "features") + else "Unknown" + ), + "Features": ( + list(self.issues.features.keys()) + if hasattr(self.issues, "features") + else "Unknown" + ), } print("Evaluation Setup Information:") for key, value in info.items(): print(f"{key}: {value}") - def run(self, agent_func: t.Callable = default_agent_func): + def run(self, agent_func: t.Callable): """ Main function to load and display entries from the SWE-bench lite dataset. """ @@ -150,7 +158,7 @@ def run(self, agent_func: t.Callable = default_agent_func): ) if version and eval_utils.check_and_pull_image(image_name): self.repo_to_image_id_map.setdefault(repo, image_name) - logger.info( + self.logger.info( f"Processing issue: {count} with repoMap: {self.repo_to_workspace_map}" f"Repo: {repo}" f"Issue id: {issue['instance_id']}" @@ -163,7 +171,7 @@ def run(self, agent_func: t.Callable = default_agent_func): issue["base_commit"], ) issue_config = self.get_issue_config(issue) - logger.info( + self.logger.info( "found patch-id: %s and install_commit_id: %s", issue["patch"], issue["environment_setup_commit"], @@ -174,32 +182,82 @@ def run(self, agent_func: t.Callable = default_agent_func): self.save_agent_run(issue_config, issue_patch) except Exception as e: - logger.error(f"Error processing issue {issue['instance_id']}: {e}") + self.logger.error(f"Error processing issue {issue['instance_id']}: {e}") raise e def score_evaluation(self): eval_utils.get_score(self.logs_dir) +def evaluate( + runnable: t.Callable, + test_range: str = "20:22", + dry_run: bool = True, + include_hints: bool = True, + logs_dir: Path = _get_logs_dir(), + generate_report: bool = True, +) -> None: + """Evaluate a callable.""" + manager = EvaluationManager( + EvaluationArgs( + test_range=test_range, + dry_run=dry_run, + include_hints=include_hints, + logs_dir=logs_dir, + generate_report=generate_report, + ) + ) + manager.run(runnable) + manager.score_evaluation() + + if __name__ == "__main__": - # fmt: off parser = argparse.ArgumentParser(description="Run SWE-bench evaluation") - parser.add_argument("--test_range", type=str, default="20:22", help="Test split range (e.g., 1:10)") - parser.add_argument("--dry_run", action="store_true", default=True, help="Just print the issues without running an agent",) - parser.add_argument("--include_hints", action="store_true", default=False, help="Include hints in the issue description",) - parser.add_argument("--gen_report", action="store_true", default=True, help="Generate a report after running evaluations",) - parser.add_argument("--logs_dir", type=str, help="Logs directory") + parser.add_argument( + "--test_range", + type=str, + default="20:22", + help="Test split range (e.g., 1:10)", + ) + parser.add_argument( + "--dry_run", + action="store_true", + default=True, + help="Just print the issues without running an agent", + ) + parser.add_argument( + "--include_hints", + action="store_true", + default=False, + help="Include hints in the issue description", + ) + parser.add_argument( + "--gen_report", + action="store_true", + default=True, + help="Generate a report after running evaluations", + ) + parser.add_argument( + "--logs_dir", + type=str, + help="Logs directory", + default=_get_logs_dir(), + ) args = parser.parse_args() - # fmt: on - eval_manager = EvaluationManager( - EvaluationArgs( - test_range=args.test_range, - dry_run=args.dry_run, - include_hints=args.include_hints, - logs_dir=args.logs_dir, - generate_report=args.gen_report, - ) + from swe.examples.crewai_agent import CrewaiAgent, SWEArgs + + def default_agent_func(workspace_id, issue_config): + return CrewaiAgent( + args=SWEArgs(agent_logs_dir=Path("")), + workspace_id=workspace_id, + ).setup_and_solve(issue_config=issue_config, workspace_id=workspace_id) + + evaluate( + default_agent_func, + test_range=args.test_range, + dry_run=args.dry_run, + include_hints=args.include_hints, + logs_dir=args.logs_dir, + generate_report=args.gen_report, ) - eval_manager.run(default_agent_func) - eval_manager.score_evaluation() diff --git a/python/swe/composio_swe/benchmark/setup_test_bed.py b/python/swe/swekit/benchmark/setup_test_bed.py similarity index 99% rename from python/swe/composio_swe/benchmark/setup_test_bed.py rename to python/swe/swekit/benchmark/setup_test_bed.py index 5b112325c3..22b127260b 100644 --- a/python/swe/composio_swe/benchmark/setup_test_bed.py +++ b/python/swe/swekit/benchmark/setup_test_bed.py @@ -4,14 +4,14 @@ from codecs import decode, encode from pathlib import Path -from composio_swe.benchmark.constants import ( +from datasets import load_dataset +from swebench import KEY_INSTANCE_ID, KEY_MODEL, KEY_PREDICTION +from swekit.benchmark.constants import ( MODEL_GPT4, PATH_PATCHES_JSON, SUBMIT_PATCH_CMD, TEST_SPLIT, ) -from datasets import load_dataset -from swebench import KEY_INSTANCE_ID, KEY_MODEL, KEY_PREDICTION def download_and_store_dataset(dataset_path_or_name, path_on_disk): diff --git a/python/swe/composio_swe/benchmark/utils.py b/python/swe/swekit/benchmark/utils.py similarity index 96% rename from python/swe/composio_swe/benchmark/utils.py rename to python/swe/swekit/benchmark/utils.py index 4d16141726..0deb0e44b6 100644 --- a/python/swe/composio_swe/benchmark/utils.py +++ b/python/swe/swekit/benchmark/utils.py @@ -7,13 +7,14 @@ import docker from composio_crewai import ComposioToolSet -from composio_swe.benchmark.constants import MODEL_GPT4 -from composio_swe.benchmark.get_score_card import generate_scorecard -from composio_swe.benchmark.setup_test_bed import create_patches_file from datasets import load_dataset from docker import errors as docker_errors +from swekit.benchmark.constants import MODEL_GPT4 +from swekit.benchmark.get_score_card import generate_scorecard +from swekit.benchmark.setup_test_bed import create_patches_file from composio import Action +from composio.tools.env.constants import DEFAULT_IMAGE from composio.tools.env.factory import ExecEnv, WorkspaceFactory from composio.utils.logging import get as get_logger from swe.swe_bench_docker.evaulate_on_docker import EvaluateOnDockerArgs, evaluate @@ -133,7 +134,7 @@ def build_image_and_container(repo, repo_to_workspace_map, base_commit): start_time = datetime.datetime.now() workspace = WorkspaceFactory.new( env=ExecEnv.DOCKER, - image="sweagent/swe-agent", + image=DEFAULT_IMAGE, ) workspace_creation_time = datetime.datetime.now() - start_time logger.info( diff --git a/python/swe/composio_swe/benchmark/visualize.py b/python/swe/swekit/benchmark/visualize.py similarity index 100% rename from python/swe/composio_swe/benchmark/visualize.py rename to python/swe/swekit/benchmark/visualize.py diff --git a/python/swe/swekit/cli.py b/python/swe/swekit/cli.py new file mode 100644 index 0000000000..a94d47a9d0 --- /dev/null +++ b/python/swe/swekit/cli.py @@ -0,0 +1,51 @@ +"""CLI for SWE Kit.""" + +import typing as t +from pathlib import Path + +import click +from swekit.exceptions import SWEKitError +from swekit.scaffold import AgenticFramework, scaffold + +from composio.cli.utils.params import EnumParam, PathParam + + +@click.group(name="swekit") +def swekit() -> None: + """Composio Coder CLI for managing the coding workspace and tasks.""" + + +@swekit.command(name="scaffold") +@click.argument("framework", type=EnumParam(cls=AgenticFramework)) +@click.option( + "-n", + "--name", + type=str, + help="Name of agent", +) +@click.option( + "-o", + "--outdir", + type=PathParam(), + help="Output directory for the agent", +) +@click.help_option("--help") +def _scaffold( + framework: AgenticFramework, + name: t.Optional[str] = None, + outdir: t.Optional[Path] = None, +) -> None: + """🤖 Scaffold agent using composio toolset.""" + try: + output = scaffold( + framework=framework, + name=name, + outdir=outdir, + ) + click.echo(f"🤖 Scaffolded agent @ {output}") + except SWEKitError as e: + raise click.ClickException(str(e)) from e + + +if __name__ == "__main__": + swekit() diff --git a/python/swe/composio_swe/config/__init__.py b/python/swe/swekit/config/__init__.py similarity index 100% rename from python/swe/composio_swe/config/__init__.py rename to python/swe/swekit/config/__init__.py diff --git a/python/swe/composio_swe/config/constants.py b/python/swe/swekit/config/constants.py similarity index 90% rename from python/swe/composio_swe/config/constants.py rename to python/swe/swekit/config/constants.py index bd61c25297..f2cb1a8535 100644 --- a/python/swe/composio_swe/config/constants.py +++ b/python/swe/swekit/config/constants.py @@ -1,4 +1,4 @@ -"""Constants for composio-swe.""" +"""Constants for SWE Kit.""" LOCAL_CACHE_DIRECTORY_NAME = ".composio_coder" MODEL_ENV_PATH = "model_env" diff --git a/python/swe/composio_swe/config/context.py b/python/swe/swekit/config/context.py similarity index 98% rename from python/swe/composio_swe/config/context.py rename to python/swe/swekit/config/context.py index f47b747ebd..a9d27ac617 100644 --- a/python/swe/composio_swe/config/context.py +++ b/python/swe/swekit/config/context.py @@ -9,7 +9,8 @@ import click import typing_extensions as te from click.globals import get_current_context as get_click_context -from composio_swe.config.constants import ( +from rich.console import Console +from swekit.config.constants import ( ISSUE_CONFIG_PATH, KEY_API_KEY, KEY_AZURE_ENDPOINT, @@ -20,13 +21,12 @@ MODEL_ENV_OPENAI, MODEL_ENV_PATH, ) -from composio_swe.config.store import ( +from swekit.config.store import ( AzureModelConfig, IssueConfig, ModelEnv, OpenAiModelConfig, ) -from rich.console import Console _context: t.Optional["Context"] = None diff --git a/python/swe/composio_swe/config/store.py b/python/swe/swekit/config/store.py similarity index 100% rename from python/swe/composio_swe/config/store.py rename to python/swe/swekit/config/store.py diff --git a/python/swe/swekit/exceptions.py b/python/swe/swekit/exceptions.py new file mode 100644 index 0000000000..0817503ab4 --- /dev/null +++ b/python/swe/swekit/exceptions.py @@ -0,0 +1,5 @@ +"""SWE Kit Exceptions.""" + + +class SWEKitError(Exception): + """Base exception for handling SWE errors.""" diff --git a/python/swe/swekit/py.typed b/python/swe/swekit/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python/swe/composio_swe/scaffold/__init__.py b/python/swe/swekit/scaffold/__init__.py similarity index 68% rename from python/swe/composio_swe/scaffold/__init__.py rename to python/swe/swekit/scaffold/__init__.py index 116a5e47ec..05a05f653b 100644 --- a/python/swe/composio_swe/scaffold/__init__.py +++ b/python/swe/swekit/scaffold/__init__.py @@ -1,4 +1,4 @@ -"""Scaffolding Utilities Composio SWE Agents.""" +"""Scaffolding Utilities.""" from ._scaffold import AgenticFramework, scaffold diff --git a/python/swe/composio_swe/scaffold/_scaffold.py b/python/swe/swekit/scaffold/_scaffold.py similarity index 83% rename from python/swe/composio_swe/scaffold/_scaffold.py rename to python/swe/swekit/scaffold/_scaffold.py index cc54298865..cdbe085ad4 100644 --- a/python/swe/composio_swe/scaffold/_scaffold.py +++ b/python/swe/swekit/scaffold/_scaffold.py @@ -4,8 +4,8 @@ from enum import Enum from pathlib import Path -from composio_swe.exceptions import ComposioSWEError -from composio_swe.scaffold.templates import PATH as TEMPLATES_PATH +from swekit.exceptions import SWEKitError +from swekit.scaffold.templates import PATH as TEMPLATES_PATH class AgenticFramework(Enum): @@ -35,7 +35,7 @@ def scaffold( output = outdir / name if output.exists(): - raise ComposioSWEError(f"Directory already exists @ {output}") + raise SWEKitError(f"Directory already exists @ {output}") output.mkdir() for file, template in framework.load_templates().items(): diff --git a/python/swe/composio_swe/scaffold/templates/__init__.py b/python/swe/swekit/scaffold/templates/__init__.py similarity index 100% rename from python/swe/composio_swe/scaffold/templates/__init__.py rename to python/swe/swekit/scaffold/templates/__init__.py diff --git a/python/swe/composio_swe/scaffold/templates/crewai/__init__.template b/python/swe/swekit/scaffold/templates/crewai/__init__.template similarity index 100% rename from python/swe/composio_swe/scaffold/templates/crewai/__init__.template rename to python/swe/swekit/scaffold/templates/crewai/__init__.template diff --git a/python/swe/composio_swe/scaffold/templates/crewai/agent.template b/python/swe/swekit/scaffold/templates/crewai/agent.template similarity index 100% rename from python/swe/composio_swe/scaffold/templates/crewai/agent.template rename to python/swe/swekit/scaffold/templates/crewai/agent.template diff --git a/python/swe/composio_swe/scaffold/templates/crewai/benchmark.template b/python/swe/swekit/scaffold/templates/crewai/benchmark.template similarity index 70% rename from python/swe/composio_swe/scaffold/templates/crewai/benchmark.template rename to python/swe/swekit/scaffold/templates/crewai/benchmark.template index a1c66b4941..8c363c5c5f 100644 --- a/python/swe/composio_swe/scaffold/templates/crewai/benchmark.template +++ b/python/swe/swekit/scaffold/templates/crewai/benchmark.template @@ -1,6 +1,6 @@ from agent import composio_toolset, crew -from composio_swe.benchmark.run_evaluation import run_and_get_scores -from composio_swe.config.store import IssueConfig +from swekit.benchmark.run_evaluation import evaluate +from swekit.config.store import IssueConfig import argparse @@ -20,7 +20,9 @@ def bench(workspace_id: str, issue_config: IssueConfig) -> str: if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Run benchmark on the agent.") + parser = argparse.ArgumentParser( + description="Run benchmark on the agent.", + ) parser.add_argument( "--test-split", type=str, @@ -28,5 +30,8 @@ if __name__ == "__main__": help="Test split ratio (e.g. 1:2, 1:300) Maximum 300 tests per project.", ) args = parser.parse_args() - - run_and_get_scores(bench, test_split=args.test_split) + evaluate( + bench, + dry_run=False, + test_range=args.test_split, + ) diff --git a/python/swe/composio_swe/scaffold/templates/crewai/inputs.template b/python/swe/swekit/scaffold/templates/crewai/inputs.template similarity index 100% rename from python/swe/composio_swe/scaffold/templates/crewai/inputs.template rename to python/swe/swekit/scaffold/templates/crewai/inputs.template diff --git a/python/swe/composio_swe/scaffold/templates/crewai/main.template b/python/swe/swekit/scaffold/templates/crewai/main.template similarity index 100% rename from python/swe/composio_swe/scaffold/templates/crewai/main.template rename to python/swe/swekit/scaffold/templates/crewai/main.template diff --git a/python/swe/composio_swe/scaffold/templates/crewai/prompts.template b/python/swe/swekit/scaffold/templates/crewai/prompts.template similarity index 100% rename from python/swe/composio_swe/scaffold/templates/crewai/prompts.template rename to python/swe/swekit/scaffold/templates/crewai/prompts.template diff --git a/python/swe/tests/test_cli.py b/python/swe/tests/test_cli.py index 4a17471971..43ea58a6a4 100644 --- a/python/swe/tests/test_cli.py +++ b/python/swe/tests/test_cli.py @@ -7,10 +7,10 @@ import click.testing from click.testing import CliRunner -from composio_swe.cli import swe -from composio_swe.config.context import Context, set_context from langchain_core.callbacks.manager import CallbackManagerForLLMRun from langchain_core.language_models.llms import LLM +from swekit.cli import swekit +from swekit.config.context import Context, set_context # pylint: disable=unused-argument @@ -76,7 +76,7 @@ def handle_exception(self, result: click.testing.Result): def test_openai_setup(self): """Test the openai setup command.""" with self.runner.isolated_filesystem(): - result = self.runner.invoke(swe, ["setup"], input="openai\napi_key\n") + result = self.runner.invoke(swekit, ["setup"], input="openai\napi_key\n") self.handle_exception(result) self.assertIn("Model configuration saved", result.output) self.assertEqual(result.exit_code, 0) @@ -85,7 +85,7 @@ def test_azure_setup(self): """Test the azure setup command.""" with self.runner.isolated_filesystem(): result = self.runner.invoke( - swe, ["setup"], input="azure\napi_key\nend_point_url\n" + swekit, ["setup"], input="azure\napi_key\nend_point_url\n" ) self.handle_exception(result) self.assertIn("Model configuration saved", result.output) @@ -95,7 +95,7 @@ def test_add_issue(self): """Test the add_issue command.""" with self.runner.isolated_filesystem(): result = self.runner.invoke( - swe, + swekit, ["add_issue"], input="repo_name\nissue_id\nbase_commit_id\nissue_description\n", env={"GITHUB_ACCESS_TOKEN": "DEFAULT-TOKEN"}, @@ -123,7 +123,7 @@ def test_solve_openai(self): with patch("composio_coders.swe.CoderAgent.get_llm") as mock_get_llm: mock_get_llm.return_value = FakeListLLM(responses=["Fake Response"]) - result = self.runner.invoke(swe, ["solve"]) + result = self.runner.invoke(swekit, ["solve"]) self.handle_exception(result) mock_get_llm.assert_called_once() self.assertEqual(result.exit_code, 0) @@ -151,14 +151,14 @@ def test_solve_azure(self): with patch("composio_coders.swe.CoderAgent.get_llm") as mock_get_llm: mock_get_llm.return_value = FakeListLLM(responses=["Fake Response"]) - result = self.runner.invoke(swe, ["solve"]) + result = self.runner.invoke(swekit, ["solve"]) self.handle_exception(result) mock_get_llm.assert_called_once() self.assertEqual(result.exit_code, 0) def test_show_workflow(self): """Test the show_workflow command.""" - result = self.runner.invoke(swe, ["workflow"]) + result = self.runner.invoke(swekit, ["workflow"]) self.handle_exception(result) self.assertIn("Workflow:", result.output) self.assertEqual(result.exit_code, 0)