refactor: implement snippet truncation for task descriptions and comments
This commit is contained in:
@@ -64,6 +64,8 @@ TASK_EVENT_TYPES = {
|
|||||||
"task.comment",
|
"task.comment",
|
||||||
}
|
}
|
||||||
SSE_SEEN_MAX = 2000
|
SSE_SEEN_MAX = 2000
|
||||||
|
TASK_SNIPPET_MAX_LEN = 500
|
||||||
|
TASK_SNIPPET_TRUNCATED_LEN = 497
|
||||||
|
|
||||||
|
|
||||||
def _comment_validation_error() -> HTTPException:
|
def _comment_validation_error() -> HTTPException:
|
||||||
@@ -83,6 +85,13 @@ def _blocked_task_error(blocked_by_task_ids: Sequence[UUID]) -> HTTPException:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _truncate_snippet(value: str) -> str:
|
||||||
|
text = value.strip()
|
||||||
|
if len(text) <= TASK_SNIPPET_MAX_LEN:
|
||||||
|
return text
|
||||||
|
return f"{text[:TASK_SNIPPET_TRUNCATED_LEN]}..."
|
||||||
|
|
||||||
|
|
||||||
async def has_valid_recent_comment(
|
async def has_valid_recent_comment(
|
||||||
session: AsyncSession,
|
session: AsyncSession,
|
||||||
task: Task,
|
task: Task,
|
||||||
@@ -282,9 +291,7 @@ async def _notify_agent_on_task_assign(
|
|||||||
config = await _gateway_config(session, board)
|
config = await _gateway_config(session, board)
|
||||||
if config is None:
|
if config is None:
|
||||||
return
|
return
|
||||||
description = (task.description or "").strip()
|
description = _truncate_snippet(task.description or "")
|
||||||
if len(description) > 500:
|
|
||||||
description = f"{description[:497]}..."
|
|
||||||
details = [
|
details = [
|
||||||
f"Board: {board.name}",
|
f"Board: {board.name}",
|
||||||
f"Task: {task.title}",
|
f"Task: {task.title}",
|
||||||
@@ -340,9 +347,7 @@ async def _notify_lead_on_task_create(
|
|||||||
config = await _gateway_config(session, board)
|
config = await _gateway_config(session, board)
|
||||||
if config is None:
|
if config is None:
|
||||||
return
|
return
|
||||||
description = (task.description or "").strip()
|
description = _truncate_snippet(task.description or "")
|
||||||
if len(description) > 500:
|
|
||||||
description = f"{description[:497]}..."
|
|
||||||
details = [
|
details = [
|
||||||
f"Board: {board.name}",
|
f"Board: {board.name}",
|
||||||
f"Task: {task.title}",
|
f"Task: {task.title}",
|
||||||
@@ -397,9 +402,7 @@ async def _notify_lead_on_task_unassigned(
|
|||||||
config = await _gateway_config(session, board)
|
config = await _gateway_config(session, board)
|
||||||
if config is None:
|
if config is None:
|
||||||
return
|
return
|
||||||
description = (task.description or "").strip()
|
description = _truncate_snippet(task.description or "")
|
||||||
if len(description) > 500:
|
|
||||||
description = f"{description[:497]}..."
|
|
||||||
details = [
|
details = [
|
||||||
f"Board: {board.name}",
|
f"Board: {board.name}",
|
||||||
f"Task: {task.title}",
|
f"Task: {task.title}",
|
||||||
@@ -486,13 +489,11 @@ async def stream_tasks(
|
|||||||
if len(seen_queue) > SSE_SEEN_MAX:
|
if len(seen_queue) > SSE_SEEN_MAX:
|
||||||
oldest = seen_queue.popleft()
|
oldest = seen_queue.popleft()
|
||||||
seen_ids.discard(oldest)
|
seen_ids.discard(oldest)
|
||||||
if event.created_at > last_seen:
|
last_seen = max(event.created_at, last_seen)
|
||||||
last_seen = event.created_at
|
|
||||||
payload: dict[str, object] = {"type": event.event_type}
|
payload: dict[str, object] = {"type": event.event_type}
|
||||||
if event.event_type == "task.comment":
|
if event.event_type == "task.comment":
|
||||||
payload["comment"] = _serialize_comment(event)
|
payload["comment"] = _serialize_comment(event)
|
||||||
else:
|
elif task is None:
|
||||||
if task is None:
|
|
||||||
payload["task"] = None
|
payload["task"] = None
|
||||||
else:
|
else:
|
||||||
dep_list = deps_map.get(task.id, [])
|
dep_list = deps_map.get(task.id, [])
|
||||||
@@ -891,11 +892,8 @@ async def update_task(
|
|||||||
task.updated_at = utcnow()
|
task.updated_at = utcnow()
|
||||||
|
|
||||||
if "status" in updates and updates["status"] == "review":
|
if "status" in updates and updates["status"] == "review":
|
||||||
if comment is not None and comment.strip():
|
comment_text = (comment or "").strip()
|
||||||
if not comment.strip():
|
if not comment_text and not await has_valid_recent_comment(
|
||||||
raise _comment_validation_error()
|
|
||||||
else:
|
|
||||||
if not await has_valid_recent_comment(
|
|
||||||
session,
|
session,
|
||||||
task,
|
task,
|
||||||
task.assigned_agent_id,
|
task.assigned_agent_id,
|
||||||
@@ -1083,9 +1081,7 @@ async def create_task_comment(
|
|||||||
board = await Board.objects.by_id(task.board_id).first(session) if task.board_id else None
|
board = await Board.objects.by_id(task.board_id).first(session) if task.board_id else None
|
||||||
config = await _gateway_config(session, board) if board else None
|
config = await _gateway_config(session, board) if board else None
|
||||||
if board and config:
|
if board and config:
|
||||||
snippet = payload.message.strip()
|
snippet = _truncate_snippet(payload.message)
|
||||||
if len(snippet) > 500:
|
|
||||||
snippet = f"{snippet[:497]}..."
|
|
||||||
actor_name = actor.agent.name if actor.actor_type == "agent" and actor.agent else "User"
|
actor_name = actor.agent.name if actor.actor_type == "agent" and actor.agent else "User"
|
||||||
for agent in targets.values():
|
for agent in targets.values():
|
||||||
if not agent.openclaw_session_id:
|
if not agent.openclaw_session_id:
|
||||||
|
|||||||
Reference in New Issue
Block a user