# Project export: Contract Simplifier

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: AI-powered contract risk analyzer that uses LangGraph, ChromaDB, Bright Data, FastAPI, and React to assess vendor risks in real time before agreements complete with live streaming insights.
- Devpost: https://devpost.com/software/contract-simplifier
- GitHub: https://github.com/sanjay872/calhacks-12
- Video: https://www.youtube.com/embed/yeSOO3tDSdQ?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 3 GitHub contributor(s) — Sanjay Sakthivel (15 commits), Aman Nindra (14 commits), Rajbir Longia (7 commits)

## Devpost submission (written by the team)

### Overview

🌍

### Inspiration

Business contracts often carry hidden risks that can affect compliance, finances, or security — yet reviewing them manually is slow, subjective, and prone to oversight. Our team wanted to build an AI system that helps organizations evaluate vendor risk before signing a deal, in real time. We were inspired by the growing use of AI in due diligence and compliance automation and wanted to make risk intelligence accessible even to small teams without requiring a dedicated legal department. 🧠 What We Built Contract Simplifier is a real-time, AI-powered risk analysis system that identifies, evaluates, and visualizes potential vendor risks before an organization enters into a business contract. It combines LangGraph, ChromaDB, Bright Data, FastAPI, and React to form an intelligent end-to-end pipeline: User enters a query such as “Analyze Tesla with high criticality.” The backend orchestrates multiple components: LangGraph controls the AI workflow as a state machine. Bright Data scrapes credible company data in real time. ChromaDB stores and retrieves context embeddings. OpenAI GPT-4 analyzes risk factors and scores vendors. The React frontend displays a live-streaming visualization of each analysis stage, showing how data moves from collection to insight. The React frontend displays a live-streaming visualization of each analysis stage, showing how data moves from collection to insight. This flow allows users to see the reasoning behind AI-driven conclusions, increasing transparency and trust. ⚙️ How We Built It We followed a modular micro-frontend and microservice approach: Backend (FastAPI + LangGraph): Designed a pipeline with multiple “nodes” for classification, scraping, validation, and LLM evaluation. Implemented streaming responses via Server-Sent Events (SSE) for real-time updates. Integrated ChromaDB as a semantic memory layer for contextual recall. Backend (FastAPI + LangGraph): Designed a pipeline with multiple “nodes” for classification, scraping, validation, and LLM evaluation. Implemented streaming responses via Server-Sent Events (SSE) for real-time updates. Integrated ChromaDB as a semantic memory layer for contextual recall. Frontend (React + Tailwind CSS): Developed a split-screen interface — chat panel on the left, risk visualization on the right. Used animated progress indicators to show each step of the risk workflow. Rendered color-coded risk scores with smooth transitions and responsive layout. Frontend (React + Tailwind CSS): Developed a split-screen interface — chat panel on the left, risk visualization on the right. Used animated progress indicators to show each step of the risk workflow. Rendered color-coded risk scores with smooth transitions and responsive layout. Data Layer: Leveraged Bright Data for trusted source collection. Applied domain-based filtering to prioritize credible sites (e.g., .gov, .edu, Bloomberg, Reuters). Data Layer: Leveraged Bright Data for trusted source collection. Applied domain-based filtering to prioritize credible sites (e.g., .gov, .edu, Bloomberg, Reuters). 🔍 Key Features AI Risk Scoring across four critical dimensions: 🏦 Financial Risk 🔐 Security Risk 📉 Reputation Risk 🧩 Resilience Strength AI Risk Scoring across four critical dimensions: 🏦 Financial Risk 🔐 Security Risk 📉 Reputation Risk 🧩 Resilience Strength Streaming Visualization: View live updates of the analysis pipeline. Streaming Visualization: View live updates of the analysis pipeline. Source Verification: Automatically filters unreliable or duplicate data. Source Verification: Automatically filters unreliable or duplicate data. Vector Search with ChromaDB: Enhances context relevance for LLM queries. Vector Search with ChromaDB: Enhances context relevance for LLM queries. Smart Classification: Detects whether the user request is a risk query or general chat. Smart Classification: Detects whether the user request is a risk query or general chat. 🧩 Architecture Overview 💡 What We Learned AI pipelines benefit from clear state management. LangGraph helped us structure complex workflows that involved multiple data sources and LLM reasoning stages. Streaming enhances user trust. Showing every step of analysis makes AI decisions more explainable and engaging. Data credibility is crucial. Many scraped sources are unreliable, so integrating domain verification was key. Frontend performance tuning matters. Handling SSE in React required careful optimization to avoid UI lag during real-time updates. Cross-team collaboration is smoother with modular design. Each team member could iterate independently on backend, frontend, or AI pipeline. 🧠 Challenges We Faced Latency management: AI and web scraping operations can be slow, so we used asynchronous FastAPI tasks and caching. LLM consistency: Different runs could produce slightly varied risk ratings, so we implemented post-processing checks. Data validation: Ensuring only credible, non-duplicate sources reached the model required multiple iterations of our filtering logic. Frontend synchronization: Coordinating the live streaming events with changing backend states was initially tricky but solved using an event-driven architecture. 🚀 Impact The system demonstrates how AI can act as an assistant for contract risk evaluation — performing tasks that would normally take analysts hours. By providing real-time transparency, contextual memory, and automated reasoning, Contract Simplifier has the potential to help organizations reduce decision-making time and improve compliance readiness. 🧰 Tech Stack 🧪 Future Enhancements Batch contract analysis for multiple vendors Integration with CRM or ERP systems Historical risk trend tracking PDF report export Multilingual support Custom risk factor weighting 🤝 Team Sanjay Sakthivel — AI & Backend (LangGraph, ChromaDB, FastAPI) Aman Nindra — Frontend & Streaming & Database Integration (React, Tailwind, Firebase, AWS) Rajbir Longia — Web Scraping & API Integration (Bright Data, REST) ❤️ Closing Thoughts We built Contract Simplifier to show how AI can transform due diligence from a static checklist into a dynamic, explainable, and data-driven process. It’s not just about predicting risk — it’s about understanding it in real time. “Contracts define trust. Our AI ensures that trust is measurable.”

