feat: refactor imports and clean up code formatting across multiple files

This commit is contained in:
Abhimanyu Saharan
2026-02-06 02:43:08 +05:30
parent 2d60de0900
commit f258b756e8
13 changed files with 75 additions and 138 deletions

View File

@@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
from uuid import UUID
import asyncio import asyncio
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, status from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlmodel import Session, select from sqlmodel import Session, select
@@ -14,28 +14,18 @@ from app.api import tasks as tasks_api
from app.api.deps import ActorContext, get_board_or_404, get_task_or_404 from app.api.deps import ActorContext, get_board_or_404, get_task_or_404
from app.core.agent_auth import AgentAuthContext, get_agent_auth_context from app.core.agent_auth import AgentAuthContext, get_agent_auth_context
from app.db.session import get_session from app.db.session import get_session
from app.integrations.openclaw_gateway import ( from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
GatewayConfig as GatewayClientConfig, from app.integrations.openclaw_gateway import OpenClawGatewayError, ensure_session, send_message
OpenClawGatewayError,
ensure_session,
send_message,
)
from app.models.agents import Agent from app.models.agents import Agent
from app.models.tasks import Task
from app.models.boards import Board from app.models.boards import Board
from app.models.gateways import Gateway from app.models.gateways import Gateway
from app.models.tasks import Task
from app.schemas.agents import AgentCreate, AgentHeartbeatCreate, AgentNudge, AgentRead
from app.schemas.approvals import ApprovalCreate, ApprovalRead from app.schemas.approvals import ApprovalCreate, ApprovalRead
from app.schemas.board_memory import BoardMemoryCreate, BoardMemoryRead from app.schemas.board_memory import BoardMemoryCreate, BoardMemoryRead
from app.schemas.board_onboarding import BoardOnboardingRead from app.schemas.board_onboarding import BoardOnboardingRead
from app.schemas.boards import BoardRead from app.schemas.boards import BoardRead
from app.schemas.tasks import ( from app.schemas.tasks import TaskCommentCreate, TaskCommentRead, TaskCreate, TaskRead, TaskUpdate
TaskCommentCreate,
TaskCommentRead,
TaskCreate,
TaskRead,
TaskUpdate,
)
from app.schemas.agents import AgentCreate, AgentHeartbeatCreate, AgentNudge, AgentRead
from app.services.activity_log import record_activity from app.services.activity_log import record_activity
router = APIRouter(prefix="/agent", tags=["agent"]) router = APIRouter(prefix="/agent", tags=["agent"])
@@ -98,9 +88,7 @@ def list_agents(
agents = list(session.exec(statement)) agents = list(session.exec(statement))
main_session_keys = agents_api._get_gateway_main_session_keys(session) main_session_keys = agents_api._get_gateway_main_session_keys(session)
return [ return [
agents_api._to_agent_read( agents_api._to_agent_read(agents_api._with_computed_status(agent), main_session_keys)
agents_api._with_computed_status(agent), main_session_keys
)
for agent in agents for agent in agents
] ]
@@ -351,6 +339,7 @@ def nudge_agent(
detail="message is required", detail="message is required",
) )
config = _gateway_config(session, board) config = _gateway_config(session, board)
async def _send() -> None: async def _send() -> None:
await ensure_session(target.openclaw_session_id, config=config, label=target.name) await ensure_session(target.openclaw_session_id, config=config, label=target.name)
await send_message( await send_message(

View File

@@ -1,9 +1,9 @@
from __future__ import annotations from __future__ import annotations
import re
from datetime import datetime, timedelta, timezone
import asyncio import asyncio
import json import json
import re
from datetime import datetime, timedelta, timezone
from uuid import UUID, uuid4 from uuid import UUID, uuid4
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
@@ -23,7 +23,13 @@ from app.models.agents import Agent
from app.models.boards import Board from app.models.boards import Board
from app.models.gateways import Gateway from app.models.gateways import Gateway
from app.models.tasks import Task from app.models.tasks import Task
from app.schemas.agents import AgentCreate, AgentHeartbeat, AgentHeartbeatCreate, AgentRead, AgentUpdate from app.schemas.agents import (
AgentCreate,
AgentHeartbeat,
AgentHeartbeatCreate,
AgentRead,
AgentUpdate,
)
from app.services.activity_log import record_activity from app.services.activity_log import record_activity
from app.services.agent_provisioning import ( from app.services.agent_provisioning import (
DEFAULT_HEARTBEAT_CONFIG, DEFAULT_HEARTBEAT_CONFIG,
@@ -159,14 +165,10 @@ def _to_agent_read(agent: Agent, main_session_keys: set[str]) -> AgentRead:
return model.model_copy(update={"is_gateway_main": _is_gateway_main(agent, main_session_keys)}) return model.model_copy(update={"is_gateway_main": _is_gateway_main(agent, main_session_keys)})
def _find_gateway_for_main_session( def _find_gateway_for_main_session(session: Session, session_key: str | None) -> Gateway | None:
session: Session, session_key: str | None
) -> Gateway | None:
if not session_key: if not session_key:
return None return None
return session.exec( return session.exec(select(Gateway).where(Gateway.main_session_key == session_key)).first()
select(Gateway).where(Gateway.main_session_key == session_key)
).first()
async def _ensure_gateway_session( async def _ensure_gateway_session(
@@ -193,9 +195,7 @@ def _with_computed_status(agent: Agent) -> Agent:
def _serialize_agent(agent: Agent, main_session_keys: set[str]) -> dict[str, object]: def _serialize_agent(agent: Agent, main_session_keys: set[str]) -> dict[str, object]:
return _to_agent_read( return _to_agent_read(_with_computed_status(agent), main_session_keys).model_dump(mode="json")
_with_computed_status(agent), main_session_keys
).model_dump(mode="json")
def _fetch_agent_events( def _fetch_agent_events(
@@ -206,15 +206,12 @@ def _fetch_agent_events(
statement = select(Agent) statement = select(Agent)
if board_id: if board_id:
statement = statement.where(col(Agent.board_id) == board_id) statement = statement.where(col(Agent.board_id) == board_id)
statement = ( statement = statement.where(
statement.where( or_(
or_( col(Agent.updated_at) >= since,
col(Agent.updated_at) >= since, col(Agent.last_seen_at) >= since,
col(Agent.last_seen_at) >= since,
)
) )
.order_by(asc(col(Agent.updated_at))) ).order_by(asc(col(Agent.updated_at)))
)
return list(session.exec(statement)) return list(session.exec(statement))
@@ -257,10 +254,7 @@ def list_agents(
) -> list[Agent]: ) -> list[Agent]:
agents = list(session.exec(select(Agent))) agents = list(session.exec(select(Agent)))
main_session_keys = _get_gateway_main_session_keys(session) main_session_keys = _get_gateway_main_session_keys(session)
return [ return [_to_agent_read(_with_computed_status(agent), main_session_keys) for agent in agents]
_to_agent_read(_with_computed_status(agent), main_session_keys)
for agent in agents
]
@router.get("/stream") @router.get("/stream")
@@ -336,9 +330,7 @@ async def create_agent(
data["identity_template"] = None data["identity_template"] = None
if data.get("soul_template") == "": if data.get("soul_template") == "":
data["soul_template"] = None data["soul_template"] = None
data["identity_profile"] = _normalize_identity_profile( data["identity_profile"] = _normalize_identity_profile(data.get("identity_profile"))
data.get("identity_profile")
)
agent = Agent.model_validate(data) agent = Agent.model_validate(data)
agent.status = "provisioning" agent.status = "provisioning"
raw_token = generate_agent_token() raw_token = generate_agent_token()
@@ -441,9 +433,7 @@ async def update_agent(
if updates.get("soul_template") == "": if updates.get("soul_template") == "":
updates["soul_template"] = None updates["soul_template"] = None
if "identity_profile" in updates: if "identity_profile" in updates:
updates["identity_profile"] = _normalize_identity_profile( updates["identity_profile"] = _normalize_identity_profile(updates.get("identity_profile"))
updates.get("identity_profile")
)
if not updates and not force and make_main is None: if not updates and not force and make_main is None:
main_session_keys = _get_gateway_main_session_keys(session) main_session_keys = _get_gateway_main_session_keys(session)
return _to_agent_read(_with_computed_status(agent), main_session_keys) return _to_agent_read(_with_computed_status(agent), main_session_keys)
@@ -823,9 +813,7 @@ def delete_agent(
) )
) )
session.execute( session.execute(
update(ActivityEvent) update(ActivityEvent).where(col(ActivityEvent.agent_id) == agent.id).values(agent_id=None)
.where(col(ActivityEvent.agent_id) == agent.id)
.values(agent_id=None)
) )
session.delete(agent) session.delete(agent)
session.commit() session.commit()

View File

@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime, timezone
import asyncio import asyncio
import json import json
from datetime import datetime, timezone
from uuid import UUID from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
@@ -42,9 +42,7 @@ def _approval_updated_at(approval: Approval) -> datetime:
def _serialize_approval(approval: Approval) -> dict[str, object]: def _serialize_approval(approval: Approval) -> dict[str, object]:
return ApprovalRead.model_validate( return ApprovalRead.model_validate(approval, from_attributes=True).model_dump(mode="json")
approval, from_attributes=True
).model_dump(mode="json")
def _fetch_approval_events( def _fetch_approval_events(
@@ -103,9 +101,7 @@ async def stream_approvals(
while True: while True:
if await request.is_disconnected(): if await request.is_disconnected():
break break
approvals = await run_in_threadpool( approvals = await run_in_threadpool(_fetch_approval_events, board.id, last_seen)
_fetch_approval_events, board.id, last_seen
)
for approval in approvals: for approval in approvals:
updated_at = _approval_updated_at(approval) updated_at = _approval_updated_at(approval)
if updated_at > last_seen: if updated_at > last_seen:

View File

@@ -1,9 +1,9 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime, timezone
import asyncio import asyncio
import json import json
import re import re
from datetime import datetime, timezone
from fastapi import APIRouter, Depends, HTTPException, Query, Request from fastapi import APIRouter, Depends, HTTPException, Query, Request
from sqlmodel import Session, col, select from sqlmodel import Session, col, select
@@ -13,12 +13,8 @@ from starlette.concurrency import run_in_threadpool
from app.api.deps import ActorContext, get_board_or_404, require_admin_or_agent from app.api.deps import ActorContext, get_board_or_404, require_admin_or_agent
from app.core.config import settings from app.core.config import settings
from app.db.session import engine, get_session from app.db.session import engine, get_session
from app.integrations.openclaw_gateway import ( from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
GatewayConfig as GatewayClientConfig, from app.integrations.openclaw_gateway import OpenClawGatewayError, ensure_session, send_message
OpenClawGatewayError,
ensure_session,
send_message,
)
from app.models.agents import Agent from app.models.agents import Agent
from app.models.board_memory import BoardMemory from app.models.board_memory import BoardMemory
from app.models.gateways import Gateway from app.models.gateways import Gateway
@@ -46,9 +42,7 @@ def _parse_since(value: str | None) -> datetime | None:
def _serialize_memory(memory: BoardMemory) -> dict[str, object]: def _serialize_memory(memory: BoardMemory) -> dict[str, object]:
return BoardMemoryRead.model_validate( return BoardMemoryRead.model_validate(memory, from_attributes=True).model_dump(mode="json")
memory, from_attributes=True
).model_dump(mode="json")
def _extract_mentions(message: str) -> set[str]: def _extract_mentions(message: str) -> set[str]:
@@ -162,6 +156,7 @@ def _notify_chat_targets(
except OpenClawGatewayError: except OpenClawGatewayError:
continue continue
@router.get("", response_model=list[BoardMemoryRead]) @router.get("", response_model=list[BoardMemoryRead])
def list_board_memory( def list_board_memory(
limit: int = Query(default=50, ge=1, le=200), limit: int = Query(default=50, ge=1, le=200),
@@ -201,9 +196,7 @@ async def stream_board_memory(
while True: while True:
if await request.is_disconnected(): if await request.is_disconnected():
break break
memories = await run_in_threadpool( memories = await run_in_threadpool(_fetch_memory_events, board.id, last_seen)
_fetch_memory_events, board.id, last_seen
)
for memory in memories: for memory in memories:
if memory.created_at > last_seen: if memory.created_at > last_seen:
last_seen = memory.created_at last_seen = memory.created_at

View File

@@ -1,12 +1,12 @@
from __future__ import annotations from __future__ import annotations
import json import json
import logging
import re import re
from datetime import datetime from datetime import datetime
from uuid import uuid4 from uuid import uuid4
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
import logging
from sqlmodel import Session, select from sqlmodel import Session, select
from app.api.deps import ActorContext, get_board_or_404, require_admin_auth, require_admin_or_agent from app.api.deps import ActorContext, get_board_or_404, require_admin_auth, require_admin_or_agent
@@ -33,7 +33,6 @@ router = APIRouter(prefix="/boards/{board_id}/onboarding", tags=["board-onboardi
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def _gateway_config(session: Session, board: Board) -> tuple[Gateway, GatewayClientConfig]: def _gateway_config(session: Session, board: Board) -> tuple[Gateway, GatewayClientConfig]:
if not board.gateway_id: if not board.gateway_id:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY) raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
@@ -64,9 +63,7 @@ async def _ensure_lead_agent(
auth: AuthContext, auth: AuthContext,
) -> Agent: ) -> Agent:
existing = session.exec( existing = session.exec(
select(Agent) select(Agent).where(Agent.board_id == board.id).where(Agent.is_board_lead.is_(True))
.where(Agent.board_id == board.id)
.where(Agent.is_board_lead.is_(True))
).first() ).first()
if existing: if existing:
if existing.name != _lead_agent_name(board): if existing.name != _lead_agent_name(board):
@@ -161,21 +158,21 @@ async def start_onboarding(
"Onboarding response endpoint:\n" "Onboarding response endpoint:\n"
f"POST {base_url}/api/v1/agent/boards/{board.id}/onboarding\n" f"POST {base_url}/api/v1/agent/boards/{board.id}/onboarding\n"
"QUESTION example (send JSON body exactly as shown):\n" "QUESTION example (send JSON body exactly as shown):\n"
f"curl -s -X POST \"{base_url}/api/v1/agent/boards/{board.id}/onboarding\" " f'curl -s -X POST "{base_url}/api/v1/agent/boards/{board.id}/onboarding" '
"-H \"X-Agent-Token: $AUTH_TOKEN\" " '-H "X-Agent-Token: $AUTH_TOKEN" '
"-H \"Content-Type: application/json\" " '-H "Content-Type: application/json" '
"-d '{\"question\":\"...\",\"options\":[{\"id\":\"1\",\"label\":\"...\"},{\"id\":\"2\",\"label\":\"...\"}]}'\n" '-d \'{"question":"...","options":[{"id":"1","label":"..."},{"id":"2","label":"..."}]}\'\n'
"COMPLETION example (send JSON body exactly as shown):\n" "COMPLETION example (send JSON body exactly as shown):\n"
f"curl -s -X POST \"{base_url}/api/v1/agent/boards/{board.id}/onboarding\" " f'curl -s -X POST "{base_url}/api/v1/agent/boards/{board.id}/onboarding" '
"-H \"X-Agent-Token: $AUTH_TOKEN\" " '-H "X-Agent-Token: $AUTH_TOKEN" '
"-H \"Content-Type: application/json\" " '-H "Content-Type: application/json" '
"-d '{\"status\":\"complete\",\"board_type\":\"goal\",\"objective\":\"...\",\"success_metrics\":{...},\"target_date\":\"YYYY-MM-DD\"}'\n" '-d \'{"status":"complete","board_type":"goal","objective":"...","success_metrics":{...},"target_date":"YYYY-MM-DD"}\'\n'
"QUESTION FORMAT (one question per response, no arrays, no markdown, no extra text):\n" "QUESTION FORMAT (one question per response, no arrays, no markdown, no extra text):\n"
"{\"question\":\"...\",\"options\":[{\"id\":\"1\",\"label\":\"...\"},{\"id\":\"2\",\"label\":\"...\"}]}\n" '{"question":"...","options":[{"id":"1","label":"..."},{"id":"2","label":"..."}]}\n'
"Do NOT wrap questions in a list. Do NOT add commentary.\n" "Do NOT wrap questions in a list. Do NOT add commentary.\n"
"When you have enough info, return JSON ONLY (via API):\n" "When you have enough info, return JSON ONLY (via API):\n"
"{\"status\":\"complete\",\"board_type\":\"goal\"|\"general\",\"objective\":\"...\"," '{"status":"complete","board_type":"goal"|"general","objective":"...",'
"\"success_metrics\":{...},\"target_date\":\"YYYY-MM-DD\"}." '"success_metrics":{...},"target_date":"YYYY-MM-DD"}.'
) )
try: try:

View File

@@ -214,9 +214,7 @@ def delete_board(
session.execute(delete(Approval).where(col(Approval.board_id) == board.id)) session.execute(delete(Approval).where(col(Approval.board_id) == board.id))
session.execute(delete(BoardMemory).where(col(BoardMemory.board_id) == board.id)) session.execute(delete(BoardMemory).where(col(BoardMemory.board_id) == board.id))
session.execute( session.execute(
delete(BoardOnboardingSession).where( delete(BoardOnboardingSession).where(col(BoardOnboardingSession.board_id) == board.id)
col(BoardOnboardingSession.board_id) == board.id
)
) )
session.execute(delete(Task).where(col(Task.board_id) == board.id)) session.execute(delete(Task).where(col(Task.board_id) == board.id))
session.delete(board) session.delete(board)

View File

@@ -1,12 +1,11 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime
from uuid import UUID from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from sqlmodel import Session, select from sqlmodel import Session, select
from datetime import datetime
from app.core.agent_tokens import generate_agent_token, hash_agent_token from app.core.agent_tokens import generate_agent_token, hash_agent_token
from app.core.auth import AuthContext, get_auth_context from app.core.auth import AuthContext, get_auth_context
from app.db.session import get_session from app.db.session import get_session
@@ -306,7 +305,9 @@ async def _ensure_main_agent(
try: try:
await provision_main_agent(agent, gateway, raw_token, auth.user, action=action) await provision_main_agent(agent, gateway, raw_token, auth.user, action=action)
await ensure_session( await ensure_session(
gateway.main_session_key, config=GatewayClientConfig(url=gateway.url, token=gateway.token), label=agent.name gateway.main_session_key,
config=GatewayClientConfig(url=gateway.url, token=gateway.token),
label=agent.name,
) )
await send_message( await send_message(
( (

View File

@@ -1,17 +1,17 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime, timezone
import asyncio import asyncio
import json import json
import re import re
from collections import deque from collections import deque
from datetime import datetime, timezone
from uuid import UUID from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
from sqlalchemy import asc, delete, desc
from sqlmodel import Session, col, select
from sse_starlette.sse import EventSourceResponse from sse_starlette.sse import EventSourceResponse
from starlette.concurrency import run_in_threadpool from starlette.concurrency import run_in_threadpool
from sqlalchemy import asc, desc, delete
from sqlmodel import Session, col, select
from app.api.deps import ( from app.api.deps import (
ActorContext, ActorContext,
@@ -22,18 +22,14 @@ from app.api.deps import (
) )
from app.core.auth import AuthContext from app.core.auth import AuthContext
from app.db.session import engine, get_session from app.db.session import engine, get_session
from app.integrations.openclaw_gateway import ( from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
GatewayConfig as GatewayClientConfig, from app.integrations.openclaw_gateway import OpenClawGatewayError, ensure_session, send_message
OpenClawGatewayError,
ensure_session,
send_message,
)
from app.models.activity_events import ActivityEvent from app.models.activity_events import ActivityEvent
from app.models.agents import Agent from app.models.agents import Agent
from app.models.boards import Board from app.models.boards import Board
from app.models.gateways import Gateway from app.models.gateways import Gateway
from app.models.tasks import Task
from app.models.task_fingerprints import TaskFingerprint from app.models.task_fingerprints import TaskFingerprint
from app.models.tasks import Task
from app.schemas.tasks import TaskCommentCreate, TaskCommentRead, TaskCreate, TaskRead, TaskUpdate from app.schemas.tasks import TaskCommentCreate, TaskCommentRead, TaskCreate, TaskRead, TaskUpdate
from app.services.activity_log import record_activity from app.services.activity_log import record_activity
@@ -151,9 +147,7 @@ def _fetch_task_events(
since: datetime, since: datetime,
) -> list[tuple[ActivityEvent, Task | None]]: ) -> list[tuple[ActivityEvent, Task | None]]:
with Session(engine) as session: with Session(engine) as session:
task_ids = list( task_ids = list(session.exec(select(Task.id).where(col(Task.board_id) == board_id)))
session.exec(select(Task.id).where(col(Task.board_id) == board_id))
)
if not task_ids: if not task_ids:
return [] return []
statement = ( statement = (
@@ -270,9 +264,7 @@ def _notify_lead_on_task_create(
task: Task, task: Task,
) -> None: ) -> None:
lead = session.exec( lead = session.exec(
select(Agent) select(Agent).where(Agent.board_id == board.id).where(Agent.is_board_lead.is_(True))
.where(Agent.board_id == board.id)
.where(Agent.is_board_lead.is_(True))
).first() ).first()
if lead is None or not lead.openclaw_session_id: if lead is None or not lead.openclaw_session_id:
return return
@@ -329,9 +321,7 @@ def _notify_lead_on_task_unassigned(
task: Task, task: Task,
) -> None: ) -> None:
lead = session.exec( lead = session.exec(
select(Agent) select(Agent).where(Agent.board_id == board.id).where(Agent.is_board_lead.is_(True))
.where(Agent.board_id == board.id)
.where(Agent.is_board_lead.is_(True))
).first() ).first()
if lead is None or not lead.openclaw_session_id: if lead is None or not lead.openclaw_session_id:
return return
@@ -639,11 +629,7 @@ def update_task(
task=task, task=task,
) )
if task.assigned_agent_id and task.assigned_agent_id != previous_assigned: if task.assigned_agent_id and task.assigned_agent_id != previous_assigned:
if ( if actor.actor_type == "agent" and actor.agent and task.assigned_agent_id == actor.agent.id:
actor.actor_type == "agent"
and actor.agent
and task.assigned_agent_id == actor.agent.id
):
return task return task
assigned_agent = session.get(Agent, task.assigned_agent_id) assigned_agent = session.get(Agent, task.assigned_agent_id)
if assigned_agent: if assigned_agent:
@@ -740,11 +726,7 @@ def create_task_comment(
snippet = payload.message.strip() snippet = payload.message.strip()
if len(snippet) > 500: if len(snippet) > 500:
snippet = f"{snippet[:497]}..." snippet = f"{snippet[:497]}..."
actor_name = ( actor_name = actor.agent.name if actor.actor_type == "agent" and actor.agent else "User"
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:
continue continue

View File

@@ -1,10 +1,10 @@
from __future__ import annotations from __future__ import annotations
import logging
from dataclasses import dataclass from dataclasses import dataclass
from typing import Literal from typing import Literal
from fastapi import Depends, Header, HTTPException, Request, status from fastapi import Depends, Header, HTTPException, Request, status
import logging
from sqlmodel import Session, col, select from sqlmodel import Session, col, select
from app.core.agent_tokens import verify_agent_token from app.core.agent_tokens import verify_agent_token

View File

@@ -31,5 +31,4 @@ class Settings(BaseSettings):
log_use_utc: bool = False log_use_utc: bool = False
settings = Settings() settings = Settings()

View File

@@ -5,8 +5,8 @@ from app.models.board_memory import BoardMemory
from app.models.board_onboarding import BoardOnboardingSession from app.models.board_onboarding import BoardOnboardingSession
from app.models.boards import Board from app.models.boards import Board
from app.models.gateways import Gateway from app.models.gateways import Gateway
from app.models.tasks import Task
from app.models.task_fingerprints import TaskFingerprint from app.models.task_fingerprints import TaskFingerprint
from app.models.tasks import Task
from app.models.users import User from app.models.users import User
__all__ = [ __all__ = [

View File

@@ -24,9 +24,7 @@ class BoardCreate(BoardBase):
def validate_goal_fields(self): def validate_goal_fields(self):
if self.board_type == "goal" and self.goal_confirmed: if self.board_type == "goal" and self.goal_confirmed:
if not self.objective or not self.success_metrics: if not self.objective or not self.success_metrics:
raise ValueError( raise ValueError("Confirmed goal boards require objective and success_metrics")
"Confirmed goal boards require objective and success_metrics"
)
return self return self

View File

@@ -10,11 +10,7 @@ from jinja2 import Environment, FileSystemLoader, StrictUndefined, select_autoes
from app.core.config import settings from app.core.config import settings
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
from app.integrations.openclaw_gateway import ( from app.integrations.openclaw_gateway import OpenClawGatewayError, ensure_session, openclaw_call
OpenClawGatewayError,
ensure_session,
openclaw_call,
)
from app.models.agents import Agent from app.models.agents import Agent
from app.models.boards import Board from app.models.boards import Board
from app.models.gateways import Gateway from app.models.gateways import Gateway
@@ -304,9 +300,7 @@ def _render_agent_files(
) )
heartbeat_path = _templates_root() / heartbeat_template heartbeat_path = _templates_root() / heartbeat_template
if heartbeat_path.exists(): if heartbeat_path.exists():
rendered[name] = ( rendered[name] = env.get_template(heartbeat_template).render(**context).strip()
env.get_template(heartbeat_template).render(**context).strip()
)
continue continue
override = overrides.get(name) override = overrides.get(name)
if override: if override:
@@ -400,7 +394,9 @@ async def _remove_gateway_agent_list(
if not isinstance(lst, list): if not isinstance(lst, list):
raise OpenClawGatewayError("config agents.list is not a list") raise OpenClawGatewayError("config agents.list is not a list")
new_list = [entry for entry in lst if not (isinstance(entry, dict) and entry.get("id") == agent_id)] new_list = [
entry for entry in lst if not (isinstance(entry, dict) and entry.get("id") == agent_id)
]
if len(new_list) == len(lst): if len(new_list) == len(lst):
return return
patch = {"agents": {"list": new_list}} patch = {"agents": {"list": new_list}}