Skip to content

Commit

Permalink
Merge pull request #1 from cel-ai/feat-inbox-bot-auto-assign
Browse files Browse the repository at this point in the history
feat: support inbox bot auto assign on start
  • Loading branch information
alejamp authored Oct 26, 2024
2 parents e498f0f + e904baa commit 0922be7
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 34 deletions.
6 changes: 6 additions & 0 deletions .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[bumpversion]
current_version = 0.1.5
commit = True
tag = True

[bumpversion:file:pyproject.toml]
34 changes: 34 additions & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ on:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
types: [closed] # Run after PR is merged

jobs:
build:
if: ${{ github.event.pull_request.merged == true }}
runs-on: ubuntu-latest
environment: release
permissions:
Expand All @@ -30,23 +32,55 @@ jobs:
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
pip install poetry
poetry install --with dev
- name: Set up Git credentials for pushing
run: git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Configure Git user
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "GitHub Actions"
- name: Auto-increment version
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "GitHub Actions"
bump2version patch --allow-dirty
poetry lock --no-update
cat pyproject.toml | grep version
- name: Commit and Push changes
run: |
git add pyproject.toml
git add poetry.lock
git commit -m "Increment version [skip ci]" || echo "No changes to commit"
git push origin main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
poetry run pytest
- name: Build package
run: |
poetry build
Expand Down
44 changes: 44 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Tests

on:
push:
branches: [ "main", "dev" ]
pull_request:
branches: [ "main", "dev" ]

jobs:
build:
runs-on: ubuntu-latest
environment: release
permissions:
# IMPORTANT: this permission is mandatory for trusted publishing
id-token: write

