Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Changelog

All notable changes to the Receipt Printer Task Manager project will be documented in this file.

## [Unreleased] - 2025-01-09

### Added
- **Setup Validation Script** (`setup_validation.py`)
- Comprehensive dependency checking
- Environment variable validation
- Database connectivity testing
- Automatic `.env` template generation
- Clear setup guidance and error messages

### Fixed
- **Database Initialization**: Fixed missing `_create_tables()` call in TaskDatabase constructor
- **Missing Dependencies**: Added all required dependencies to `requirements.txt`
- `reportlab` for PDF generation
- `Pillow` for image processing
- `python-escpos` for thermal printer support
- `imgkit` and `selenium` for HTML to image conversion
- `pdf2image` for PDF to image conversion

### Improved
- **Enhanced CLI Experience** in `main.py`
- Better user prompts and examples
- Input validation and error handling
- Interactive confirmation for outputs and printing
- Graceful error handling with helpful messages
- Proper exit codes for scripting

- **Better Error Handling** in `agent.py`
- Database initialization error handling
- Individual task save error handling
- More informative error messages

- **Updated Documentation**
- Improved installation instructions
- Added dependency information
- Updated usage examples with setup validation

### Technical Improvements
- Added proper exception handling throughout the codebase
- Improved user experience with better prompts and feedback
- Added validation for essential requirements before execution
- Enhanced error messages with actionable suggestions

### Breaking Changes
None - all changes are backward compatible.

### Migration Guide
1. Run `pip install -r requirements.txt` to install new dependencies
2. Run `python setup_validation.py` to validate your setup
3. Follow any recommendations from the validation script

---

## Previous Versions
This changelog starts from the current improvements. Previous version history was not tracked.
36 changes: 31 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ cd receipt-printer-tasks
# Install dependencies
pip install -r requirements.txt

# Set up environment variables
cp .env.example .env
# Validate setup and create .env template
python setup_validation.py

# Edit .env with your API keys
# (A template will be created automatically)
```

## Configuration
Expand All @@ -35,16 +37,21 @@ Required environment variables:

## Usage

### Extract tasks from Gmail
### Validate setup (recommended first step)
```bash
python agent.py
python setup_validation.py
```

### Create a task from text
```bash
python main.py
```

### Extract tasks from Gmail
```bash
python agent.py
```

### Use Arcade tools
```bash
python tools.py
Expand All @@ -58,9 +65,28 @@ python setup_database.py
## Requirements

- Python 3.8+
- Thermal receipt printer (USB)
- Thermal receipt printer (USB) - optional
- API keys for OpenAI and Arcade.dev

### Dependencies

**Required:**
- `openai` - AI task processing
- `python-dotenv` - Environment configuration
- `pydantic` - Data validation
- `agents` & `arcadepy` - AI agent framework
- `libsql-experimental` - Database connectivity

**Optional (for enhanced features):**
- `reportlab` - PDF generation
- `Pillow` - Image processing
- `python-escpos` - Thermal printer support
- `imgkit` + `wkhtmltopdf` - HTML to image conversion
- `selenium` - Web-based image generation
- `pdf2image` - PDF to image conversion

The setup validation script will check all dependencies and provide installation guidance.

## License

MIT License - see LICENSE file for details.
28 changes: 19 additions & 9 deletions agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,13 @@ async def main():
print("=" * 50)

# Initialize database
db = TaskDatabase()
try:
db = TaskDatabase()
print("💾 Database initialized successfully")
except Exception as e:
print(f"❌ Database initialization failed: {e}")
print("💡 Run 'python setup_validation.py' to check your setup")
return

try:
# Get user email from environment or ask
Expand Down Expand Up @@ -132,14 +138,18 @@ async def main():
continue

# Add new task to database
db_task = TaskRecord(
name=task.name,
priority=task.priority,
due_date=task.due_date,
created_at=datetime.datetime.now().isoformat(),
)
db.add_task(db_task)
new_tasks.append(task)
try:
db_task = TaskRecord(
name=task.name,
priority=task.priority,
due_date=task.due_date,
created_at=datetime.datetime.now().isoformat(),
)
db.add_task(db_task)
new_tasks.append(task)
except Exception as e:
print(f" ⚠️ Failed to save task '{task.name}': {e}")
continue

# Print summary of database operations
if new_tasks:
Expand Down
193 changes: 144 additions & 49 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"""Simple CLI for AI-powered task extraction and printing."""

