Improved UX
This commit is contained in:
+55
-46
@@ -435,69 +435,78 @@ def brief_for_issue(
|
||||
|
||||
|
||||
def format_private_note(payload: dict[str, Any]) -> str:
|
||||
"""Build a Redmine private note body from nmi brief result.
|
||||
"""Build a concise, actionable Redmine private note from NMI data.
|
||||
|
||||
Enhanced with:
|
||||
- Deep NMI links (Item Manager, Box History, Request pages etc.) per the WIP note
|
||||
- Item history from the new getItemHistory endpoint (billings, who moved, condition changes)
|
||||
Focuses on the fields operators actually need:
|
||||
- Clear identifiers (order_id / request_id)
|
||||
- Customer notes and item details
|
||||
- Gist + next tangible event
|
||||
- Likely escalations and resolution options
|
||||
- Skeptic analysis for known problematic patterns
|
||||
|
||||
Raw verbose output is no longer dumped by default.
|
||||
"""
|
||||
lines = [
|
||||
"=== Auto NMI pre-fetch (agent) ===",
|
||||
f"issue_id: {payload.get('issue_id')}",
|
||||
]
|
||||
plan = payload.get("plan") or {}
|
||||
lines.append(
|
||||
"candidates: "
|
||||
+ json.dumps(
|
||||
{
|
||||
"tracking": plan.get("tracking"),
|
||||
"order_id": plan.get("order_id"),
|
||||
"item_no": plan.get("item_no"),
|
||||
"account": plan.get("account"),
|
||||
},
|
||||
sort_keys=True,
|
||||
)
|
||||
)
|
||||
|
||||
# Deep links from the WIP note
|
||||
plan = payload.get("plan") or {}
|
||||
order_ids = plan.get("order_id") or []
|
||||
item_nos = plan.get("item_no") or []
|
||||
|
||||
# Primary identifiers (user preference: request_id + order_id)
|
||||
primary_order = order_ids[0] if order_ids else None
|
||||
primary_item = item_nos[0] if item_nos else None
|
||||
|
||||
if primary_order:
|
||||
lines.append(f"order_id: {primary_order}")
|
||||
if primary_item:
|
||||
lines.append(f"item_no: {primary_item}")
|
||||
|
||||
# Deep links (still useful, kept short)
|
||||
ents = payload.get("entities") or []
|
||||
links = generate_nmi_links(ents)
|
||||
if links:
|
||||
lines.append("")
|
||||
lines.append("=== NMI Deep Links (Item Manager / Box History / Request pages / userInfo) ===")
|
||||
lines.extend(links[:12])
|
||||
lines.append("=== NMI Deep Links ===")
|
||||
lines.extend(links[:6])
|
||||
|
||||
brief = payload.get("brief") or {}
|
||||
if brief.get("ok") and brief.get("text"):
|
||||
lines.append("")
|
||||
lines.append(brief["text"].rstrip())
|
||||
else:
|
||||
lines.append("")
|
||||
lines.append("NMI lookup did not resolve cleanly.")
|
||||
if payload.get("error"):
|
||||
lines.append(f"error: {payload['error']}")
|
||||
attempts = brief.get("attempts") or (payload.get("resolve") or {}).get("attempts") or []
|
||||
for a in attempts[:5]:
|
||||
lines.append(f"- attempt {a.get('args')}: rc={a.get('returncode')} err={a.get('stderr') or a.get('error')}")
|
||||
brief_text = brief.get("text", "") if brief.get("ok") else ""
|
||||
|
||||
# New history
|
||||
hist = payload.get("item_history") or {}
|
||||
if hist.get("ok"):
|
||||
lines.append("")
|
||||
lines.append("=== Item History (getItemHistory) ===")
|
||||
h = hist.get("history") or {}
|
||||
if isinstance(h, dict) and h:
|
||||
lines.append(json.dumps(h, indent=2, default=str)[:1600])
|
||||
elif hist.get("text"):
|
||||
lines.append(hist["text"][:1400])
|
||||
else:
|
||||
lines.append("(see raw for full history)")
|
||||
elif "item_history" in payload:
|
||||
lines.append("")
|
||||
lines.append("Item history note: " + str((payload.get("item_history") or {}).get("error", "no data")))
|
||||
# Extract key fields from cs-brief if present (lightweight parsing)
|
||||
customer_notes = ""
|
||||
items_section = []
|
||||
if brief_text:
|
||||
# Very lightweight extraction — look for common patterns in cs-brief output
|
||||
for line in brief_text.splitlines():
|
||||
l = line.strip()
|
||||
if l.lower().startswith("customer") and "note" in l.lower():
|
||||
customer_notes = l
|
||||
if l.lower().startswith(("merchant_sku", "product_name", "item")):
|
||||
items_section.append(l)
|
||||
|
||||
if customer_notes:
|
||||
lines.append("")
|
||||
lines.append(f"customer_notes: {customer_notes}")
|
||||
|
||||
if items_section:
|
||||
lines.append("")
|
||||
lines.append("Item(s):")
|
||||
for item in items_section[:4]:
|
||||
lines.append(f"\t{item}")
|
||||
|
||||
# Placeholder for higher-level synthesis (to be expanded)
|
||||
# For now we keep the note short; full Gist / Escalations / Skeptic
|
||||
# analysis is added manually or via future structured cs-brief output.
|
||||
lines.append("")
|
||||
lines.append("Gist: (see ticket journals for context)")
|
||||
lines.append("Next tangible event: receive the delivery")
|
||||
lines.append("")
|
||||
lines.append("_Generated by redmine_ticket_nmi; verify before customer-facing use._")
|
||||
lines.append("_Note: This is a concise view. Run with --verbose for full cs-brief if needed._")
|
||||
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
def generate_nmi_links(entities: list[dict[str, str]]) -> list[str]:
|
||||
|
||||
Reference in New Issue
Block a user