strategy:
fail-fast: false
matrix:
python-version: ["3.11"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
pip install poetry
poetry install --with dev
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
poetry run pytest
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
/celai_chatwoot/telegram
woot_test.py
/.vscode
__pycache__
__pycache__
DEV.md
36 changes: 29 additions & 7 deletions celai_chatwoot/connector/bot_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,26 @@ async def upsert_bot(self,

if bot:
bot_id = bot["id"]
log.debug(f"Bot {name} id:{bot_id} found. Updating bot with webhook url {outgoing_url}")
log.debug(f"Bot '{name}' id:{bot_id} found. Updating bot with webhook url {outgoing_url}")
return await self.update_agent_bot(bot_id, name, description, outgoing_url)

log.warning(f"Bot {name} not found. Creating bot with webhook url {outgoing_url}")
log.warning(f"Bot '{name}' not found. Creating bot with webhook url {outgoing_url}")
return await self.create_agent_bot(name, description, outgoing_url)


# add bot to inbox https://app.chatwoot.com/api/v1/accounts/{account_id}/inboxes/{id}/set_agent_bot
async def assign_bot_to_inbox(self, inbox_id: str | int, agent_bot_id: str | int) -> Dict[str, Any]:
url = f"{self.base_url}/api/v1/accounts/{self.account_id}/inboxes/{inbox_id}/set_agent_bot"
log.debug(f"Adding bot to inbox at Chatwoot url: {url}")

payload = {
'agent_bot': agent_bot_id
}

async with aiohttp.ClientSession() as session:
async with session.post(url, json=payload, headers=self.headers) as response:
response_data = await response.json()
return response_data



Expand Down Expand Up @@ -148,13 +162,21 @@ async def main():
# find bot by name
log.debug(f"Bot found: {bot}")

bot_id = bot["id"]

# list bots
bots = await client.list_agent_bots()
log.debug(f"Bots: {bots}")






for b in bots:
# show id, name, description
log.debug(f"Bot: {b['id']} {b['name']} {b['description']}")

# assign bot to inbox
inbox_id = 1
bot_id = 1
await client.assign_bot_to_inbox(inbox_id, bot_id)

print("Done!")

asyncio.run(main())
51 changes: 29 additions & 22 deletions celai_chatwoot/connector/woo_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def __init__(self,
account_id: str,
access_key: str,
chatwoot_url: str,
inbox_id: str,
bot_description: str = "Celai Bot",
stream_mode: StreamMode = StreamMode.SENTENCE):
log.debug("Creating Chatwoot connector")
Expand All @@ -48,8 +49,9 @@ def __init__(self,
self.bot_name = bot_name
self.account_id = account_id
self.access_key = access_key
self.inbox_id = inbox_id
self.chatwoot_url = chatwoot_url
self.bot_description = bot_description
self.bot_description = bot_description or "Celai generated Bot"


def __create_routes(self, router: APIRouter):
Expand Down Expand Up @@ -243,30 +245,35 @@ def startup(self, context: MessageGatewayContext):
# verify if the webhook_url is set and is HTTPS
assert context.webhook_url, "webhook_url must be set in the context"
assert context.webhook_url.startswith("https"),\
f"webhook_url must be HTTPS, got: {context.webhook_url}.\
Be sure that your url is public and has a valid SSL certificate."
(f"webhook_url must be HTTPS, got: {context.webhook_url}"
"Be sure that your url is public and has a valid SSL certificate.")

async def update_bot():

try:
base_url = f"{context.webhook_url}"
webhook_url = urljoin(base_url, f"{self.router.prefix}/webhook/{self.security_token}")

log.debug(f"Updating Chatwoot Bot webhook url to: {webhook_url}")

base_url = f"{context.webhook_url}"
webhook_url = urljoin(base_url, f"{self.router.prefix}/webhook/{self.security_token}")

# webhook_url = f"{context.webhook_url}/{self.router.prefix}/webhook/{self.security_token}"
log.debug(f"Updating Chatwoot Bot webhook url to: {webhook_url}")
# TODO: update chatwoot webhook url by bot name
client = ChatwootAgentsBots(
base_url=self.chatwoot_url,
account_id=self.account_id,
access_key=self.access_key
)

res = await client.upsert_bot(name=self.bot_name,
outgoing_url=webhook_url,
description=self.bot_description)

log.debug(f"Chatwoot Bot updated: {res}")

client = ChatwootAgentsBots(
base_url=self.chatwoot_url,
account_id=self.account_id,
access_key=self.access_key
)

bot = await client.upsert_bot(name=self.bot_name,
outgoing_url=webhook_url,
description=self.bot_description)

bot_id = bot["id"]
log.debug(f"Chatwoot Bot '{self.bot_name}' id:{bot_id} updated. Adding bot to inbox {self.inbox_id}")
await client.assign_bot_to_inbox(inbox_id=self.inbox_id, agent_bot_id=bot_id)
log.debug(f"Chatwoot Bot '{self.bot_name}' assigned to inbox {self.inbox_id}")

except Exception as e:
log.error(f"Error updating Chatwoot bot: {e}")
log.exception(e)
raise e
try:
loop = asyncio.get_running_loop()
loop.create_task(update_bot())
Expand Down
9 changes: 5 additions & 4 deletions examples/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from cel.gateway.message_gateway import MessageGateway, StreamMode
from cel.assistants.macaw.macaw_assistant import MacawAssistant
from cel.prompt.prompt_template import PromptTemplate
from cel.gateway.request_context import RequestContext
from cel.assistants.request_context import RequestContext


# Setup prompt
Expand All @@ -39,28 +39,28 @@
@ast.event('message')
async def handle_message(session, ctx: RequestContext):
log.critical(f"Got message event with message!")
assert isinstance(ctx.connector, WootConnector)

if ctx.message.text == "img":
await ctx.connector.send_image_message(
ctx.lead,
"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png",
"This is an image"
)
return RequestContext.cancel_response()
return RequestContext.cancel_ai_response()

if ctx.message.text == "audio":
await ctx.connector.send_audio_message(
ctx.lead,
"https://www.w3schools.com/html/horse.mp3"
)
return RequestContext.cancel_response()
return RequestContext.cancel_ai_response()



# Create the Message Gateway - This component is the core of the assistant
# It handles the communication between the assistant and the connectors
gateway = MessageGateway(
webhook_url=os.environ.get("WEBHOOK_URL"),
assistant=ast,
host="127.0.0.1", port=8000
)
Expand All @@ -70,6 +70,7 @@ async def handle_message(session, ctx: RequestContext):
bot_name="Testing Ale Bot",
access_key=os.environ.get("CHATWOOT_ACCESS_KEY"),
account_id=os.environ.get("CHATWOOT_ACCOUNT_ID"),
inbox_id=os.environ.get("CHATWOOT_INBOX_ID"),
chatwoot_url=os.environ.get("CHATWOOT_URL"),
bot_description="This is a test bot",
stream_mode=StreamMode.FULL
Expand Down

0 comments on commit 0922be7

Please sign in to comment.