## README (from the GitHub repository)

# 🛡️ Contract Simplifier

A real-time AI-powered contract risk analysis system that helps organizations assess vendor risks before entering business contracts. Built with LangGraph, FastAPI, and React with live streaming capabilities.

![License](https://img.shields.io/badge/license-MIT-blue.svg)
![Python](https://img.shields.io/badge/python-3.8%2B-blue)
![React](https://img.shields.io/badge/react-18.0%2B-blue)

## 📋 Table of Contents

- [Features](#features)
- [Architecture](#architecture)
- [Demo](#demo)
- [Installation](#installation)
- [Usage](#usage)
- [API Documentation](#api-documentation)
- [Project Structure](#project-structure)
- [Configuration](#configuration)
- [Contributing](#contributing)
- [License](#license)

## ✨ Features

### 🤖 AI-Powered Analysis
- **Intelligent Classification**: Automatically detects risk analysis requests vs. general queries
- **Multi-Source Data Gathering**: Fetches information from multiple web sources
- **Source Verification**: Validates source credibility and filters unreliable information
- **Vector Database Integration**: Stores and retrieves relevant context using ChromaDB
- **LLM Risk Scoring**: Comprehensive risk assessment across multiple dimensions

### 📊 Real-Time Processing
- **Live Streaming UI**: Watch the analysis pipeline execute in real-time
- **Stage-by-Stage Updates**: See each processing step as it happens
- **Progress Indicators**: Visual feedback for every stage of analysis
- **Status Messages**: Detailed information about what's being processed

### 🎨 Modern Interface
- **Split-Screen Design**: Chat on the left, analysis visualization on the right
- **Responsive Components**: Beautiful UI built with React and Tailwind CSS
- **Color-Coded Risk Scores**: Easy-to-understand visual risk indicators
- **Smooth Animations**: Professional transitions and loading states

### 🔒 Comprehensive Risk Assessment
Analyzes vendors across four key dimensions:
- **Financial Risk** (1-5): Stability, revenue, debt, market position
- **Security Risk** (1-5): Data breaches, vulnerabilities, compliance
- **Reputation Risk** (1-5): Legal issues, public perception, controversies
- **Resilience Strength** (1-5): Recovery capability, partnerships, certifications

## 🏗️ Architecture

```
┌─────────────┐         ┌──────────────┐         ┌─────────────┐
│   React     │ ◄─SSE──►│   FastAPI    │ ◄──────►│  LangGraph  │
│   Frontend  │         │   Backend    │         │   Pipeline  │
└─────────────┘         └──────────────┘         └─────────────┘
                               │                         │
                               ▼                         ▼
                        ┌──────────────┐         ┌─────────────┐
                        │  Web Scraper │         │  ChromaDB   │
                        └──────────────┘         └─────────────┘
                               │                         │
                               ▼                         ▼
                        ┌──────────────┐         ┌─────────────┐
                        │   OpenAI     │         │   Vector    │
                        │   LLM API    │         │   Storage   │
                        └──────────────┘         └─────────────┘
```

### Tech Stack

**Backend:**
- Python 3.8+
- FastAPI - Modern web framework with async support
- LangGraph - State machine for AI workflows
- LangChain - LLM orchestration
- ChromaDB - Vector database for semantic search
- OpenAI GPT-4 - Language model for analysis

**Frontend:**
- React 18+
- Tailwind CSS - Utility-first styling
- Lucide Icons - Beautiful icon set
- Server-Sent Events (SSE) - Real-time streaming

## 🎥 Demo

### Chat Interface
```
User: Analyze Tesla with high criticality
Assistant: 📊 Risk Report for Tesla
• Financial Risk: 2/5
• Security Risk: 3/5
• Reputation Risk: 2/5
• Resilience Strength: 4/5
→ Recommendation: PROCEED WITH PROTECTIONS
```

### Real-Time Processing View
```
✓ Classifying request...
✓ Extracting company details...
⟳ Fetching external data...
  └─ Found 15 sources
⟳ Verifying sources...
  └─ Verified 12 high-trust sources
⟳ Generating risk analysis...
```

## 🚀 Installation

### Prerequisites
- Python 3.8 or higher
- Node.js 16 or higher
- OpenAI API key
- Git

### Backend Setup

1. **Clone the repository**
```bash
git clone https://github.com/yourusername/contract-risk-analyzer.git
cd contract-risk-analyzer
```

2. **Create virtual environment**
```bash
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
```

3. **Install Python dependencies**
```bash
cd backend
pip install -r requirements.txt
```

4. **Set up environment variables**
```bash
cp .env
```

Edit `.env` and add your API keys:
```env
OPENAI_API_KEY=your_openai_api_key_here
CHROMA_HOST=chroma_url
CHROMA_PORT=chroma_port
BRIGHT_DATA_KEY=your_bright_data_key_api
```

5. **Initialize ChromaDB**
Run ChromaDB using Dockers

6. **Run the backend**
```bash
uvicorn main:app --reload --port 8000
```

Backend will be available at `http://localhost:8000`

### Frontend Setup

1. **Navigate to frontend directory**
```bash
cd ../frontend
```

2. **Install dependencies**
```bash
npm install
# or
yarn install
```

3. **Configure backend URL**

Edit `src/config.js` if needed:
```javascript
export const BACKEND_URL = 'http://localhost:8000';
```

4. **Run the development server**
```bash
npm start
# or
yarn start
```
Frontend will be available at `http://localhost:3000`

## 📖 Usage

### Advanced Risk Analysis

1. Open the application in your browser
2. Type in the chat: `"Analyze Tesla with high criticality"`
3. Watch the real-time processing on the right panel
4. Review the comprehensive risk report

### General Questions

Ask general questions about contracts or the tool:
- `"What can you do?"`
- `"What is contract risk?"`
- `"How do you analyze companies?"`

### API Usage

#### Non-Streaming Endpoint
```bash
curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user123",
    "message": "Analyze Apple with medium criticality"
  }'
```

#### Streaming Endpoint
```bash
curl -N -X POST http://localhost:8000/chat/stream \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user123",
    "message": "Analyze Microsoft with high criticality"
  }'
```

## 📚 API Documentation

### Endpoints

#### `POST /chat/stream`
Real-time streaming endpoint for chat interactions.

**Request:**
```json
{
  "user_id": "string",
  "message": "string"
}
```

**Response:** Server-Sent Events (SSE)
```javascript
// Stage start event
data: {"type": "stage_start", "stage": "fetch_external_data", "message": "Searching..."}

// Stage complete event
data: {"type": "stage_complete", "stage": "fetch_external_data", "message": "Found 15 sources"}

// Final result event
data: {"type": "final", "mode": "risk_report", "assistant_reply": "...", "risk_report": {...}}

// Stream end
data: {"type": "done"}
```

#### `POST /chat`
Non-streaming endpoint for simple requests.

**Request:**
```json
{
  "userId": "string",
  "userMessage": "string"
}
```

**Response:**
```json
{
  "success": true,
  "response": "string",
  "full_state": {
    "assistant_reply": "string",
    "risk_report": {...}
  }
}
```

#### `GET /health`
Health check endpoint.

**Response:**
```json
{
  "status": "healthy"
}
```

## 📁 Project Structure

```
contract-risk-analyzer/
├── backend/
│   ├── main.py                    # FastAPI application
│   ├── requirements.txt           # Python dependencies
│   ├── graphs/
│   │   └── contractbot.py         # LangGraph workflow
│   ├── utils/
│   │   ├── stream_runner.py       # Streaming pipeline
│   │   ├── webScraper.py          # Web scraping utilities
│   │   └── jsonConverter.py       # LLM JSON helpers
│   └── db/
│       └── chromaClient.py        # Vector database client
├── frontend/
│   ├── src/
│   │   ├── App.js                 # Main React component
│   │   ├── components/
│   │   │   ├── ChatPanel.js       # Chat interface


[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 112 recognized source files, 2732 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- Firebase (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- LangChain (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- AWS (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 762)

```
.gitignore
diagnose_s3.py
dsadasddas.text
FIREBASE_CONTRACT_SAVE_GUIDE.md
latex_converter.py
main.py
py_secure.py
py.py
README.md
requirements.txt
S3_UID_FILE_STRUCTURE.md
server/.gitignore
server/awsS3.py
server/db/__init__.py
server/db/chromaClient.py
server/graphs/__init__.py
server/graphs/contractbot.py
server/graphs/riskAnalysisGraph.py
server/main.py
server/README.md
server/requirements.txt
server/utils/__init__.py
server/utils/htmlParser.py
server/utils/jsonConverter.py
server/utils/stream_runner.py
server/utils/webScraper.py
web/.gitignore
web/.vite/deps/_metadata.json
web/.vite/deps/package.json
web/components.json
web/ERROR_FIX.md
web/eslint.config.js
web/FIREBASE_BACKEND_SETUP.md
web/index.html
web/package.json
web/public/nutrient-viewer-lib/chunk-848-386a1b3b5aa7cf16.js
web/public/nutrient-viewer-lib/chunk-core-worker-809c10ee3a144cbf.js
web/public/nutrient-viewer-lib/chunk-gdpicture-371ed9f786a40c22.js
web/public/nutrient-viewer-lib/chunk-gdpicture-worker-78cba5d4a2efeaf2.js
web/public/nutrient-viewer-lib/chunk-lazy-sha-ccfdc5c2881671e9.js
web/public/nutrient-viewer-lib/chunk-locale-ar-79c161ff0813b95f.js
web/public/nutrient-viewer-lib/chunk-locale-cs-c4e6766e147aa7e1.js
web/public/nutrient-viewer-lib/chunk-locale-cy-3ee08987f4bc6626.js
web/public/nutrient-viewer-lib/chunk-locale-da-2354b0c7ec7a5ca5.js
web/public/nutrient-viewer-lib/chunk-locale-de-9da8802f7da57346.js
web/public/nutrient-viewer-lib/chunk-locale-el-d3ec2f635d174bc2.js
web/public/nutrient-viewer-lib/chunk-locale-en-GB-4a098b14485912aa.js
web/public/nutrient-viewer-lib/chunk-locale-es-436546f8bf7429ed.js
web/public/nutrient-viewer-lib/chunk-locale-fi-6b7d804d35053900.js
web/public/nutrient-viewer-lib/chunk-locale-fr-9e5afdf53d53038a.js
web/public/nutrient-viewer-lib/chunk-locale-fr-CA-a511827dc67c387a.js
web/public/nutrient-viewer-lib/chunk-locale-he-83dc650ca67b4216.js
web/public/nutrient-viewer-lib/chunk-locale-hr-d735346e849b6fd3.js
web/public/nutrient-viewer-lib/chunk-locale-id-a4ea493347192e86.js
web/public/nutrient-viewer-lib/chunk-locale-it-f4ea1063d7e1555d.js
web/public/nutrient-viewer-lib/chunk-locale-ja-786c1c08bc0f2882.js
web/public/nutrient-viewer-lib/chunk-locale-ko-8b36e111f6103394.js
web/public/nutrient-viewer-lib/chunk-locale-ms-2aa576756a6f76f1.js
web/public/nutrient-viewer-lib/chunk-locale-nb-NO-ac9213c77c26322f.js
web/public/nutrient-viewer-lib/chunk-locale-nl-1e873f574695369f.js
web/public/nutrient-viewer-lib/chunk-locale-pl-769ff721a79e1f26.js
web/public/nutrient-viewer-lib/chunk-locale-pt-8ac54512f4ef4292.js
web/public/nutrient-viewer-lib/chunk-locale-pt-PT-6b79a9f48f912de5.js
web/public/nutrient-viewer-lib/chunk-locale-ru-e7eaa4f44b936f20.js
web/public/nutrient-viewer-lib/chunk-locale-sk-373e6f2dcad0a63d.js
web/public/nutrient-viewer-lib/chunk-locale-sl-f86c0cdb9cc53e54.js
web/public/nutrient-viewer-lib/chunk-locale-sv-55e4633f1f183cf0.js
web/public/nutrient-viewer-lib/chunk-locale-th-0064d9fb488e6cb7.js
web/public/nutrient-viewer-lib/chunk-locale-tr-9b065ecddc11ef73.js
web/public/nutrient-viewer-lib/chunk-locale-uk-6f4e6652d14bf6d1.js
web/public/nutrient-viewer-lib/chunk-locale-zh-Hans-801dec5b8f7e26fc.js
web/public/nutrient-viewer-lib/chunk-locale-zh-Hant-a7305e1216894562.js
web/public/nutrient-viewer-lib/chunk-offscreen-renderer-worker-aa3bb73c3644e514.js
web/public/nutrient-viewer-lib/chunk-server-86422be65c5bd5a3.js
web/public/nutrient-viewer-lib/chunk-server-instant-0fb6cafbf6ff0c5b.js
web/public/nutrient-viewer-lib/chunk-server-rest-e7a19a39aa5ba5b8.js
web/public/nutrient-viewer-lib/chunk-standalone-ed36186f6288d7d3.js
web/public/nutrient-viewer-lib/chunk-standalone-server-68f7ebfde563fd5e.js
web/public/nutrient-viewer-lib/core-worker.js
web/public/nutrient-viewer-lib/dark-402cc98d3d69bff8.css
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/blazor.boot.json
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/BouncyCastle.Cryptography.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/DocumentFormat.OpenXml.Framework.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/DocumentFormat.OpenXml.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/dotnet.js
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/dotnet.js.map
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/dotnet.native.js
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/dotnet.native.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/dotnet.runtime.js
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/dotnet.runtime.js.map
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.API.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.barcode.1d.writer.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.barcode.2d.writer.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.CAD.DWG.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.CAD.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.Common.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.Document.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.Email.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.HTML.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.Imaging.Formats.Conversion.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.Imaging.Formats.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.Imaging.Rendering.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.Imaging.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.MSOfficeBinary.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.OpenDocument.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.OpenXML.Templating.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.OpenXML.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.PDF.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.RTF.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.14.SVG.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.JsonApi.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.PSPDFKit.Wasm.runtimeconfig.json
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.PSPDFKit.Wasm.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/GdPicture.NET.Wasm.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/icudt_CJK.dat
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/icudt_EFIGS.dat
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/icudt_no_CJK.dat
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/initDotnet.js
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/Microsoft.CSharp.wasm
web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/Newtonsoft.Json.wasm
[642 more files omitted for size]
```

### Dependencies

- requirements.txt: boto3, chromadb, dotenv, fastapi, openai, pdfplumber, requests
- server/requirements.txt: boto3, bs4, chromadb, fastapi, langchain, langchain-openai, langgraph, openai, pydantic, python-dotenv, python-multipart, uvicorn
- web/package.json: @eslint/js@^9.36.0, @nutrient-sdk/viewer@^1.8.0, @tailwindcss/vite@^4.1.16, @types/node@^24.9.1, @types/react@^19.1.16, @types/react-dom@^19.1.9, @vitejs/plugin-react@^5.0.4, class-variance-authority@^0.7.1, clsx@^2.1.1, eslint@^9.36.0, eslint-plugin-react-hooks@^5.2.0, eslint-plugin-react-refresh@^0.4.22, firebase@^12.4.0, globals@^16.4.0, lucide-react@^0.548.0, pandoc@^0.2.0, pdfjs-dist@^5.4.296, react@^19.2.0, react-dom@^19.1.1, react-icons@^5.5.0, react-pdf@^10.2.0, react-router-dom@^7.9.4, rollup-plugin-copy@^3.5.0, tailwind-merge@^3.3.1, tailwindcss@^4.1.16, tw-animate-css@^1.4.0, typescript@~5.9.3, typescript-eslint@^8.45.0, vite@^7.1.7

### Recent commits (newest first)

- Merge branch 'main' of https://github.com/sanjay872/calhacks-12
- updated readme
- Merge branch 'main' of https://github.com/sanjay872/calhacks-12
- Refactor CreateContract component to enhance risk analysis functionality. Introduce asynchronous message handling, integrate real-time processing stages, and improve UI layout with dedicated left and right panels. Update Left and Right components for better user interaction and display of risk assessment results.
- updated main in server
- Merge branch 'main' of https://github.com/sanjay872/calhacks-12
- ADDED STREAMER
- Database
- Merge branch 'main' of https://github.com/sanjay872/calhacks-12
- Remove awsS3.py and integrate S3 functionality into main.py. Implement file upload and listing features in the FastAPI server. Update requirements.txt to include boto3 and python-multipart. Enhance web app with PDF.js for document preview and add file upload capability in the Right component.
- work
- Backend
- Added the editor UI
- dsdas
- Merge remote changes and apply new deep blue and gold color scheme
- new UI changes
- Refactor CreateContract and Left components for improved functionality and UI. Removed unused imports, added auto-scroll feature in Left component, and enhanced user input handling.
- Merge branch 'main' of https://github.com/sanjay872/calhacks-12
- Add react-icons dependency and update CreateContract component
- Merge branch 'main' of https://github.com/sanjay872/calhacks-12

## Key source files (fetched from GitHub, selected and truncated for size)

### S3_UID_FILE_STRUCTURE.md

```markdown
# S3 File Organization by User UID

## Overview

Files in S3 are now organized by user UID in the structure:

```
calhacks3.0/
  ├── {UID_1}/
  │   ├── file1.pdf
  │   ├── file2.pdf
  │   └── file3.pdf
  ├── {UID_2}/
  │   ├── document1.pdf
  │   └── document2.pdf
  └── ...
```

## Backend API Endpoints

### 1. Upload File

**Endpoint:** `POST /upload_file`

**Parameters:**

- `file`: The file to upload (multipart/form-data)
- `user_id`: User's UID (form data)

**Response:**

```json
{
  "success": true,
  "file_name": "contract.pdf",
  "s3_path": "abc123/contract.pdf",
  "file_type": "application/pdf",
  "file_size": 12345,
  "user_id": "abc123",
  "message": "File uploaded successfully to S3 at abc123/contract.pdf"
}
```

**Example (Python):**

```python
# The backend automatically handles this
s3_path = s3_client.upload_file(temp_file_path, 'calhacks3.0', 'document.pdf', uid='abc123')
# Uploads to: calhacks3.0/abc123/document.pdf
```

### 2. List Files

**Endpoint:** `GET /list_files?user_id={uid}`

**Query Parameters:**

- `user_id` (optional): User's UID to filter files
  - If provided: Returns files only for that user
  - If omitted: Returns all files in bucket

**Response:**

```json
{
  "files": [
    {
      "name": "contract.pdf",
      "full_path": "abc123/contract.pdf",
      "size": 12345,
      "last_modified": "2025-01-15T10:30:00"
    }
  ],
  "user_id": "abc123",
  "count": 1
}
```

## Frontend Usage

### 1. Upload File with User UID

```typescript
import { uploadFile } from "../services/backend";
import { getUser } from "../utils/auth-helpers";

const handleUpload = async (file: File) => {
  const user = getUser();
  if (!user?.uid) {
    alert("Please sign in");
    return;
  }

  const formData = new FormData();
  formData.append("file", file);

  const result = await uploadFile(formData, user.uid);
  console.log("Uploaded to:", result.s3_path);
  // Output: "abc123/contract.pdf"
};
```

### 2. List Files for Current User

```typescript
import { listFiles } from "../services/backend";
import { getUserUid } from "../utils/auth-helpers";

const loadMyFiles = async () => {
  const uid = getUserUid();
  if (!uid) {
    console.error("User not signed in");
    return;
  }

  const response = await listFiles(uid);
  console.log(`Found ${response.count} files`);
  console.log(response.files);
};
```

### 3. List All Files (Admin)

```typescript
const loadAllFiles = async () => {
  const response = await listFiles(); // No UID = all files
  console.log(response.files);
};
```

## S3Client Methods

### upload_file(file_path, bucket_name, file_name, uid=None)

Uploads a file to S3

- **With UID:** Uploads to `bucket/uid/filename`
- **Without UID:** Uploads to `bucket/filename`

```python
# Upload for specific user
s3_client.upload_file('temp.pdf', 'calhacks3.0', 'contract.pdf', uid='user123')
# Result: calhacks3.0/user123/contract.pdf

# Upload without user folder
s3_client.upload_file('temp.pdf', 'calhacks3.0', 'public.pdf')
# Result: 
[truncated — 2489 more characters]
```

### FIREBASE_CONTRACT_SAVE_GUIDE.md

```markdown
# Firebase Contract Metadata Save - Implementation Complete

## ✅ What Was Implemented

### 1. Firebase Realtime Database Setup (`firebase.ts`)

- ✅ Imported `getDatabase` from `firebase/database`
- ✅ Added `databaseURL` to Firebase config
- ✅ Initialized and exported `database` instance

### 2. Contract Data Save Function (`backend.ts`)

- ✅ Fixed syntax error (missing comma in parameters)
- ✅ Implemented `contractData()` function to save to Firebase
- ✅ Uses `push()` to generate unique contract IDs
- ✅ Saves data under: `users/{userID}/{contractID}/`

### 3. Upload Flow (`right.tsx`)

- ✅ Added form validation for all fields
- ✅ Fixed undefined `result` variable
- ✅ Calls `contractData()` after file selection
- ✅ Added "Save Contract to Firebase" button
- ✅ Shows success message with contract ID
- ✅ Clears form after successful save
- ✅ Shows uploaded file confirmation

## Data Structure in Firebase

```
users/
  └── {userID}/
      └── {contractID-auto-generated}/
          ├── contractName: "My Contract"
          ├── Date: "2025-01-15"
          ├── Fellow: "Company Name"
          ├── fileName: "contract.pdf"
          └── createdAt: "2025-01-15T10:30:00.000Z"
```

## How to Use

### Step 1: Upload PDF File

1. Click "Choose File" and select a PDF
2. File automatically uploads to S3: `calhacks3.0/{uid}/filename.pdf`
3. Green checkmark appears: "✓ File uploaded: filename.pdf"

### Step 2: Fill Contract Details

1. **Contract Name**: Enter the contract title
2. **Contract Date**: Select date from calendar
3. **Contract Signatory**: Enter the other party's name (Fellow)

### Step 3: Save to Firebase

1. Click "Save Contract to Firebase" button
2. Button is disabled until all fields are filled
3. Success alert shows:
   - Contract name
   - File name
   - Firebase contract ID

### Step 4: Verify in Firebase Console

1. Go to Firebase Console: https://console.firebase.google.com
2. Select project: `calhacks-bb6c1`
3. Go to "Realtime Database"
4. Navigate to: `users/{your-uid}/{contract-id}`
5. Verify data is saved with all fields

## Example Data Flow

**User Action:**

```
1. Select file: contract.pdf
2. Enter name: "Service Agreement"
3. Enter date: "2025-01-15"
4. Enter signatory: "Acme Corp"
5. Click "Save Contract to Firebase"
```

**S3 Storage:**

```
calhacks3.0/
  └── user123abc/
      └── contract.pdf  ✓ Already saved
```

**Firebase Realtime Database:**

```json
{
  "users": {
    "user123abc": {
      "-NxYzAbc123": {
        "contractName": "Service Agreement",
        "Date": "2025-01-15",
        "Fellow": "Acme Corp",
        "fileName": "contract.pdf",
        "createdAt": "2025-01-15T10:30:00.000Z"
      }
    }
  }
}
```

## Error Handling

### Missing File

- Alert: "Please select a file to upload"

### Missing Details

- Alert: "Please fill in all contract details"

### Not Signed In

- Alert: "Please sign in to upload files"

### Firebase Error

- Alert: "Failed to save contract data. Check console for details."
- Console sh
[truncated — 2815 more characters]
```

### requirements.txt

```
fastapi 
pdfplumber 
dotenv
boto3
chromadb
openai
requests
```

### server/requirements.txt

```
fastapi
uvicorn
chromadb
langchain
langgraph
langchain-openai
openai
pydantic
python-dotenv
bs4
boto3
python-multipart
```

### web/package.json

```
{
  "name": "web",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "@nutrient-sdk/viewer": "^1.8.0",
    "@tailwindcss/vite": "^4.1.16",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "firebase": "^12.4.0",
    "lucide-react": "^0.548.0",
    "pandoc": "^0.2.0",
    "pdfjs-dist": "^5.4.296",
    "react": "^19.2.0",
    "react-dom": "^19.1.1",
    "react-icons": "^5.5.0",
    "react-pdf": "^10.2.0",
    "react-router-dom": "^7.9.4",
    "tailwind-merge": "^3.3.1",
    "tailwindcss": "^4.1.16"
  },
  "devDependencies": {
    "@eslint/js": "^9.36.0",
    "@types/node": "^24.9.1",
    "@types/react": "^19.1.16",
    "@types/react-dom": "^19.1.9",
    "@vitejs/plugin-react": "^5.0.4",
    "eslint": "^9.36.0",
    "eslint-plugin-react-hooks": "^5.2.0",
    "eslint-plugin-react-refresh": "^0.4.22",
    "globals": "^16.4.0",
    "rollup-plugin-copy": "^3.5.0",
    "tw-animate-css": "^1.4.0",
    "typescript": "~5.9.3",
    "typescript-eslint": "^8.45.0",
    "vite": "^7.1.7"
  }
}

```

### web/.vite/deps/package.json

```
{
  "type": "module"
}

```

### web/public/nutrient-viewer-lib/gdpicture-aa63976b/aot/package.json

```
{ "type":"module" }
```

### web/public/nutrient-viewer-lib/gdpicture-aa63976b/jit/package.json

```
{ "type":"module" }
```

### main.py

```python
from typing import Union

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import pdfplumber
import os
from awsS3 import S3Client

from dotenv import load_dotenv

load_dotenv()

app = FastAPI()

# Configure CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:5174",
        "http://localhost:5173",
        "http://127.0.0.1:5174",
        # "http://127.0.0.1:5173",
    ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

s3_client = S3Client()

@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/contracts")
def read_item(item_id: int, q: Union[str, None] = None):
    return {"item_id": item_id, "q": q}

@app.get("/list_files")
def list_files():
    files = s3_client.list_files('calhacks3.0')
    return {"files": files}
```

### server/main.py

```python
from fastapi import FastAPI, Body, File, UploadFile
from fastapi.middleware.cors import CORSMiddleware
from graphs.riskAnalysisGraph import riskAnalysisGraph
from utils.webScraper import get_company_data
from graphs.contractbot import handle_user_message

from typing import Union
import tempfile
import os

from fastapi.responses import StreamingResponse, JSONResponse
from typing import Generator
import json
from utils.stream_runner import run_pipeline_stream

from awsS3 import S3Client
from dotenv import load_dotenv

load_dotenv()

app = FastAPI(title="AI Service", version="1.0")



app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

s3_client = S3Client()

# @app.get("/riskanalysis")
# def read_root(payload: dict= Body(...)):
#     companyName=payload.get("companyName","")
#     criticality=payload.get("criticality","Medium")
#     return riskAnalysisGraph(companyName,criticality)

# @app.get("/search")
# def read_item(payload: dict= Body()):
#     return get_company_data(payload.get('companyName',""))

# @app.post("/chat")
# def chatBot(payload: dict= Body(...)):
#     userId=payload.get("userId")
#     userMessage=payload.get("userMessage")
#     return handle_user_message(userId,userMessage)



@app.get("/list_files")
def list_files_endpoint(user_id: str = None):
    """
    List files for a specific user
    Query param: user_id - User's UID to filter files
    Example: /list_files?user_id=abc123
    """
    files = s3_client.list_files('calhacks3.0', uid=user_id)
    return {"files": files, "user_id": user_id, "count": len(files)}




@app.post("/upload_file")
async def upload_file(file: UploadFile = File(...), user_id: str = Body(...), contract_name: str = Body(...), contract_date: str = Body(...), contract_signatory: str = Body(...)):
    """
    Upload a file to S3 under user's UID folder
    Form data:
    - file: The file to upload
    - user_id: User's UID
    """
    try:
        # Create a temporary file to save the upload
        with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(file.filename)[1]) as temp_file:
            # Read file content and write to temp file
            content = await file.read()
            temp_file.write(content)
            temp_file_path = temp_file.name
        
        # Upload to S3 with user_id as prefix (uses the updated method)
        print(f"Uploading file {file.filename} for user {user_id}")
        s3_path = s3_client.upload_file(temp_file_path, 'calhacks3.0', file.filename, uid=user_id)
        
        # Clean up temporary file
        os.unlink(temp_file_path)
        
        return {
            "success": True,
            "file_name": file.filename,
            "s3_path": s3_path,
            "file_type": file.content_type,
            "file_size": len(content),
            "user_id": user_id,
            "message": f"File uploaded successfully to S3 at {s3_path}"
        }
        
        
        
        
        
    except Exception as e:
        print(f"Error uploading file: {str(e)}")
        return {
            "success": False,
            "error": str(e),
            "message": "Failed to upload file"
        }

def sse_event(data: dict) -> str:
    """Format data as Server-Sent Events"""
    return f"data: {json.dumps(data)}\n\n"

@app.get("/")
def read_root():
    return {"message": "Risk Analysis API", "version": "1.0"}

@app.post("/riskanalysis")
def risk_analysis(payload: dict = Body(...)):
    """Non-streaming risk analysis endpoint"""
    companyName = payload.get("companyName", "")
    criticality = payload.get("criticality", "Medium")
    return riskAnalysisGraph(companyName, criticality)

@app.post("/search")
def search_company(payload: dict = Body(...)):
    """Search for company data"""
    return get_company_data(payload.get('companyName', ""))

@app.post("/chat")
def chatBot(payload: dict = Body(...)):
    """Non-streaming chat endpoint"""
    userId = payload.get("userId")
    userMessage = payload.get("userMessage")
    return handle_user_message(userId, userMessage)

@app.post("/chat/stream")
async def chat_stream(payload: dict = Body(...)):
    """
    Streaming chat endpoint with real-time progress updates.
    
    Request body:
    {
      "user_id": "sanjay123",
      "message": "analyze Tesla with high criticality"
    }
    
    Returns: text/event-stream with progress events
    """
    
    user_id = payload.get("user_id", "anonymous")
    message = payload.get("message", "")
    
    if not message:
        return JSONResponse(
            status_code=400,
            content={"error": "Message is required"}
        )
    
    def event_generator() -> Generator[str, None, None]:
        """Generate SSE events from the pipeline"""
        try:
            for event in run_pipeline_stream(user_id, message):
                yield sse_event(event)
                
            # Send completion signal
            yield sse_event({"type": "done"})
            
        except Exception as e:
            import traceback
            yield sse_event({
                "type": "error",
                "message": str(e),
                "traceback": traceback.format_exc()
            })
    
    return StreamingResponse(
        event_generator(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Accel-Buffering": "no"  # Disable buffering in nginx
        }
    )

@app.get("/health")
def health_check():
    """Health check endpoint"""
    return {"status": "healthy"}
```

[91 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]