agentweave-hub 0.34.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentweave_hub-0.34.1/PKG-INFO +20 -0
- agentweave_hub-0.34.1/agentweave_hub.egg-info/PKG-INFO +20 -0
- agentweave_hub-0.34.1/agentweave_hub.egg-info/SOURCES.txt +86 -0
- agentweave_hub-0.34.1/agentweave_hub.egg-info/dependency_links.txt +1 -0
- agentweave_hub-0.34.1/agentweave_hub.egg-info/entry_points.txt +2 -0
- agentweave_hub-0.34.1/agentweave_hub.egg-info/requires.txt +16 -0
- agentweave_hub-0.34.1/agentweave_hub.egg-info/top_level.txt +1 -0
- agentweave_hub-0.34.1/hub/__init__.py +3 -0
- agentweave_hub-0.34.1/hub/api/__init__.py +1 -0
- agentweave_hub-0.34.1/hub/api/v1/__init__.py +32 -0
- agentweave_hub-0.34.1/hub/api/v1/agent_chat.py +234 -0
- agentweave_hub-0.34.1/hub/api/v1/agent_trigger.py +306 -0
- agentweave_hub-0.34.1/hub/api/v1/agents.py +1231 -0
- agentweave_hub-0.34.1/hub/api/v1/events.py +95 -0
- agentweave_hub-0.34.1/hub/api/v1/instructions.py +53 -0
- agentweave_hub-0.34.1/hub/api/v1/jobs.py +417 -0
- agentweave_hub-0.34.1/hub/api/v1/logs.py +98 -0
- agentweave_hub-0.34.1/hub/api/v1/messages.py +109 -0
- agentweave_hub-0.34.1/hub/api/v1/questions.py +138 -0
- agentweave_hub-0.34.1/hub/api/v1/session_sync.py +118 -0
- agentweave_hub-0.34.1/hub/api/v1/setup.py +71 -0
- agentweave_hub-0.34.1/hub/api/v1/status.py +87 -0
- agentweave_hub-0.34.1/hub/api/v1/tasks.py +192 -0
- agentweave_hub-0.34.1/hub/auth.py +131 -0
- agentweave_hub-0.34.1/hub/config.py +25 -0
- agentweave_hub-0.34.1/hub/data/roles/architect.md +54 -0
- agentweave_hub-0.34.1/hub/data/roles/backend_dev.md +62 -0
- agentweave_hub-0.34.1/hub/data/roles/code_reviewer.md +70 -0
- agentweave_hub-0.34.1/hub/data/roles/data_engineer.md +54 -0
- agentweave_hub-0.34.1/hub/data/roles/devops_engineer.md +54 -0
- agentweave_hub-0.34.1/hub/data/roles/frontend_dev.md +62 -0
- agentweave_hub-0.34.1/hub/data/roles/fullstack_dev.md +57 -0
- agentweave_hub-0.34.1/hub/data/roles/ml_engineer.md +56 -0
- agentweave_hub-0.34.1/hub/data/roles/project_manager.md +72 -0
- agentweave_hub-0.34.1/hub/data/roles/qa_engineer.md +61 -0
- agentweave_hub-0.34.1/hub/data/roles/roles.json +97 -0
- agentweave_hub-0.34.1/hub/data/roles/security_engineer.md +86 -0
- agentweave_hub-0.34.1/hub/data/roles/tech_lead.md +57 -0
- agentweave_hub-0.34.1/hub/data/roles/technical_writer.md +52 -0
- agentweave_hub-0.34.1/hub/db/__init__.py +1 -0
- agentweave_hub-0.34.1/hub/db/engine.py +145 -0
- agentweave_hub-0.34.1/hub/db/models.py +317 -0
- agentweave_hub-0.34.1/hub/main.py +140 -0
- agentweave_hub-0.34.1/hub/mcp_server.py +730 -0
- agentweave_hub-0.34.1/hub/migrations/__init__.py +0 -0
- agentweave_hub-0.34.1/hub/migrations/env.py +51 -0
- agentweave_hub-0.34.1/hub/migrations/versions/0001_add_agent_outputs.py +41 -0
- agentweave_hub-0.34.1/hub/migrations/versions/0002_add_event_severity.py +44 -0
- agentweave_hub-0.34.1/hub/migrations/versions/0003_add_message_session_id.py +41 -0
- agentweave_hub-0.34.1/hub/migrations/versions/0004_add_agent_table.py +41 -0
- agentweave_hub-0.34.1/hub/migrations/versions/0005_add_agent_self_registration_columns.py +48 -0
- agentweave_hub-0.34.1/hub/migrations/versions/0006_add_agent_config_column.py +34 -0
- agentweave_hub-0.34.1/hub/migrations/versions/0007_add_job_run_error_summary.py +41 -0
- agentweave_hub-0.34.1/hub/migrations/versions/0008_cap_job_run_error_summary.py +52 -0
- agentweave_hub-0.34.1/hub/scheduler.py +364 -0
- agentweave_hub-0.34.1/hub/schemas/__init__.py +1 -0
- agentweave_hub-0.34.1/hub/schemas/agents.py +66 -0
- agentweave_hub-0.34.1/hub/schemas/common.py +21 -0
- agentweave_hub-0.34.1/hub/schemas/jobs.py +75 -0
- agentweave_hub-0.34.1/hub/schemas/logs.py +25 -0
- agentweave_hub-0.34.1/hub/schemas/messages.py +46 -0
- agentweave_hub-0.34.1/hub/schemas/questions.py +30 -0
- agentweave_hub-0.34.1/hub/schemas/tasks.py +140 -0
- agentweave_hub-0.34.1/hub/sse.py +83 -0
- agentweave_hub-0.34.1/hub/static/ui/assets/index-B1rDiHmG.js +41 -0
- agentweave_hub-0.34.1/hub/static/ui/assets/index-C8QibtKd.css +1 -0
- agentweave_hub-0.34.1/hub/static/ui/index.html +18 -0
- agentweave_hub-0.34.1/hub/utils.py +34 -0
- agentweave_hub-0.34.1/pyproject.toml +47 -0
- agentweave_hub-0.34.1/setup.cfg +4 -0
- agentweave_hub-0.34.1/tests/test_agent_chat.py +391 -0
- agentweave_hub-0.34.1/tests/test_agents.py +164 -0
- agentweave_hub-0.34.1/tests/test_agents_self_registered.py +411 -0
- agentweave_hub-0.34.1/tests/test_auth.py +84 -0
- agentweave_hub-0.34.1/tests/test_bola.py +290 -0
- agentweave_hub-0.34.1/tests/test_instructions.py +95 -0
- agentweave_hub-0.34.1/tests/test_jobs.py +415 -0
- agentweave_hub-0.34.1/tests/test_jobs_crud.py +415 -0
- agentweave_hub-0.34.1/tests/test_mcp_server.py +760 -0
- agentweave_hub-0.34.1/tests/test_messages.py +109 -0
- agentweave_hub-0.34.1/tests/test_migrations.py +379 -0
- agentweave_hub-0.34.1/tests/test_pilot_mode.py +173 -0
- agentweave_hub-0.34.1/tests/test_questions.py +42 -0
- agentweave_hub-0.34.1/tests/test_runtime_diagnostics.py +100 -0
- agentweave_hub-0.34.1/tests/test_setup.py +94 -0
- agentweave_hub-0.34.1/tests/test_sse.py +120 -0
- agentweave_hub-0.34.1/tests/test_status.py +17 -0
- agentweave_hub-0.34.1/tests/test_tasks.py +209 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentweave-hub
|
|
3
|
+
Version: 0.34.1
|
|
4
|
+
Summary: AgentWeave Hub — self-hosted FastAPI server for multi-agent collaboration
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: fastapi>=0.110
|
|
7
|
+
Requires-Dist: uvicorn[standard]>=0.27
|
|
8
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0
|
|
9
|
+
Requires-Dist: aiosqlite>=0.20
|
|
10
|
+
Requires-Dist: pydantic>=2.0
|
|
11
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
12
|
+
Requires-Dist: alembic>=1.13
|
|
13
|
+
Requires-Dist: fastmcp>=2.0
|
|
14
|
+
Requires-Dist: sse-starlette>=2.0
|
|
15
|
+
Requires-Dist: croniter>=2.0
|
|
16
|
+
Requires-Dist: apscheduler>=3.10
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
20
|
+
Requires-Dist: httpx>=0.27; extra == "dev"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentweave-hub
|
|
3
|
+
Version: 0.34.1
|
|
4
|
+
Summary: AgentWeave Hub — self-hosted FastAPI server for multi-agent collaboration
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: fastapi>=0.110
|
|
7
|
+
Requires-Dist: uvicorn[standard]>=0.27
|
|
8
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0
|
|
9
|
+
Requires-Dist: aiosqlite>=0.20
|
|
10
|
+
Requires-Dist: pydantic>=2.0
|
|
11
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
12
|
+
Requires-Dist: alembic>=1.13
|
|
13
|
+
Requires-Dist: fastmcp>=2.0
|
|
14
|
+
Requires-Dist: sse-starlette>=2.0
|
|
15
|
+
Requires-Dist: croniter>=2.0
|
|
16
|
+
Requires-Dist: apscheduler>=3.10
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
20
|
+
Requires-Dist: httpx>=0.27; extra == "dev"
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
agentweave_hub.egg-info/PKG-INFO
|
|
3
|
+
agentweave_hub.egg-info/SOURCES.txt
|
|
4
|
+
agentweave_hub.egg-info/dependency_links.txt
|
|
5
|
+
agentweave_hub.egg-info/entry_points.txt
|
|
6
|
+
agentweave_hub.egg-info/requires.txt
|
|
7
|
+
agentweave_hub.egg-info/top_level.txt
|
|
8
|
+
hub/__init__.py
|
|
9
|
+
hub/auth.py
|
|
10
|
+
hub/config.py
|
|
11
|
+
hub/main.py
|
|
12
|
+
hub/mcp_server.py
|
|
13
|
+
hub/scheduler.py
|
|
14
|
+
hub/sse.py
|
|
15
|
+
hub/utils.py
|
|
16
|
+
hub/api/__init__.py
|
|
17
|
+
hub/api/v1/__init__.py
|
|
18
|
+
hub/api/v1/agent_chat.py
|
|
19
|
+
hub/api/v1/agent_trigger.py
|
|
20
|
+
hub/api/v1/agents.py
|
|
21
|
+
hub/api/v1/events.py
|
|
22
|
+
hub/api/v1/instructions.py
|
|
23
|
+
hub/api/v1/jobs.py
|
|
24
|
+
hub/api/v1/logs.py
|
|
25
|
+
hub/api/v1/messages.py
|
|
26
|
+
hub/api/v1/questions.py
|
|
27
|
+
hub/api/v1/session_sync.py
|
|
28
|
+
hub/api/v1/setup.py
|
|
29
|
+
hub/api/v1/status.py
|
|
30
|
+
hub/api/v1/tasks.py
|
|
31
|
+
hub/data/roles/architect.md
|
|
32
|
+
hub/data/roles/backend_dev.md
|
|
33
|
+
hub/data/roles/code_reviewer.md
|
|
34
|
+
hub/data/roles/data_engineer.md
|
|
35
|
+
hub/data/roles/devops_engineer.md
|
|
36
|
+
hub/data/roles/frontend_dev.md
|
|
37
|
+
hub/data/roles/fullstack_dev.md
|
|
38
|
+
hub/data/roles/ml_engineer.md
|
|
39
|
+
hub/data/roles/project_manager.md
|
|
40
|
+
hub/data/roles/qa_engineer.md
|
|
41
|
+
hub/data/roles/roles.json
|
|
42
|
+
hub/data/roles/security_engineer.md
|
|
43
|
+
hub/data/roles/tech_lead.md
|
|
44
|
+
hub/data/roles/technical_writer.md
|
|
45
|
+
hub/db/__init__.py
|
|
46
|
+
hub/db/engine.py
|
|
47
|
+
hub/db/models.py
|
|
48
|
+
hub/migrations/__init__.py
|
|
49
|
+
hub/migrations/env.py
|
|
50
|
+
hub/migrations/versions/0001_add_agent_outputs.py
|
|
51
|
+
hub/migrations/versions/0002_add_event_severity.py
|
|
52
|
+
hub/migrations/versions/0003_add_message_session_id.py
|
|
53
|
+
hub/migrations/versions/0004_add_agent_table.py
|
|
54
|
+
hub/migrations/versions/0005_add_agent_self_registration_columns.py
|
|
55
|
+
hub/migrations/versions/0006_add_agent_config_column.py
|
|
56
|
+
hub/migrations/versions/0007_add_job_run_error_summary.py
|
|
57
|
+
hub/migrations/versions/0008_cap_job_run_error_summary.py
|
|
58
|
+
hub/schemas/__init__.py
|
|
59
|
+
hub/schemas/agents.py
|
|
60
|
+
hub/schemas/common.py
|
|
61
|
+
hub/schemas/jobs.py
|
|
62
|
+
hub/schemas/logs.py
|
|
63
|
+
hub/schemas/messages.py
|
|
64
|
+
hub/schemas/questions.py
|
|
65
|
+
hub/schemas/tasks.py
|
|
66
|
+
hub/static/ui/index.html
|
|
67
|
+
hub/static/ui/assets/index-B1rDiHmG.js
|
|
68
|
+
hub/static/ui/assets/index-C8QibtKd.css
|
|
69
|
+
tests/test_agent_chat.py
|
|
70
|
+
tests/test_agents.py
|
|
71
|
+
tests/test_agents_self_registered.py
|
|
72
|
+
tests/test_auth.py
|
|
73
|
+
tests/test_bola.py
|
|
74
|
+
tests/test_instructions.py
|
|
75
|
+
tests/test_jobs.py
|
|
76
|
+
tests/test_jobs_crud.py
|
|
77
|
+
tests/test_mcp_server.py
|
|
78
|
+
tests/test_messages.py
|
|
79
|
+
tests/test_migrations.py
|
|
80
|
+
tests/test_pilot_mode.py
|
|
81
|
+
tests/test_questions.py
|
|
82
|
+
tests/test_runtime_diagnostics.py
|
|
83
|
+
tests/test_setup.py
|
|
84
|
+
tests/test_sse.py
|
|
85
|
+
tests/test_status.py
|
|
86
|
+
tests/test_tasks.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
fastapi>=0.110
|
|
2
|
+
uvicorn[standard]>=0.27
|
|
3
|
+
sqlalchemy[asyncio]>=2.0
|
|
4
|
+
aiosqlite>=0.20
|
|
5
|
+
pydantic>=2.0
|
|
6
|
+
pydantic-settings>=2.0
|
|
7
|
+
alembic>=1.13
|
|
8
|
+
fastmcp>=2.0
|
|
9
|
+
sse-starlette>=2.0
|
|
10
|
+
croniter>=2.0
|
|
11
|
+
apscheduler>=3.10
|
|
12
|
+
|
|
13
|
+
[dev]
|
|
14
|
+
pytest>=8
|
|
15
|
+
pytest-asyncio>=0.23
|
|
16
|
+
httpx>=0.27
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hub
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""API package."""
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Compose all v1 routers."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter
|
|
4
|
+
|
|
5
|
+
from .messages import router as messages_router
|
|
6
|
+
from .tasks import router as tasks_router
|
|
7
|
+
from .questions import router as questions_router
|
|
8
|
+
from .status import router as status_router
|
|
9
|
+
from .events import router as events_router
|
|
10
|
+
from .logs import router as logs_router
|
|
11
|
+
from .agents import router as agents_router
|
|
12
|
+
from .agent_trigger import router as agent_trigger_router
|
|
13
|
+
from .agent_chat import router as agent_chat_router
|
|
14
|
+
from .session_sync import router as session_sync_router
|
|
15
|
+
from .jobs import router as jobs_router
|
|
16
|
+
from .setup import router as setup_router
|
|
17
|
+
from .instructions import router as instructions_router
|
|
18
|
+
|
|
19
|
+
v1_router = APIRouter(prefix="/api/v1")
|
|
20
|
+
v1_router.include_router(messages_router)
|
|
21
|
+
v1_router.include_router(tasks_router)
|
|
22
|
+
v1_router.include_router(questions_router)
|
|
23
|
+
v1_router.include_router(status_router)
|
|
24
|
+
v1_router.include_router(events_router)
|
|
25
|
+
v1_router.include_router(logs_router)
|
|
26
|
+
v1_router.include_router(agents_router)
|
|
27
|
+
v1_router.include_router(agent_trigger_router)
|
|
28
|
+
v1_router.include_router(agent_chat_router)
|
|
29
|
+
v1_router.include_router(session_sync_router)
|
|
30
|
+
v1_router.include_router(jobs_router)
|
|
31
|
+
v1_router.include_router(setup_router)
|
|
32
|
+
v1_router.include_router(instructions_router)
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""Agent chat endpoints — GET /api/v1/agent/{agent}/chat/{session_id}"""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timedelta, timezone
|
|
4
|
+
from typing import List, Optional, Tuple
|
|
5
|
+
|
|
6
|
+
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
from sqlalchemy import func, select
|
|
9
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
10
|
+
|
|
11
|
+
from ...auth import get_project
|
|
12
|
+
from ...db.engine import get_session
|
|
13
|
+
from ...db.models import AgentOutput, Message
|
|
14
|
+
|
|
15
|
+
router = APIRouter(prefix="/agent", tags=["agent-chat"])
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ChatMessage(BaseModel):
|
|
19
|
+
id: str
|
|
20
|
+
role: str # 'user' or 'agent'
|
|
21
|
+
content: str
|
|
22
|
+
timestamp: datetime
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ChatHistoryResponse(BaseModel):
|
|
26
|
+
session_id: str
|
|
27
|
+
agent: str
|
|
28
|
+
messages: List[ChatMessage]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@router.get("/{agent}/chat/{session_id}", response_model=ChatHistoryResponse)
|
|
32
|
+
async def get_chat_history(
|
|
33
|
+
agent: str,
|
|
34
|
+
session_id: str,
|
|
35
|
+
project: Tuple[str, str] = Depends(get_project),
|
|
36
|
+
session: AsyncSession = Depends(get_session),
|
|
37
|
+
):
|
|
38
|
+
"""Get conversation history for a specific agent session.
|
|
39
|
+
|
|
40
|
+
Returns messages between user and agent for the given session,
|
|
41
|
+
including both direct messages and agent output.
|
|
42
|
+
"""
|
|
43
|
+
project_id, _ = project
|
|
44
|
+
|
|
45
|
+
# Get agent outputs for this session
|
|
46
|
+
output_q = (
|
|
47
|
+
select(AgentOutput)
|
|
48
|
+
.where(
|
|
49
|
+
AgentOutput.project_id == project_id,
|
|
50
|
+
AgentOutput.agent == agent,
|
|
51
|
+
AgentOutput.session_id == session_id,
|
|
52
|
+
)
|
|
53
|
+
.order_by(AgentOutput.timestamp.asc())
|
|
54
|
+
)
|
|
55
|
+
output_result = await session.execute(output_q)
|
|
56
|
+
session_outputs = output_result.scalars().all()
|
|
57
|
+
|
|
58
|
+
# Build time window for this session (used for untagged messages)
|
|
59
|
+
session_first_ts = min((o.timestamp for o in session_outputs), default=None)
|
|
60
|
+
session_last_ts = max((o.timestamp for o in session_outputs), default=None)
|
|
61
|
+
|
|
62
|
+
# Get all user messages to this agent
|
|
63
|
+
msg_q = (
|
|
64
|
+
select(Message)
|
|
65
|
+
.where(
|
|
66
|
+
Message.project_id == project_id,
|
|
67
|
+
Message.recipient == agent,
|
|
68
|
+
Message.sender == "user",
|
|
69
|
+
)
|
|
70
|
+
.order_by(Message.timestamp.asc())
|
|
71
|
+
)
|
|
72
|
+
msg_result = await session.execute(msg_q)
|
|
73
|
+
user_messages = msg_result.scalars().all()
|
|
74
|
+
|
|
75
|
+
# Get first-output timestamps for all OTHER sessions (used for Tier 3 attribution)
|
|
76
|
+
other_starts_q = (
|
|
77
|
+
select(func.min(AgentOutput.timestamp))
|
|
78
|
+
.where(
|
|
79
|
+
AgentOutput.project_id == project_id,
|
|
80
|
+
AgentOutput.agent == agent,
|
|
81
|
+
AgentOutput.session_id.isnot(None),
|
|
82
|
+
AgentOutput.session_id != session_id,
|
|
83
|
+
)
|
|
84
|
+
.group_by(AgentOutput.session_id)
|
|
85
|
+
)
|
|
86
|
+
other_starts_result = await session.execute(other_starts_q)
|
|
87
|
+
other_first_timestamps = [row[0] for row in other_starts_result.all() if row[0] is not None]
|
|
88
|
+
|
|
89
|
+
messages: List[ChatMessage] = []
|
|
90
|
+
|
|
91
|
+
for msg in user_messages:
|
|
92
|
+
content = msg.content or ""
|
|
93
|
+
|
|
94
|
+
# 1. Exact match by session_id column (post-migration resume messages)
|
|
95
|
+
if msg.session_id == session_id:
|
|
96
|
+
messages.append(
|
|
97
|
+
ChatMessage(
|
|
98
|
+
id=msg.id,
|
|
99
|
+
role="user",
|
|
100
|
+
content=(
|
|
101
|
+
content.split("\n\n[Session:")[0] if "[Session:" in content else content
|
|
102
|
+
),
|
|
103
|
+
timestamp=msg.timestamp,
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
continue
|
|
107
|
+
|
|
108
|
+
# 2. Fallback: content tag match (pre-migration resume messages)
|
|
109
|
+
if f"[Session: {session_id}]" in content:
|
|
110
|
+
messages.append(
|
|
111
|
+
ChatMessage(
|
|
112
|
+
id=msg.id,
|
|
113
|
+
role="user",
|
|
114
|
+
content=(
|
|
115
|
+
content.split("\n\n[Session:")[0] if "[Session:" in content else content
|
|
116
|
+
),
|
|
117
|
+
timestamp=msg.timestamp,
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
# 3. Untagged messages (new-session messages with session_id=None).
|
|
123
|
+
# Only include if they fall within this session's time window AND no other
|
|
124
|
+
# session started closer to the message (nearest-session wins, prevents
|
|
125
|
+
# messages from previous new-sessions bleeding into the current one).
|
|
126
|
+
if msg.session_id is None and "[Session:" not in content:
|
|
127
|
+
if session_first_ts is not None and session_last_ts is not None:
|
|
128
|
+
in_window = (
|
|
129
|
+
session_first_ts - timedelta(minutes=5) <= msg.timestamp <= session_last_ts
|
|
130
|
+
)
|
|
131
|
+
# Exclude if another session started between this message and the current session
|
|
132
|
+
closer_session_exists = any(
|
|
133
|
+
msg.timestamp <= other_ts < session_first_ts
|
|
134
|
+
for other_ts in other_first_timestamps
|
|
135
|
+
)
|
|
136
|
+
if in_window and not closer_session_exists:
|
|
137
|
+
messages.append(
|
|
138
|
+
ChatMessage(
|
|
139
|
+
id=msg.id,
|
|
140
|
+
role="user",
|
|
141
|
+
content=content,
|
|
142
|
+
timestamp=msg.timestamp,
|
|
143
|
+
)
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Add agent outputs for this session
|
|
147
|
+
for output in session_outputs:
|
|
148
|
+
messages.append(
|
|
149
|
+
ChatMessage(
|
|
150
|
+
id=output.id,
|
|
151
|
+
role="agent",
|
|
152
|
+
content=output.content,
|
|
153
|
+
timestamp=output.timestamp,
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Sort by timestamp
|
|
158
|
+
messages.sort(key=lambda m: m.timestamp)
|
|
159
|
+
|
|
160
|
+
return ChatHistoryResponse(
|
|
161
|
+
session_id=session_id,
|
|
162
|
+
agent=agent,
|
|
163
|
+
messages=messages,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@router.get("/{agent}/chat", response_model=List[ChatMessage])
|
|
168
|
+
async def get_recent_chat(
|
|
169
|
+
agent: str,
|
|
170
|
+
limit: int = Query(50, ge=1, le=500),
|
|
171
|
+
project: Tuple[str, str] = Depends(get_project),
|
|
172
|
+
session: AsyncSession = Depends(get_session),
|
|
173
|
+
):
|
|
174
|
+
"""Get recent chat messages with an agent across all sessions.
|
|
175
|
+
|
|
176
|
+
Returns the most recent messages between user and agent,
|
|
177
|
+
useful for a general chat view without session filtering.
|
|
178
|
+
"""
|
|
179
|
+
project_id, _ = project
|
|
180
|
+
|
|
181
|
+
# Get recent messages from user to agent
|
|
182
|
+
msg_q = (
|
|
183
|
+
select(Message)
|
|
184
|
+
.where(
|
|
185
|
+
Message.project_id == project_id,
|
|
186
|
+
Message.recipient == agent,
|
|
187
|
+
Message.sender == "user",
|
|
188
|
+
)
|
|
189
|
+
.order_by(Message.timestamp.desc())
|
|
190
|
+
.limit(limit)
|
|
191
|
+
)
|
|
192
|
+
msg_result = await session.execute(msg_q)
|
|
193
|
+
user_messages = msg_result.scalars().all()
|
|
194
|
+
|
|
195
|
+
# Get recent agent outputs
|
|
196
|
+
output_q = (
|
|
197
|
+
select(AgentOutput)
|
|
198
|
+
.where(
|
|
199
|
+
AgentOutput.project_id == project_id,
|
|
200
|
+
AgentOutput.agent == agent,
|
|
201
|
+
)
|
|
202
|
+
.order_by(AgentOutput.timestamp.desc())
|
|
203
|
+
.limit(limit)
|
|
204
|
+
)
|
|
205
|
+
output_result = await session.execute(output_q)
|
|
206
|
+
agent_outputs = output_result.scalars().all()
|
|
207
|
+
|
|
208
|
+
# Build chat messages
|
|
209
|
+
messages: List[ChatMessage] = []
|
|
210
|
+
|
|
211
|
+
for msg in user_messages:
|
|
212
|
+
content = msg.content or ""
|
|
213
|
+
messages.append(
|
|
214
|
+
ChatMessage(
|
|
215
|
+
id=msg.id,
|
|
216
|
+
role="user",
|
|
217
|
+
content=content.split("\n\n[Session:")[0] if "[Session:" in content else content,
|
|
218
|
+
timestamp=msg.timestamp,
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
for output in agent_outputs:
|
|
223
|
+
messages.append(
|
|
224
|
+
ChatMessage(
|
|
225
|
+
id=output.id,
|
|
226
|
+
role="agent",
|
|
227
|
+
content=output.content,
|
|
228
|
+
timestamp=output.timestamp,
|
|
229
|
+
)
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
# Sort by timestamp and limit
|
|
233
|
+
messages.sort(key=lambda m: m.timestamp)
|
|
234
|
+
return messages[-limit:]
|