WIP: status component working; result page still being patched

This commit is contained in:
Francis Secada 2025-01-22 11:53:19 -05:00
parent 05d8baffb1
commit f2363ff81d
9 changed files with 76 additions and 70 deletions

View File

@ -10,7 +10,7 @@ annotated-types==0.7.0
# via
# pydantic
# sqlmodel-crud-utilities
anthropic==0.43.1
anthropic==0.44.0
# via pydantic-ai-slim
anyio==4.8.0
# via
@ -31,7 +31,7 @@ beautifulsoup4==4.12.3
# via httpx-html
billiard==4.2.1
# via celery
cachetools==5.5.0
cachetools==5.5.1
# via google-auth
celery==5.4.0
# via
@ -195,7 +195,7 @@ mistralai==1.4.0
# via pydantic-ai-slim
mypy-extensions==1.0.0
# via typing-inspect
openai==1.59.9
openai==1.60.0
# via
# -r core_requirements.in
# pydantic-ai-slim
@ -413,7 +413,7 @@ typing-inspect==0.9.0
# via
# -r core_requirements.in
# mistralai
tzdata==2024.2
tzdata==2025.1
# via
# celery
# kombu

View File

@ -84,7 +84,7 @@ fastapi-debug-toolbar @ git+https://github.com/fsecada01/fastapi-debug-toolbar.g
# via -r dev_requirements.in
fastjsonschema==2.21.1
# via nbformat
filelock==3.16.1
filelock==3.17.0
# via virtualenv
fqdn==1.5.1
# via jsonschema

View File

