Phase 2 of the FlowPilot-First Pivot connecting AI sessions to ConnectWise PSA: Slice 1 — PSA Ticket Intake: - FlowPilotEngine accepts psa_ticket intake with graceful CW API fallback - Ticket picker on intake screen (refactored TicketPickerModal for dual-mode) - Ticket context card in session sidebar Slice 2 — Auto Documentation Push: - PSA documentation service with resolution/escalation note formatting - Time entry creation via new ConnectWise provider method - Automatic retry scheduler (APScheduler, 5min interval, 3 retries) - PSA push status indicators in frontend with manual retry button - Member mapping warning when CW member not mapped Slice 3 — Session Pause/Resume & Escalation Handoff: - Pause/resume endpoints for same-engineer session bookmarking - Escalation flow: requesting_escalation status, self-escalation blocked - Enhanced escalation package with LLM-generated hypotheses/suggestions - Pickup endpoint with continue/fresh resume modes and briefing step - Escalation queue (sidebar nav + dedicated page) - SessionBriefing component with continue/fresh choice UI - EscalateModal with PSA-aware button text Slice 4 — Mid-Session Ticket Linking: - Link ticket retroactively with context injection into system prompt - Link Ticket button in session sidebar Slice 5 — FlowPilot PSA Settings: - Settings tab on IntegrationsPage with 7 configurable options - Stored as flowpilot_settings JSONB on PsaConnection Database: 2 migrations (flowpilot_settings, psa_post_log changes, status constraint) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
79 lines
2.5 KiB
Python
79 lines
2.5 KiB
Python
"""phase2 psa flowpilot integration
|
|
|
|
Revision ID: bb2101378a61
|
|
Revises: f1a2b3c4d5e6
|
|
Create Date: 2026-03-18 23:05:01.099910
|
|
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = 'bb2101378a61'
|
|
down_revision: Union[str, None] = 'f1a2b3c4d5e6'
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# 1. Add flowpilot_settings JSONB to psa_connections
|
|
op.add_column('psa_connections', sa.Column(
|
|
'flowpilot_settings',
|
|
postgresql.JSONB(astext_type=sa.Text()),
|
|
nullable=True,
|
|
server_default='{}',
|
|
comment='FlowPilot-specific settings: auto_push, time_rounding, note_visibility, etc.',
|
|
))
|
|
|
|
# 2. Add ai_session_id FK to psa_post_log
|
|
op.add_column('psa_post_log', sa.Column(
|
|
'ai_session_id',
|
|
sa.Uuid(),
|
|
nullable=True,
|
|
comment='FK to AI sessions (Phase 2). Original session_id FK remains for legacy sessions.',
|
|
))
|
|
op.create_index(
|
|
op.f('ix_psa_post_log_ai_session_id'),
|
|
'psa_post_log',
|
|
['ai_session_id'],
|
|
)
|
|
op.create_foreign_key(
|
|
'fk_psa_post_log_ai_session_id',
|
|
'psa_post_log',
|
|
'ai_sessions',
|
|
['ai_session_id'],
|
|
['id'],
|
|
ondelete='CASCADE',
|
|
)
|
|
|
|
# 3. Make original session_id nullable (was NOT NULL — legacy sessions only)
|
|
op.alter_column('psa_post_log', 'session_id', nullable=True)
|
|
|
|
# 4. Add retry_count and next_retry_at for automatic retries
|
|
op.add_column('psa_post_log', sa.Column(
|
|
'retry_count',
|
|
sa.Integer(),
|
|
nullable=False,
|
|
server_default='0',
|
|
comment='Number of retry attempts for failed PSA pushes',
|
|
))
|
|
op.add_column('psa_post_log', sa.Column(
|
|
'next_retry_at',
|
|
sa.DateTime(timezone=True),
|
|
nullable=True,
|
|
comment='When to attempt the next retry',
|
|
))
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_column('psa_post_log', 'next_retry_at')
|
|
op.drop_column('psa_post_log', 'retry_count')
|
|
op.alter_column('psa_post_log', 'session_id', nullable=False)
|
|
op.drop_constraint('fk_psa_post_log_ai_session_id', 'psa_post_log', type_='foreignkey')
|
|
op.drop_index(op.f('ix_psa_post_log_ai_session_id'), table_name='psa_post_log')
|
|
op.drop_column('psa_post_log', 'ai_session_id')
|
|
op.drop_column('psa_connections', 'flowpilot_settings')
|