Skip to content

Commit 3ef949f

Browse files
mtanzimscott-coheregiannis2two
authored
agents: track indexing tasks (#676)
* plumb through agent_id * worker can access db to persist task agent rs * decorator works * does this actually work? * fix missing args * Squashed commit of the following: commit 2ea591d Author: Scott <[email protected]> Date: Thu Aug 15 17:34:28 2024 -0400 db changes * wire up agent task status with controller * return serialized json from tasks * . * raise job errors correctly and read back exception snippet * get task status in client * thanks tailwind * link to the indexing page * copypasta galore * fix type errors * lint * revert ui change * lint with new tools * will this fix tests? * fix lint * simplify restore * . * clean ups * small fixes * fix * feedback * lint * fixes * fixes, still need to check db changes * fe changes * fix all --------- Co-authored-by: Scott <[email protected]> Co-authored-by: giannis <[email protected]>
1 parent 75031b4 commit 3ef949f

File tree

34 files changed

+626
-234
lines changed

34 files changed

+626
-234
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,6 @@ secrets.toml
156156
/src/backend/config/configuration.yaml
157157
/src/backend/config/secrets.yaml
158158
logs/
159+
credentials.json
160+
token.json
161+
src/interfaces/assistants_web/bun.lockb

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ win-setup:
7878
poetry install --with setup --verbose
7979
poetry run python src/backend/cli/main.py
8080

81+
.PHONY: typecheck
82+
typecheck:
83+
poetry run pyright
84+
8185
.PHONY: lint
8286
lint:
8387
poetry run ruff check
@@ -123,3 +127,7 @@ test-db:
123127
.PHONY: dev-sync
124128
dev-sync:
125129
@docker compose up --build sync_worker sync_publisher flower -d
130+
131+
.PHONY: dev-sync-down
132+
dev-sync-down:
133+
@docker compose down sync_worker sync_publisher flower

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ requires = ["poetry-core"]
116116
build-backend = "poetry.core.masonry.api"
117117

118118
[tool.pyright]
119-
include = ["src/backend/services/metrics.py"]
119+
include = [
120+
"src/backend/services/metrics.py",
121+
"src/backend/tools/google_drive/sync/actions/",
122+
]
120123
defineConstant = { DEBUG = true }
121124
reportMissingImports = true
122125
reportMissingTypeStubs = false

src/backend/alembic/env.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727
target_metadata = Base.metadata
2828

2929

30+
def include_object(object, name, type_, reflected, compare_to):
31+
if type_ == "table" and reflected and compare_to is None:
32+
return False
33+
else:
34+
return True
35+
36+
3037
def run_migrations_offline() -> None:
3138
"""Run migrations in 'offline' mode.
3239
@@ -45,6 +52,7 @@ def run_migrations_offline() -> None:
4552
target_metadata=target_metadata,
4653
literal_binds=True,
4754
dialect_opts={"paramstyle": "named"},
55+
include_object=include_object,
4856
)
4957

5058
with context.begin_transaction():
@@ -77,6 +85,7 @@ def process_revision_directives(context, revision, directives):
7785
connection=connection,
7886
target_metadata=target_metadata,
7987
process_revision_directives=process_revision_directives,
88+
include_object=include_object,
8089
)
8190

8291
with context.begin_transaction():
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
3+
Revision ID: ac3933258035
4+
Revises: 08bcb9a24d9b
5+
Create Date: 2024-08-22 20:34:37.547325
6+
7+
"""
8+
from typing import Sequence, Union
9+
10+
import sqlalchemy as sa
11+
from alembic import op
12+
13+
# revision identifiers, used by Alembic.
14+
revision: str = 'ac3933258035'
15+
down_revision: Union[str, None] = '08bcb9a24d9b'
16+
branch_labels: Union[str, Sequence[str], None] = None
17+
depends_on: Union[str, Sequence[str], None] = None
18+
19+
20+
def upgrade() -> None:
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
op.create_table('agent_tasks',
23+
sa.Column('agent_id', sa.String(), nullable=False),
24+
sa.Column('task_id', sa.String(), nullable=False),
25+
sa.Column('id', sa.String(), nullable=False),
26+
sa.Column('created_at', sa.DateTime(), nullable=True),
27+
sa.Column('updated_at', sa.DateTime(), nullable=True),
28+
sa.ForeignKeyConstraint(['agent_id'], ['agents.id'], ondelete='CASCADE'),
29+
sa.PrimaryKeyConstraint('id'),
30+
sa.UniqueConstraint('agent_id', 'task_id', name='unique_agent_task')
31+
)
32+
# ### end Alembic commands ###
33+
34+
35+
def downgrade() -> None:
36+
# ### commands auto generated by Alembic - please adjust! ###
37+
op.drop_table('agent_tasks')
38+
# ### end Alembic commands ###

src/backend/crud/agent_task.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from typing import List
2+
3+
from sqlalchemy.orm import Session
4+
5+
from backend.database_models.agent_task import AgentTask, SyncCeleryTaskMeta
6+
from backend.services.logger.utils import LoggerFactory
7+
from backend.services.transaction import validate_transaction
8+
9+
logger = LoggerFactory().get_logger()
10+
11+
12+
@validate_transaction
13+
def create_agent_task(db: Session, agent_id: str, task_id: str) -> AgentTask:
14+
agent_task = AgentTask(agent_id=agent_id, task_id=task_id)
15+
db.add(agent_task)
16+
db.commit()
17+
db.refresh(agent_task)
18+
return agent_task
19+
20+
21+
@validate_transaction
22+
def get_agent_tasks_by_agent_id(db: Session, agent_id: str) -> List[SyncCeleryTaskMeta]:
23+
return (
24+
db.query(SyncCeleryTaskMeta)
25+
.join(AgentTask, AgentTask.task_id == SyncCeleryTaskMeta.task_id)
26+
.filter(AgentTask.agent_id == agent_id)
27+
.all()
28+
)

src/backend/database_models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# ruff: noqa
22
from backend.database_models.agent import *
3+
from backend.database_models.agent_task import *
34
from backend.database_models.agent_tool_metadata import *
45
from backend.database_models.base import *
56
from backend.database_models.blacklist import *
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from sqlalchemy import (
2+
DateTime,
3+
ForeignKey,
4+
Integer,
5+
LargeBinary,
6+
String,
7+
Text,
8+
UniqueConstraint,
9+
)
10+
from sqlalchemy.orm import Mapped, mapped_column
11+
12+
from backend.database_models.base import Base, MinimalBase
13+
14+
15+
class SyncCeleryTaskMeta(MinimalBase):
16+
__tablename__ = "sync_celery_taskmeta"
17+
18+
id: Mapped[int] = mapped_column(Integer, primary_key=True)
19+
task_id: Mapped[str] = mapped_column(String(155), unique=True)
20+
status: Mapped[str] = mapped_column(String(50))
21+
result: Mapped[bytes] = mapped_column(LargeBinary)
22+
date_done: Mapped[DateTime] = mapped_column(DateTime)
23+
traceback: Mapped[str] = mapped_column(Text)
24+
name: Mapped[str] = mapped_column(String(155))
25+
args: Mapped[bytes] = mapped_column(LargeBinary)
26+
kwargs: Mapped[bytes] = mapped_column(LargeBinary)
27+
worker: Mapped[str] = mapped_column(String(155))
28+
retries: Mapped[int] = mapped_column(Integer)
29+
queue: Mapped[str] = mapped_column(String(155))
30+
31+
32+
class AgentTask(Base):
33+
__tablename__ = "agent_tasks"
34+
35+
agent_id: Mapped[str] = mapped_column(
36+
ForeignKey("agents.id", ondelete="CASCADE"), nullable=False
37+
)
38+
39+
task_id: Mapped[str] = mapped_column(nullable=False)
40+
41+
__table_args__ = (
42+
UniqueConstraint("agent_id", "task_id", name="unique_agent_task"),
43+
)

src/backend/database_models/base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ def __new__(cls, *args, **kwargs):
4242
return object.__new__(cls)
4343

4444

45+
class MinimalBase(DeclarativeBase):
46+
pass
47+
48+
4549
class Base(DeclarativeBase):
4650
id = mapped_column(
4751
String,

src/backend/routers/agent.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import asyncio
2-
from typing import Optional
2+
from typing import List, Optional
33

44
from fastapi import APIRouter, Depends, HTTPException
55
from fastapi import File as RequestFile
@@ -11,6 +11,7 @@
1111
from backend.crud import agent as agent_crud
1212
from backend.crud import agent_tool_metadata as agent_tool_metadata_crud
1313
from backend.crud import snapshot as snapshot_crud
14+
from backend.crud.agent_task import get_agent_tasks_by_agent_id
1415
from backend.database_models.agent import Agent as AgentModel
1516
from backend.database_models.agent_tool_metadata import (
1617
AgentToolMetadata as AgentToolMetadataModel,
@@ -20,6 +21,7 @@
2021
from backend.schemas.agent import (
2122
Agent,
2223
AgentPublic,
24+
AgentTaskResponse,
2325
AgentToolMetadata,
2426
AgentToolMetadataPublic,
2527
AgentVisibility,
@@ -40,6 +42,7 @@
4042
agent_to_metrics_agent,
4143
)
4244
from backend.services.agent import (
45+
parse_task,
4346
raise_db_error,
4447
validate_agent_exists,
4548
validate_agent_tool_metadata_exists,
@@ -246,7 +249,6 @@ async def get_agent_by_id(
246249
agent_schema = Agent.model_validate(agent)
247250
ctx.with_agent(agent_schema)
248251
ctx.with_metrics_agent(agent_to_metrics_agent(agent))
249-
250252
return agent
251253

252254

@@ -278,6 +280,23 @@ async def get_agent_deployments(
278280
]
279281

280282

283+
@router.get(
284+
"/{agent_id}/tasks",
285+
response_model=List[AgentTaskResponse],
286+
dependencies=[
287+
Depends(validate_user_header),
288+
],
289+
)
290+
async def get_agent_tasks(
291+
agent_id: str,
292+
session: DBSessionDep,
293+
ctx: Context = Depends(get_context),
294+
) -> List[AgentTaskResponse]:
295+
raw_tasks = get_agent_tasks_by_agent_id(session, agent_id)
296+
tasks = [parse_task(t) for t in raw_tasks]
297+
return tasks
298+
299+
281300
@router.put(
282301
"/{agent_id}",
283302
response_model=AgentPublic,

0 commit comments

Comments
 (0)