@ -80,7 +80,7 @@ dependencies = [
"aiomysql==0.2.0",
"amqp==5.3.1",
"annotated-types==0.7.0",
"anthropic==0.43.1",
"anthropic==0.44.0",
"anyio==4.8.0",
"appdirs==1.4.4",
"asgiref==3.8.1",
@ -88,7 +88,7 @@ dependencies = [
"asyncpg==0.30.0",
"beautifulsoup4==4.12.3",
"billiard==4.2.1",
"cachetools==5.5.0",
"cachetools==5.5.1",
"celery==5.4.0",
"certifi==2024.12.14",
"charset-normalizer==3.4.1",
@ -141,7 +141,7 @@ dependencies = [
"mdurl==0.1.2",
"mistralai==1.4.0",
"mypy-extensions==1.0.0",
"openai==1.59.9",
"openai==1.60.0",
"opentelemetry-api==1.29.0",
"opentelemetry-exporter-otlp-proto-common==1.29.0",
"opentelemetry-exporter-otlp-proto-http==1.29.0",
@ -203,7 +203,7 @@ dependencies = [
"tqdm==4.67.1",
"typing-extensions==4.12.2",
"typing-inspect==0.9.0",
"tzdata==2024.2",
"tzdata==2025.1",
"update-checker==0.18.0",
"urllib3==1.26.20",
"uvicorn==0.34.0",
@ -252,7 +252,7 @@ dev = [
"fastapi-debug-toolbar==0.6.3",
"fastapi==0.115.6",
"fastjsonschema==2.21.1",
"filelock==3.16.1",
"filelock==3.17.0",
"fqdn==1.5.1",
"greenlet==3.1.1",
"h11==0.14.0",

View File

@ -119,7 +119,7 @@ async def run_agent(
f"Perform a comprehensive SWOT analysis for this product: {url}",
deps=deps,
)
logger.info(f"Agent Result: {pformat(result.data)}")
logger.info(f"Agent Result: {pformat(result.data.model_dump())}")
if deps.update_status_func:
await deps.update_status_func(deps.request, "Analysis Complete")

View File

@ -13,6 +13,7 @@ from backend.site.consts import (
ANALYSIS_COMPLETE_MESSAGE,
ANALYZING_MESSAGE,
result_store,
running_tasks,
status_store,
)
from backend.site.utils import run_agent_with_progress
@ -47,13 +48,13 @@ async def analyze_url(request: Request, url: str = Form(...)) -> HTMLResponse:
:param url:
:return:
"""
running_tasks = set()
session_id = str(id(request))
request.session["analysis_id"] = session_id
request.session["start_time"] = asyncio.get_event_loop().time()
# Clearing out the status store for the analysis ID session
status_store[session_id] = []
result_store[session_id] = None
status_store[session_id].append(ANALYZING_MESSAGE)
@ -83,15 +84,18 @@ async def get_status(request: Request):
context = {"request": request, "messages": [], "result": False}
session_id = request.session.get("analysis_id")
if session_id:
logger.info(f"Found session id! {session_id}")
messages = status_store.get(session_id, [])
result = ANALYSIS_COMPLETE_MESSAGE in messages
logger.info(
f"Status check - Session ID: {'session_id'}, Messages: "
f"Status check - Session ID: {session_id}, Messages: "
f"{messages}",
)
context.update({"messages": messages, "result": result})
logger.info(context)
return templates.TemplateResponse("status.html", context=context)

View File

@ -1,6 +1,6 @@
{% extends "components/main/base.html" %}
{% block content %}
<section class="hero is-large is-info">
<section class="hero is-medium is-info">
<div class="hero-body">
<p class="title">SWOT ANALYZER</p>
<p class="subtitle">Strengths, Weaknesses, Opportunities and Threats
@ -31,29 +31,28 @@
</Search>
</div>
</section>
<section class="section">
<div class="container"
id="status">
<div class="box"
id="status"
hx-get={{ url_for('get_status') }}
hx-trigger='load, every 1s'
hx-swap='innerHTML'
style="display: none">
</div>
<div class="box"
id="result"
hx-get={{ url_for('get_result') }}
hx-trigger="load, every 1s[!this.querySelector('#result-container') || this.style.display === 'none']"
hx-swap='innerHTML'
hx-on:after-request="
if(this.innerHTML.trim().length > 0) {
const statusDiv = document.querySelector(#status);
if (statusDiv) statusDiv.style.display = 'none';
this.style.display = 'block'
}
">
</div>
<section class="section"
id="analysis-content">
<div class="box"
id="status"
hx-get={{ url_for('get_status') }}
hx-trigger="load, every 1s"
hx-swap="innerHTML"
style="display: none">
</div>
<div class="box"
id="result"
hx-get={{ url_for('get_result') }}
hx-trigger="load, every 1s[!this.querySelector('#result-container') || this.style.display === 'none']"
hx-swap="innerHTML"
hx-on:after-request="
if(this.innerHTML.trim().length > 0) {
console.log('Going to turn off the status element and load the result element.')
const statusDiv = document.querySelector('#status');
if (statusDiv) statusDiv.style.display = 'none';
this.style.display = 'block'
}
">
</div>
</section>
{% endblock content %}

View File

@ -1,17 +1,19 @@
{% if result %}
<section class="section"
id="result-container">
<div class="container"
id="result-container">
<h2 class="title is-2">
{{ result }}
</h2>
<div class="container">
<h2 class="subtitle is-2">Analysis Complete</h2>
<div class="fixed-grid">
<div class="grid">
{% for cat in result %}
{% for cat, val in result.items() %}
<div class="cell">
<div class="content">
<ul>
{% for result in cat %}
<ResultEntry result=result>
{% for value in val %}
<ResultEntry result=value>
{% if cat == 'strengths' %}
<i class="fas fa-solid fa-arrow-up"></i>
{% elif cat == 'weaknesses' %}
@ -23,7 +25,6 @@
class="fas fa-solid fa-triangle-exclamation"></i>
{% endif %}
</ResultEntry>
</ul>
</div>
</div>

View File

@ -7,18 +7,20 @@
{% set is_loading = loop.last and not result %}
{% set is_tool_message = message.startswith('Using tool') %}
<div class="box">
{% set bg_color = 'danger' if is_error else ('dark' if is_loading else
"info") %}
{% if is_error %}
{% set bg_color = 'danger' %}
{% set header_content, content = message.split('body:', 1) %}
{% elif is_tool_message %}
{% set header_content, content = message.split(' ', 2)[2].split('...', 1) %}
{% elif is_loading %}
{% set content = message %}
{% set header_content = 'In Progress' %}
{% else %}
{% set bg_color = 'success' %}
{% set content = message %}
{% set header_content = 'Complete' %}
{% elif is_tool_message %}
{% set bg_color = 'dark'%}
{% set header_content, content = message.split(' ', 2)[2].split('...', 1) %}
{% else %}
{% set bg_color = 'info' %}
{% set content = message %}
{% set header_content = 'In Progress' %}
{% endif %}
<StatusResult div_class={{ bg_color }}
header_content={{ header_content }}>{{ message }}

40
uv.lock generated
View File

@ -282,7 +282,7 @@ requires-dist = [
{ name = "aiomysql", specifier = "==0.2.0" },
{ name = "amqp", specifier = "==5.3.1" },
{ name = "annotated-types", specifier = "==0.7.0" },
{ name = "anthropic", specifier = "==0.43.1" },
{ name = "anthropic", specifier = "==0.44.0" },
{ name = "anyio", specifier = "==4.8.0" },
{ name = "appdirs", specifier = "==1.4.4" },
{ name = "asgiref", specifier = "==3.8.1" },
@ -290,7 +290,7 @@ requires-dist = [
{ name = "asyncpg", specifier = "==0.30.0" },
{ name = "beautifulsoup4", specifier = "==4.12.3" },
{ name = "billiard", specifier = "==4.2.1" },
{ name = "cachetools", specifier = "==5.5.0" },
{ name = "cachetools", specifier = "==5.5.1" },
{ name = "celery", specifier = "==5.4.0" },
{ name = "certifi", specifier = "==2024.12.14" },
{ name = "charset-normalizer", specifier = "==3.4.1" },
@ -343,7 +343,7 @@ requires-dist = [
{ name = "mdurl", specifier = "==0.1.2" },
{ name = "mistralai", specifier = "==1.4.0" },
{ name = "mypy-extensions", specifier = "==1.0.0" },
{ name = "openai", specifier = "==1.59.9" },
{ name = "openai", specifier = "==1.60.0" },
{ name = "opentelemetry-api", specifier = "==1.29.0" },
{ name = "opentelemetry-exporter-otlp-proto-common", specifier = "==1.29.0" },
{ name = "opentelemetry-exporter-otlp-proto-http", specifier = "==1.29.0" },
@ -405,7 +405,7 @@ requires-dist = [
{ name = "tqdm", specifier = "==4.67.1" },
{ name = "typing-extensions", specifier = "==4.12.2" },
{ name = "typing-inspect", specifier = "==0.9.0" },
{ name = "tzdata", specifier = "==2024.2" },
{ name = "tzdata", specifier = "==2025.1" },
{ name = "update-checker", specifier = "==0.18.0" },
{ name = "urllib3", specifier = "==1.26.20" },
{ name = "uvicorn", specifier = "==0.34.0" },
@ -454,7 +454,7 @@ dev = [
{ name = "fastapi", specifier = "==0.115.6" },
{ name = "fastapi-debug-toolbar", git = "https://github.com/fsecada01/fastapi-debug-toolbar.git?rev=2da9f1e724d1d7ca56990ba7a8e72598fa3e1cf4" },
{ name = "fastjsonschema", specifier = "==2.21.1" },
{ name = "filelock", specifier = "==3.16.1" },
{ name = "filelock", specifier = "==3.17.0" },
{ name = "fqdn", specifier = "==1.5.1" },
{ name = "greenlet", specifier = "==3.1.1" },
{ name = "h11", specifier = "==0.14.0" },
@ -606,7 +606,7 @@ wheels = [
[[package]]
name = "anthropic"
version = "0.43.1"
version = "0.44.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@ -617,9 +617,9 @@ dependencies = [
{ name = "sniffio" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ca/d8/238c2bc59e41a787e7b62460adfc7b2edd88f28b0a14e292801a72725369/anthropic-0.43.1.tar.gz", hash = "sha256:c7f13e4b7b515ac4a3111142310b214527c0fc561485e5bc9b582e49fe3adba2", size = 195298 }
sdist = { url = "https://files.pythonhosted.org/packages/eb/34/ed394012684f7d6e36bb36c8b7c82b438f0ef189d2afd3d0090b85801211/anthropic-0.44.0.tar.gz", hash = "sha256:dc5c91c8b0463f97513d2e79350511ef295a56910bac4fbbe9491016c71f2ef0", size = 196065 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/89/2b/63b167d76401f759c8c4ff0266042e60aac6fd3cc0685b27437ceaaf95eb/anthropic-0.43.1-py3-none-any.whl", hash = "sha256:20759c25cd0f4072eb966b0180a41c061c156473bbb674da6a3f1e92e1ad78f8", size = 208170 },
{ url = "https://files.pythonhosted.org/packages/d3/ad/c3c7d199eedc0b6d4621deed8dc1ed252ce399400cd76f1da098f1f50e56/anthropic-0.44.0-py3-none-any.whl", hash = "sha256:7087ccfc8ed7b164f971e094495cd3aeabac1e435fa393480cc146c87946c21c", size = 208634 },
]
[[package]]
@ -823,11 +823,11 @@ css = [
[[package]]
name = "cachetools"
version = "5.5.0"
version = "5.5.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c3/38/a0f315319737ecf45b4319a8cd1f3a908e29d9277b46942263292115eee7/cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a", size = 27661 }
sdist = { url = "https://files.pythonhosted.org/packages/d9/74/57df1ab0ce6bc5f6fa868e08de20df8ac58f9c44330c7671ad922d2bbeae/cachetools-5.5.1.tar.gz", hash = "sha256:70f238fbba50383ef62e55c6aff6d9673175fe59f7c6782c7a0b9e38f4a9df95", size = 28044 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a4/07/14f8ad37f2d12a5ce41206c21820d8cb6561b728e51fad4530dff0552a67/cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292", size = 9524 },
{ url = "https://files.pythonhosted.org/packages/ec/4e/de4ff18bcf55857ba18d3a4bd48c8a9fde6bb0980c9d20b263f05387fd88/cachetools-5.5.1-py3-none-any.whl", hash = "sha256:b76651fdc3b24ead3c648bbdeeb940c1b04d365b38b4af66788f9ec4a81d42bb", size = 9530 },
]
[[package]]
@ -1162,11 +1162,11 @@ wheels = [
[[package]]
name = "filelock"
version = "3.16.1"
version = "3.17.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037 }
sdist = { url = "https://files.pythonhosted.org/packages/dc/9c/0b15fb47b464e1b663b1acd1253a062aa5feecb07d4e597daea542ebd2b5/filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e", size = 18027 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 },
{ url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 },
]
[[package]]
@ -2091,7 +2091,7 @@ wheels = [
[[package]]
name = "openai"
version = "1.59.9"
version = "1.60.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@ -2103,9 +2103,9 @@ dependencies = [
{ name = "tqdm" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ec/2d/04faa92bac0341649223398503db4415d2f658a757d9d32bb68f3378ddd0/openai-1.59.9.tar.gz", hash = "sha256:ec1a20b0351b4c3e65c6292db71d8233515437c6065efd4fd50edeb55df5f5d2", size = 347134 }
sdist = { url = "https://files.pythonhosted.org/packages/d4/2d/9bdf4435d7669b4d027d6d69b4ac82f6be76153d9e90d3155d4224626a29/openai-1.60.0.tar.gz", hash = "sha256:7fa536cd4b644718645b874d2706e36dbbef38b327e42ca0623275da347ee1a9", size = 347844 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/07/b4/57f1954a4560092ad8c45f07ad183eab9c8e093e0a1db829f9b506b2d5d1/openai-1.59.9-py3-none-any.whl", hash = "sha256:61a0608a1313c08ddf92fe793b6dbd1630675a1fe3866b2f96447ce30050c448", size = 455527 },
{ url = "https://files.pythonhosted.org/packages/c0/53/782008d94f5f3141795e65bd7f87afaebb97e7516342299c1b1a08d5aaf8/openai-1.60.0-py3-none-any.whl", hash = "sha256:df06c43be8018274980ac363da07d4b417bd835ead1c66e14396f6f15a0d5dda", size = 456109 },
]
[[package]]
@ -3309,11 +3309,11 @@ wheels = [
[[package]]
name = "tzdata"
version = "2024.2"
version = "2025.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/34/943888654477a574a86a98e9896bae89c7aa15078ec29f490fef2f1e5384/tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc", size = 193282 }
sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a6/ab/7e5f53c3b9d14972843a647d8d7a853969a58aecc7559cb3267302c94774/tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd", size = 346586 },
{ url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 },
]
[[package]]