feat: enhance agent notifications for issue comments and assignments
All checks were successful
Lint and Syntax Check / build (pull_request) Successful in 5s
All checks were successful
Lint and Syntax Check / build (pull_request) Successful in 5s
This commit is contained in:
99
main.py
99
main.py
@@ -11,8 +11,8 @@ DATABASE_STORAGE = os.getenv("DATABASE_STORAGE_NAME")
|
||||
AGENT_USERNAME = os.getenv("AGENT_USERNAME")
|
||||
AGENT_PROMPT_FILE = os.getenv("AGENT_PROMPT_FILE")
|
||||
|
||||
eventsToHandle = ["pull_request", "issues"]
|
||||
actionsToHandle = ["assigned", "unassigned"]
|
||||
eventsToHandle = ["pull_request", "issues", "issue_comment"]
|
||||
actionsToHandle = ["assigned", "created"]
|
||||
|
||||
# Template Fields:
|
||||
DEFAULT_PROMPT_TEMPLATE = """# GITEA STATUS UPDATE
|
||||
@@ -31,7 +31,7 @@ The Goal is to solve this issue or PR as quickly and with as little back and for
|
||||
|
||||
|
||||
def get_assignee_key(event_type, repository_id, number):
|
||||
if event_type == "issues" or event_type == "issue":
|
||||
if event_type == "issues" or event_type == "issue" or event_type == "issue_comment":
|
||||
return f"assignees_issue_{repository_id}_{number}"
|
||||
elif event_type == "pull_request":
|
||||
return f"assignees_pr_{repository_id}_{number}"
|
||||
@@ -89,6 +89,11 @@ def fill_template(template, event_object, action_str, type_str):
|
||||
|
||||
|
||||
def build_message(event_object, action_str, type_str):
|
||||
if type_str == "comment":
|
||||
action_summary = f"There is a new comment on a {event_object['target_type']} you are assigned to in {event_object['repository']} by {event_object['sender']}."
|
||||
else:
|
||||
action_summary = f"You were {action_str} to an {type_str} in {event_object['repository']} by {event_object['sender']}."
|
||||
|
||||
if AGENT_PROMPT_FILE:
|
||||
AGENT_PROMPT_FILE_PATH = "/app/" + AGENT_PROMPT_FILE
|
||||
|
||||
@@ -98,32 +103,45 @@ def build_message(event_object, action_str, type_str):
|
||||
f"Custom prompt file not found at {AGENT_PROMPT_FILE_PATH}. Using default message."
|
||||
)
|
||||
message = fill_template(DEFAULT_PROMPT_TEMPLATE, event_object, action_str, type_str)
|
||||
message = message.replace("You were [action_str] to an [type_str]", action_summary)
|
||||
return message
|
||||
|
||||
with open(AGENT_PROMPT_FILE_PATH, "r") as f:
|
||||
custom_prompt = f.read()
|
||||
message = fill_template(custom_prompt, event_object, action_str, type_str)
|
||||
message = message.replace("You were [action_str] to an [type_str]", action_summary)
|
||||
return message
|
||||
else:
|
||||
print("No custom prompt file specified. Using default message.")
|
||||
message = fill_template(DEFAULT_PROMPT_TEMPLATE, event_object, action_str, type_str)
|
||||
message = message.replace("You were [action_str] to an [type_str]", action_summary)
|
||||
return message
|
||||
|
||||
|
||||
def sendToAgent(event_object):
|
||||
headers = {"x-openclaw-token": OPENCLAW_TOKEN, "Content-Type": "application/json"}
|
||||
action_str = "assigned" if event_object["action"] == "assigned" else "unassigned"
|
||||
type_str = "issue" if event_object["type"] == "issue" else "pull request"
|
||||
|
||||
assignees = event_object.get("assignees", [event_object.get("assignee", "Unknown")])
|
||||
|
||||
if AGENT_USERNAME in assignees:
|
||||
message = build_message(event_object, action_str, type_str)
|
||||
if event_object.get("type") == "issue_comment":
|
||||
action_str = "created"
|
||||
type_str = "comment"
|
||||
mention = f"@{AGENT_USERNAME}".lower()
|
||||
comment_body = event_object.get("comment_body", "").lower()
|
||||
if mention not in comment_body:
|
||||
print(
|
||||
f"Agent {AGENT_USERNAME} was not mentioned in comment body. Skipping notification."
|
||||
)
|
||||
return
|
||||
else:
|
||||
print(
|
||||
f"Agent {AGENT_USERNAME} is not among the assignees for this event. Skipping notification."
|
||||
)
|
||||
return
|
||||
action_str = "assigned"
|
||||
type_str = "issue" if event_object["type"] == "issue" else "pull request"
|
||||
assignees = event_object.get("assignees", [event_object.get("assignee", "Unknown")])
|
||||
if AGENT_USERNAME not in assignees:
|
||||
print(
|
||||
f"Agent {AGENT_USERNAME} is not among the assignees for this event. Skipping notification."
|
||||
)
|
||||
return
|
||||
|
||||
message = build_message(event_object, action_str, type_str)
|
||||
|
||||
try:
|
||||
if OPENCLAW_PROXY_AUTH:
|
||||
@@ -239,7 +257,7 @@ def main(args):
|
||||
"_headers": {"Content-Type": "application/json"},
|
||||
}
|
||||
|
||||
if action in ["assigned", "unassigned"]:
|
||||
if action == "assigned" and event_type in ["issues", "pull_request"]:
|
||||
assignee_data = data.get("assignee")
|
||||
assignees_data = data.get("assignees")
|
||||
|
||||
@@ -315,28 +333,12 @@ def main(args):
|
||||
}
|
||||
|
||||
if event_object:
|
||||
# Use helpers to store/delete assignees
|
||||
# Store assignees for later comment events.
|
||||
if action == "assigned":
|
||||
set_stored_assignees(
|
||||
db, event_type, repo_id, event_object["number"], assignees_list
|
||||
)
|
||||
|
||||
if action == "unassigned":
|
||||
# If the payload STILL has assignees, it means someone is still assigned
|
||||
# If it's empty (or only contains "Unknown"), delete it.
|
||||
if not assignees_data or len(assignees_data) == 0:
|
||||
delete_stored_assignees(
|
||||
db, event_type, repo_id, event_object["number"]
|
||||
)
|
||||
else:
|
||||
set_stored_assignees(
|
||||
db,
|
||||
event_type,
|
||||
repo_id,
|
||||
event_object["number"],
|
||||
assignees_list,
|
||||
)
|
||||
|
||||
print(f"--- {event_object['type'].upper()} {action.capitalize()} ---")
|
||||
print(f"Title: {event_object['title']}")
|
||||
print(f"Assignees: {', '.join(event_object['assignees'])}")
|
||||
@@ -344,8 +346,39 @@ def main(args):
|
||||
print(f"By: {event_object['sender']}")
|
||||
|
||||
# Send to OpenClaw
|
||||
# sendToAgent(event_object)
|
||||
print("Not sending event to agent, unassinging is too noisy for now, will only send assigned events")
|
||||
if action == "assigned":
|
||||
sendToAgent(event_object)
|
||||
else:
|
||||
print(f"Action {action} is not configured to send to agent")
|
||||
|
||||
elif action == "created" and event_type == "issue_comment":
|
||||
comment_data = data.get("comment", {})
|
||||
is_pull = data.get("is_pull", False)
|
||||
target_data = data.get("issue") or data.get("pull_request") or {}
|
||||
|
||||
repository = data.get("repository", {}).get("full_name", "Unknown")
|
||||
repo_id = data.get("repository", {}).get("id")
|
||||
sender = data.get("sender", {}).get("login", "Unknown")
|
||||
issue_number = target_data.get("number")
|
||||
|
||||
event_object = {
|
||||
"type": "issue_comment",
|
||||
"target_type": "pull_request" if is_pull else "issue",
|
||||
"action": action,
|
||||
"repository": repository,
|
||||
"number": issue_number,
|
||||
"title": target_data.get("title", "Unknown"),
|
||||
"sender": sender,
|
||||
"comment_body": comment_data.get("body", ""),
|
||||
"url": comment_data.get("html_url"),
|
||||
}
|
||||
|
||||
print(f"--- {event_object['type'].upper()} {action.capitalize()} ---")
|
||||
print(f"Title: {event_object['title']}")
|
||||
print(f"Repo: {event_object['repository']}")
|
||||
print(f"By: {event_object['sender']}")
|
||||
|
||||
sendToAgent(event_object)
|
||||
|
||||
return {
|
||||
"_shsf": "v2",
|
||||
|
||||
Reference in New Issue
Block a user