File size: 3,885 Bytes
4f129c9
181758b
4f129c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""Typed models for the SupportDesk OpenEnv environment."""

from __future__ import annotations

from typing import Literal

from pydantic import BaseModel, Field

from openenv_compat import Action, Observation, State


class KnowledgeSnippet(BaseModel):
    """A policy or runbook excerpt the agent can use during triage."""

    article_id: str
    title: str
    content: str


class SupportTicket(BaseModel):
    """Static task input representing the inbound support ticket."""

    customer_name: str
    customer_tier: Literal["free", "pro", "enterprise"]
    company: str
    subject: str
    body: str
    region: str
    affected_users: int | None = None
    sla_minutes_remaining: int | None = None
    business_impact: str | None = None
    secondary_concerns: list[str] = Field(default_factory=list)
    attachments: list[str] = Field(default_factory=list)


class ActionHistoryEntry(BaseModel):
    """A concise trace entry used in observations and state dumps."""

    step: int
    operation: str
    summary: str
    reward_delta: float = 0.0


class CustomerFollowUp(BaseModel):
    """A scripted customer response that arrives after a request for more information."""

    status: Literal["none", "pending", "partial", "complete", "incorrect"] = "none"
    message: str | None = None
    provided_fields: list[str] = Field(default_factory=list)
    wrong_fields: list[str] = Field(default_factory=list)


class SupportCaseProgress(BaseModel):
    """Mutable case state that graders score against."""

    queue: str | None = None
    priority: str | None = None
    issue_type: str | None = None
    status: str = "new"
    resolution_code: str | None = None
    requested_fields: list[str] = Field(default_factory=list)
    reply: str | None = None
    internal_note: str | None = None
    customer_follow_up: CustomerFollowUp = Field(default_factory=CustomerFollowUp)


class SupportDeskAction(Action):
    """One structured action the agent can take at each step."""

    operation: Literal["classify", "request_info", "draft_reply", "add_internal_note", "submit", "wait"]
    queue: str | None = None
    priority: str | None = None
    issue_type: str | None = None
    status: str | None = None
    resolution_code: str | None = None
    requested_fields: list[str] = Field(default_factory=list)
    reply: str | None = None
    internal_note: str | None = None


class SupportDeskObservation(Observation):
    """Observation emitted to the agent after reset and each step."""

    task_id: str
    difficulty: Literal["easy", "medium", "hard"]
    objective: str
    ticket: SupportTicket
    knowledge_base: list[KnowledgeSnippet]
    available_queues: list[str]
    available_priorities: list[str]
    available_statuses: list[str]
    available_issue_types: list[str]
    case: SupportCaseProgress
    current_sla_minutes_remaining: int | None = None
    workflow_stage: str
    required_next_actions: list[str] = Field(default_factory=list)
    risk_flags: list[str] = Field(default_factory=list)
    action_history: list[ActionHistoryEntry] = Field(default_factory=list)
    feedback: str = ""
    remaining_steps: int = 0


class SupportDeskState(State):
    """Current environment state returned by the OpenEnv state() API."""

    episode_id: str | None = None
    task_id: str
    difficulty: Literal["easy", "medium", "hard"]
    step_count: int = 0
    reward: float = 0.0
    done: bool = False
    current_score: float = 0.0
    max_steps: int = 0
    case: SupportCaseProgress
    current_sla_minutes_remaining: int | None = None
    workflow_stage: str
    required_next_actions: list[str] = Field(default_factory=list)
    risk_flags: list[str] = Field(default_factory=list)
    action_history: list[ActionHistoryEntry] = Field(default_factory=list)
    completed_milestones: list[str] = Field(default_factory=list)
    last_feedback: str = ""