From a242ed8fdf6311ba2febbe3508ec25c3552497c8 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Wed, 23 Jul 2025 05:58:49 +0530 Subject: [PATCH] Update README, LICENSE & CONTRIBUTING.md --- CHANGELOG.md | 2 +- CONTRIBUTING.md | 35 ++++++ LICENSE | 21 ++++ README.md | 20 +++- packages/bot/README.md | 220 +++++++++++++++++++++++++++++++++++- packages/bot/pyproject.toml | 2 +- 6 files changed, 296 insertions(+), 4 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a15c7..2369bed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,4 +2,4 @@ Please refer to individual package changelogs: -* [`automa-bot`](./packages/bot/CHANGELOG.md) +- [`automa-bot`](./packages/bot/CHANGELOG.md) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3ed1a81 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,35 @@ +# How to Contribute + +## Prerequisites + +- Have [`git`](https://git-scm.com/) installed. +- Have [`uv`](https://docs.astral.sh/uv/) installed. + +## Installing dependencies + +```sh +uv sync +``` + +## CI/CD + +#### Testing + +In each package, you can run tests using: + +```sh +export PYTHON_ENV=test +uv run pytest +``` + +#### Linting + +```sh +uv run ruff check +``` + +#### Formatting + +```sh +uv run ruff format +``` diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c4894bd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Sunkara, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 64d49cc..e9c359d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,21 @@ # sdk-python -Automa SDK for Python +Automa SDKs for Python. + +Please refer to individual package documentation: + +- [`automa-bot`](./packages/bot) + +Please refer to the [Automa documentation](https://docs.automa.app/sdks) for more information on how to use these SDKs. + +## Contributing + +Contributions and feedback are welcome! Feel free to open an issue or submit a pull request. See [CONTRIBUTING.md](CONTRIBUTING.md) for more details. Here is a list of [Contributors](https://github.com/automa/sdk-python/contributors). + +## LICENSE + +MIT + +## Bug Reports + +Report [here](https://github.com/automa/sdk-python/issues). diff --git a/packages/bot/README.md b/packages/bot/README.md index 4fed4c3..71df697 100644 --- a/packages/bot/README.md +++ b/packages/bot/README.md @@ -1,3 +1,221 @@ # automa-bot -Bot helpers for Automa +Bot SDK for Automa. + +Please read more about Automa [Bots](https://docs.automa.app/bots) and their [development](https://docs.automa.app/bot-development) in our documentation. + +1. [Installation](#installation) +2. [Usage](#usage) +3. [Webhook signatures](#webhook-signatures) +4. [Testing](#testing) +5. [Reference](#reference) + +## Installation + +```sh +# Using pip +pip install automa-bot + +# Using uv +uv add automa-bot +``` + +## Usage + +```python +from automa import Automa + +client = Automa() + +def main(): + # Download code for a task + folder = client.code.download({ + "task": { + "id": 10, + "token": '3ee12f8ca60132c087c6303efb46c3b5', + }, + }) + + # Change code in the folder ... + + # Propose the changed code + client.code.propose({ + "task": { "id": 10 }, + }) + + # Remove the downloaded code folder + client.code.cleanup({ + "task": { "id": 10 }, + }) + +main() +``` + +### Asynchronous + +Simply import `AsyncAutoma` instead of `Automa` and use `await` with each method call: + +```python +import asyncio +from automa import AsyncAutoma + +client = AsyncAutoma() + +async def main() -> None: + # Download code for a task + folder = await client.code.download({ + "task": { + "id": 10, + "token": '3ee12f8ca60132c087c6303efb46c3b5', + }, + }) + + # Change code in the folder ... + + # Propose the changed code + await client.code.propose({ + "task": { "id": 10 }, + }) + + # Remove the downloaded code folder + await client.code.cleanup({ + "task": { "id": 10 }, + }) + +asyncio.run(main()) +``` + +Functionality between the synchronous and asynchronous clients is otherwise identical. + +### Managing client resource + +By default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting. + +```py +from automa import Automa + +with Automa() as client: + # make requests here + ... + +# HTTP client is now closed +``` + +## Webhook signatures + +To verify webhook signatures, you can use the `verify_webhook` helper provided by the SDK. + +```python +import os +from automa.bot.webhook import verify_webhook + +payload = (await request.body()).decode("utf-8") # The body of the webhook request +signature = request.headers.get('webhook-signature') # The signature header from the request + +is_valid = verify_webhook( + os.environ['AUTOMA_WEBHOOK_SECRET'], + signature, + payload +) +``` + +## Testing + +When writing tests for your bot, you can mock the client methods to simulate the behavior of the SDK without making actual network requests. + +```python +from automa.bot import CodeFolder + +fixture_code = CodeFolder("." / "fixtures" / "code") + +@patch("automa.bot.AsyncCodeResource.cleanup") +@patch("automa.bot.AsyncCodeResource.propose") +@patch("automa.bot.AsyncCodeResource.download", return_value=fixture_code) +def test(download_mock, propose_mock, cleanup_mock): + pass +``` + +### Webhook signatures in tests + +When testing webhook handling, you may want to simulate valid webhook requests. The SDK provides `generate_webhook_signature` helper to generate valid signatures for your test payloads. + +```python +import os +from automa.bot.webhook import generate_webhook_signature + +payload = '{}' # Example payload + +signature = generate_webhook_signature( + os.environ['AUTOMA_WEBHOOK_SECRET'], + payload +) + +# Use this signature in your tests to simulate a valid webhook request +``` + +## Reference + +Please find below the reference for both the client and its methods in the SDK. + +All methods are available in both synchronous and asynchronous clients. + +### `Automa`/`AsyncAutoma` + +Named parameters: + +- `base_url` (optional): Base URL for the Automa API. Defaults to `https://api.automa.app`. + + If you are using the bot with a self-hosted instance of Automa, you can specify the base URL like this: + + ```python + client = Automa(base_url="https://api.your-automa-instance.com") + ``` + +Properties: + +- `code`: `CodeResource` / `AsyncCodeResource` providing code related methods. + +### `code.download` + +Downloads the code for the specified task and returns a [`CodeFolder`](#codefolder) pointing to the cloned or extracted code directory. + +Parameters: + +- `body` (`CodeDownloadParams`) + - `task` (dict) + - `id` (int): The identifier of the task. + - `token` (str): The authorization token for the task sent in webhook request. + +### `code.propose` + +Submits a code change proposal for the specified task, using the diff between the current working directory and the base commit saved on download. + +Parameters: + +- `body` (`CodeProposeParams`) + - `task` (dict) + - `id` (int): The identifier of the task. + - `proposal` (dict, optional) + - `title` (str): Title of the pull request for the proposal. + - `body` (str): Description of the pull request for the proposal. + - `metadata` (dict, optional) + - `cost` (float): Cost incurred for implementing the task. + +### `code.cleanup` + +Removes any downloaded code folder and its archive for the specified task. + +Parameters: + +- `body` (`CodeCleanupParams`) + - `task` (dict) + - `id` (int): The identifier of the task. + +### `CodeFolder` + +Represents a folder containing the downloaded code for a task. It provides some helper methods to build the code proposal. + +Methods: + +- `add(paths: str | list[str])`: Add the specified new file(s) to the code proposal. +- `add_all()`: Add all new files to the code proposal. diff --git a/packages/bot/pyproject.toml b/packages/bot/pyproject.toml index 50ed249..fae1741 100644 --- a/packages/bot/pyproject.toml +++ b/packages/bot/pyproject.toml @@ -3,7 +3,7 @@ name = "automa-bot" version = "0.3.0" authors = [{ name = "Sunkara, Inc.", email = "engineering@automa.app" }] -description = "Bot helpers for Automa" +description = "Bot SDK for Automa" license = "MIT" readme = "README.md" requires-python = ">=3.11"