import os
import sys
from dotenv import load_dotenv
from src.task_card_generator import (
create_task_image,
Expand All @@ -16,67 +17,161 @@
load_dotenv()


def validate_setup():
"""Quick validation of essential requirements."""
missing_requirements = []

# Check OpenAI API key
if not os.getenv("OPENAI_API_KEY"):
missing_requirements.append("OPENAI_API_KEY environment variable")

# Check if we can import essential modules
try:
from src.task_card_generator import get_task_from_ai
except ImportError as e:
missing_requirements.append(f"Task generator module: {e}")

if missing_requirements:
print("❌ Setup validation failed:")
for req in missing_requirements:
print(f" - Missing: {req}")
print("\n💡 Run 'python setup_validation.py' for detailed setup check")
return False

return True

def get_user_input():
"""Get task description from user with better prompts."""
print("\nDescribe the task you need to complete:")
print("💡 Examples:")
print(" - 'Review the quarterly budget report'")
print(" - 'Call dentist to schedule appointment'")
print(" - 'Prepare presentation for Monday meeting'")
print()

while True:
task_description = input(">> ").strip()

if not task_description:
print("⚠️ Please enter a task description (or 'quit' to exit)")
continue

if task_description.lower() in ['quit', 'exit', 'q']:
return None

if len(task_description) < 3:
print("⚠️ Task description too short. Please be more specific.")
continue

return task_description

def main():
"""Main CLI entry point for task generation."""
print("=" * 50)
print("AI TASK GENERATOR")
print("🎯 AI TASK GENERATOR")
print("Turn your thoughts into actionable tasks")
print("=" * 50)

# Get user task description
print("\nDescribe the task you need to complete:")
task_description = input(">> ")

if not task_description.strip():
print("ERROR: Please enter a valid task description!")
return
# Validate setup
if not validate_setup():
return 1

# Get AI response
print("\n🤖 Processing with AI...")
ai_response = get_task_from_ai(task_description)

if not ai_response or ai_response.startswith("Error"):
print(f"ERROR: {ai_response or 'Failed to get response'}")
return

# Parse AI response
task_data = parse_ai_response(ai_response)

print(f"\n✅ Generated Task: {task_data['title']}")
print(f"📌 Priority: {task_data['priority']}")
print(f"📅 Due: {task_data.get('due_date', 'Today')}")
# Get user task description
task_description = get_user_input()
if not task_description:
print("👋 Goodbye!")
return 0

try:
# Get AI response
print("\n🤖 Processing with AI...")
ai_response = get_task_from_ai(task_description)

if not ai_response or ai_response.startswith("Error"):
print(f"❌ AI processing failed: {ai_response or 'No response received'}")
print("💡 Check your OpenAI API key and internet connection")
return 1

# Parse AI response
task_data = parse_ai_response(ai_response)

print(f"\n✅ Generated Task: {task_data['title']}")
print(f"📌 Priority: {task_data['priority']}")
print(f"📅 Due: {task_data.get('due_date', 'Today')}")

# Ask user if they want to proceed with outputs
print(f"\n📄 Create outputs? (PDF, image, print) [Y/n]: ", end="")
create_outputs = input().strip().lower()

if create_outputs in ['n', 'no']:
print("✅ Task created successfully (no outputs generated)")
return 0

# Create outputs
print("\n📄 Creating outputs...")

# Create PDF for viewing
pdf_path = create_task_pdf(task_data)
if pdf_path:
print(f" PDF saved: {pdf_path}")

# Create image for printing
image_path = create_task_html_image(task_data)
if not image_path:
# Fallback to PIL method
image_path = create_task_image(task_data)

if image_path:
print(f" Image saved: {image_path}")
# Create outputs
print("\n📄 Creating outputs...")
outputs_created = []

# Print if printer is available
# Create PDF for viewing
try:
print("\n🖨️ Sending to printer...")
print_to_thermal_printer(image_path)
print(" ✅ Printed successfully!")
pdf_path = create_task_pdf(task_data)
if pdf_path:
print(f" ✅ PDF saved: {pdf_path}")
outputs_created.append("PDF")
else:
print(f" ⚠️ PDF creation skipped (reportlab not available)")
except Exception as e:
print(f" ⚠️ Printing failed: {e}")
else:
print(" ❌ Could not create image")
print(f" ❌ PDF creation failed: {e}")

print("\n" + "=" * 50)
print("Task generation complete!")
print("=" * 50)
# Create image for printing
image_path = None
try:
image_path = create_task_html_image(task_data)
if not image_path:
# Fallback to PIL method
image_path = create_task_image(task_data)

if image_path:
print(f" ✅ Image saved: {image_path}")
outputs_created.append("Image")
else:
print(f" ⚠️ Image creation failed (check image dependencies)")
except Exception as e:
print(f" ❌ Image creation failed: {e}")

# Print if printer is available and image was created
if image_path:
print(f"\n🖨️ Print to thermal printer? [y/N]: ", end="")
should_print = input().strip().lower()

if should_print in ['y', 'yes']:
try:
print(" 🖨️ Sending to printer...")
print_to_thermal_printer(image_path)
print(" ✅ Printed successfully!")
outputs_created.append("Print")
except Exception as e:
print(f" ❌ Printing failed: {e}")
print(" 💡 Make sure your thermal printer is connected and configured")

# Summary
print(f"\n" + "=" * 50)
if outputs_created:
print(f"🎉 Task generation complete! Created: {', '.join(outputs_created)}")
else:
print("✅ Task generated (no outputs created)")
print("=" * 50)

return 0

except KeyboardInterrupt:
print("\n\n👋 Operation cancelled by user")
return 0
except Exception as e:
print(f"\n❌ Unexpected error: {e}")
print("💡 Run 'python setup_validation.py' to check your setup")
return 1


if __name__ == "__main__":
main()
exit_code = main()
sys.exit(exit_code)
Loading