feat: wire PDF and text file content into AI chat messages

PDF uploads were stored in S3 and had text extracted during upload, but
fetch_upload_images() filtered exclusively for image MIME types, so
document content never reached the AI.

- Add fetch_upload_documents() in storage_service.py to retrieve
  extracted_content for PDFs and text files
- Update ai_sessions.py chat endpoint to call both fetch_upload_images
  and fetch_upload_documents, injecting document text as context
- Add PDF text extraction in _generate_ai_description (pypdf)
- Add pypdf>=4.0.0 to requirements.txt
- Fix test_db teardown to avoid connection pool issues
- Add 5 tests for fetch_upload_documents

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-27 21:02:56 +00:00
parent 3cea949519
commit 11de850054
6 changed files with 324 additions and 12 deletions

View File

@@ -85,13 +85,25 @@ async def test_db() -> AsyncGenerator[AsyncSession, None]:
# Provide session to test
async with async_session_maker() as session:
yield session
# Ensure session is fully closed before teardown
await session.close()
# Dispose engine first so all pooled connections are released,
# then reconnect to perform the schema teardown cleanly.
await engine.dispose()
# Drop all tables after test (CASCADE for circular FKs)
async with engine.begin() as conn:
await conn.execute(sa.text("DROP SCHEMA public CASCADE"))
await conn.execute(sa.text("CREATE SCHEMA public"))
await engine.dispose()
teardown_engine = create_async_engine(
TEST_DATABASE_URL,
poolclass=NullPool,
echo=False,
)
try:
async with teardown_engine.begin() as conn:
await conn.execute(sa.text("DROP SCHEMA public CASCADE"))
await conn.execute(sa.text("CREATE SCHEMA public"))
finally:
await teardown_engine.dispose()
@pytest.fixture