- Add tool framework (BaseTool ABC, ToolRegistry, ToolContext/ToolResult) - Implement agentic loop in LLMFactory.stream_with_tools() with max_rounds and timeout - Add 9 Microsoft Graph tools: Calendar (3), Mail (3), Teams (1), Planner (2) - Add Graph Token Manager with Fernet encryption and auto-refresh - Add consent flow endpoints (start/callback/status/revoke) - Add admin tool management endpoints (list/toggle) - Add SSE tool events (tool_start, tool_result, tool_error) in chat endpoint - Frontend: ToolCallCard component, tool call tracking in chat store - Frontend: Admin Integrations tab with per-tool enable/disable - Frontend: Consent banner and M365 connect flow - Migration 008: tool_definitions, user_graph_tokens, message_tool_calls tables Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
26 lines
1.1 KiB
Python
26 lines
1.1 KiB
Python
"""
|
|
User Graph Token model - stores encrypted Microsoft Graph delegated tokens
|
|
"""
|
|
from sqlalchemy import Column, String, Boolean, DateTime, Text, ForeignKey
|
|
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
|
from sqlalchemy.orm import relationship
|
|
from app.database import Base
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
|
|
class UserGraphToken(Base):
|
|
"""Encrypted Graph API tokens per user"""
|
|
__tablename__ = "user_graph_tokens"
|
|
|
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True, index=True)
|
|
encrypted_access_token = Column(Text, nullable=False)
|
|
encrypted_refresh_token = Column(Text, nullable=False)
|
|
scopes = Column(JSONB, default=list, nullable=False)
|
|
expires_at = Column(DateTime, nullable=False)
|
|
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
|
|
|
|
# Relationship
|
|
user = relationship("User", backref="graph_token", uselist=False)
|