format_ticket_context_for_prompt() in services/psa/ticket_context.py serializes TicketContext into structured text for AI system prompts, with 10-note limit, 200-char text previews, and human-readable timestamps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
"""Format PSA ticket context as structured text for AI system prompts."""
|
|
from __future__ import annotations
|
|
|
|
from app.schemas.psa_context import TicketContext
|
|
|
|
|
|
def format_ticket_context_for_prompt(ctx: TicketContext) -> str:
|
|
"""Serialize a TicketContext into a structured text block for AI prompts."""
|
|
lines: list[str] = ["=== TICKET CONTEXT ==="]
|
|
|
|
# Ticket summary line
|
|
t = ctx.ticket
|
|
lines.append(f'Ticket: #{t.id} — "{t.summary}"')
|
|
lines.append(f"Status: {t.status} | Priority: {t.priority}")
|
|
lines.append(f"Board: {t.board}")
|
|
if t.sla:
|
|
lines.append(f"SLA Deadline: {t.sla}")
|
|
if t.resources:
|
|
lines.append(f"Assigned To: {t.resources}")
|
|
|
|
# Company block
|
|
lines.append("")
|
|
c = ctx.company
|
|
lines.append(f"Client: {c.name}")
|
|
if c.site:
|
|
lines.append(f"Site: {c.site}")
|
|
if c.address:
|
|
lines.append(f"Address: {c.address}")
|
|
if c.phone:
|
|
lines.append(f"Phone: {c.phone}")
|
|
if c.type:
|
|
lines.append(f"Type: {c.type}")
|
|
if c.territory:
|
|
lines.append(f"Territory: {c.territory}")
|
|
|
|
# Contact block
|
|
if ctx.contact:
|
|
contact = ctx.contact
|
|
contact_parts = [contact.name]
|
|
if contact.email:
|
|
contact_parts.append(f"({contact.email})")
|
|
if contact.title:
|
|
contact_parts.append(f"— {contact.title}")
|
|
contact_line = " ".join(contact_parts)
|
|
if contact.phone:
|
|
contact_line += f" — {contact.phone}"
|
|
lines.append("")
|
|
lines.append(f"Contact: {contact_line}")
|
|
|
|
# Devices
|
|
if ctx.configurations:
|
|
lines.append("")
|
|
lines.append("Devices:")
|
|
for cfg in ctx.configurations:
|
|
parts = [cfg.device_identifier]
|
|
if cfg.type:
|
|
parts.append(cfg.type)
|
|
if cfg.os_type:
|
|
parts.append(cfg.os_type)
|
|
if cfg.ip_address:
|
|
parts.append(cfg.ip_address)
|
|
lines.append("- " + " | ".join(parts))
|
|
|
|
# Recent Notes (limit 10, text preview 200 chars)
|
|
if ctx.notes:
|
|
lines.append("")
|
|
lines.append("Recent Notes:")
|
|
for note in ctx.notes[:10]:
|
|
date_str = note.date_created.strftime("%b %d, %I:%M %p")
|
|
member_str = f"{note.member}: " if note.member else ""
|
|
text_preview = note.text[:200]
|
|
if len(note.text) > 200:
|
|
text_preview += "..."
|
|
lines.append(f"- [{date_str}] {member_str}{text_preview}")
|
|
|
|
# Related open tickets
|
|
if ctx.related_tickets:
|
|
lines.append("")
|
|
lines.append("Related Open Tickets:")
|
|
for rt in ctx.related_tickets:
|
|
lines.append(f'- #{rt.id}: "{rt.summary}" ({rt.status}, {rt.priority})')
|
|
|
|
lines.append("=== END CONTEXT ===")
|
|
return "\n".join(lines)
|