Skip to content

Commit 77a6138

Browse files
committed
Implement setting of mandatory fields when triaging
1 parent b4ed3a9 commit 77a6138

File tree

5 files changed

+124
-9
lines changed

5 files changed

+124
-9
lines changed

beeai/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ run-beeai-bash:
1717
run-triage-agent-standalone:
1818
$(COMPOSE) -f $(COMPOSE_FILE) run --rm \
1919
-e JIRA_ISSUE=$(JIRA_ISSUE) \
20+
-e DRY_RUN=$(DRY_RUN) \
2021
triage-agent
2122

2223

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from typing import Any
2+
3+
from pydantic import BaseModel, Field
4+
5+
from beeai_framework.context import RunContext
6+
from beeai_framework.emitter import Emitter
7+
from beeai_framework.tools import JSONToolOutput, Tool, ToolRunOptions
8+
9+
10+
class VersionMapperInput(BaseModel):
11+
major_version: int = Field(description="RHEL major version (e.g., 8, 9, 10)")
12+
is_critical: bool = Field(description="Whether this is a most critical issue requiring Z-stream (e.g., privilege escalation, remote code execution, data loss)", default=False)
13+
14+
15+
class VersionMapperResult(BaseModel):
16+
fix_version: str = Field(description="The appropriate fix version for the given major version and criticality")
17+
branch: str = Field(description="The corresponding branch name")
18+
19+
20+
class VersionMapperOutput(JSONToolOutput[VersionMapperResult]):
21+
pass
22+
23+
24+
class VersionMapperTool(Tool[VersionMapperInput, ToolRunOptions, VersionMapperOutput]):
25+
"""Tool to map RHEL major versions to current development fix versions."""
26+
27+
name = "map_version"
28+
description = "Map RHEL major version to current development fix version (Y-stream or Z-stream for most critical issues only)"
29+
input_schema = VersionMapperInput
30+
31+
def __init__(self, options: dict[str, Any] | None = None) -> None:
32+
super().__init__(options)
33+
34+
def _create_emitter(self) -> Emitter:
35+
return Emitter.root().child(
36+
namespace=["tool", "version", "mapper"],
37+
creator=self,
38+
)
39+
40+
async def _run(
41+
self, tool_input: VersionMapperInput, options: ToolRunOptions | None, context: RunContext
42+
) -> VersionMapperOutput:
43+
"""
44+
Map RHEL major version to the appropriate fix version.
45+
46+
Args:
47+
tool_input: Input containing major_version and is_critical
48+
49+
Returns:
50+
VersionMapperOutput with fix_version and branch
51+
"""
52+
major_version = tool_input.major_version
53+
is_critical = tool_input.is_critical
54+
55+
if major_version == 8:
56+
fix_version = "rhel-8.10.z"
57+
elif major_version == 9:
58+
if is_critical:
59+
fix_version = "rhel-9.7.z"
60+
else:
61+
fix_version = "rhel-9.8"
62+
elif major_version == 10:
63+
if is_critical:
64+
fix_version = "rhel-10.1.z"
65+
else:
66+
fix_version = "rhel-10.2"
67+
else:
68+
raise ValueError(f"Unsupported RHEL major version: {major_version}. Supported versions: 8, 9, 10")
69+
70+
branch_map = {
71+
8: "c8s",
72+
9: "c9s",
73+
10: "c10s"
74+
}
75+
branch = branch_map[major_version]
76+
77+
result = VersionMapperResult(
78+
fix_version=fix_version,
79+
branch=branch
80+
)
81+
82+
return VersionMapperOutput(result=result)

beeai/agents/triage_agent.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from observability import setup_observability
2424
from tools.commands import RunShellCommandTool
2525
from tools.patch_validator import PatchValidatorTool
26+
from tools.version_mapper import VersionMapperTool
2627
from utils import get_agent_execution_config, mcp_tools, redis_client
2728

2829
logger = logging.getLogger(__name__)
@@ -126,6 +127,7 @@ def render_prompt(input: InputSchema) -> str:
126127
* A Rebase is only to be chosen when the issue explicitly instructs you to "rebase" or "update"
127128
to a newer/specific upstream version. Do not infer this.
128129
* Identify the <package_version> the package should be updated or rebased to.
130+
* Set the Jira fields as per the instructions below.
129131
130132
2. **Backport a Patch OR Request Clarification**
131133
This path is for issues that represent a clear bug or CVE that needs a targeted fix.
@@ -183,6 +185,8 @@ def render_prompt(input: InputSchema) -> str:
183185
is clarification-needed
184186
* This is the correct choice when you are sure a problem exists but cannot find the solution yourself
185187
188+
2.5 Set the Jira fields as per the instructions below.
189+
186190
3. **No Action**
187191
A No Action decision is appropriate for issues that are NOT bugs or CVEs requiring code fixes:
188192
* QE tasks, testing, or validation work
@@ -197,6 +201,19 @@ def render_prompt(input: InputSchema) -> str:
197201
* The package mentioned in the issue cannot be found or identified
198202
* The issue cannot be accessed
199203
204+
**Final Step: Set JIRA Fields (for Rebase and Backport decisions only)**
205+
206+
If your decision is rebase or backport, use set_jira_fields tool to update JIRA fields (Severity, Fix Version, Target End):
207+
1. Check all of the mentioned fields in the JIRA issue and don't modify those that are already set
208+
2. Extract the affected RHEL major version from the JIRA issue (look in Affects Version/s field or issue description)
209+
3. Determine if this is a very critical issue requiring Z-stream (only for: privilege escalation, remote code execution, data loss/corruption, or system compromise)
210+
4. Use map_version tool with the major version and criticality to get the appropriate Fix Version and branch
211+
5. Set JIRA fields:
212+
* Severity: default to 'moderate', for important issues use 'important', for most critical use 'critical' (privilege escalation, RCE, data loss)
213+
* Fix Version: use the fix_version from map_version tool result
214+
* Target End: today + 14 days
215+
6. Use the branch from map_version tool result for your output
216+
200217
**Output Format**
201218
202219
Your output must strictly follow the format below.
@@ -242,21 +259,23 @@ async def main() -> None:
242259
async with mcp_tools(os.getenv("MCP_GATEWAY_URL")) as gateway_tools:
243260
agent = RequirementAgent(
244261
llm=ChatModel.from_name(os.getenv("CHAT_MODEL")),
245-
tools=[ThinkTool(), RunShellCommandTool(), PatchValidatorTool()]
246-
+ [t for t in gateway_tools if t.name == "get_jira_details"],
262+
tools=[ThinkTool(), RunShellCommandTool(), PatchValidatorTool(), VersionMapperTool()]
263+
+ [t for t in gateway_tools if t.name in ["get_jira_details", "set_jira_fields"]],
247264
memory=UnconstrainedMemory(),
248265
requirements=[
249266
ConditionalRequirement(ThinkTool, force_after=Tool, consecutive_allowed=False),
250267
ConditionalRequirement("get_jira_details", min_invocations=1),
251268
ConditionalRequirement(RunShellCommandTool, only_after="get_jira_details"),
252269
ConditionalRequirement(PatchValidatorTool, only_after="get_jira_details"),
270+
ConditionalRequirement("set_jira_fields", only_after="get_jira_details"),
253271
],
254272
middlewares=[GlobalTrajectoryMiddleware(pretty=True)],
255273
role="Red Hat Enterprise Linux developer",
256274
instructions=[
257275
"Use the `think` tool to reason through complex decisions and document your approach.",
258276
"Be proactive in your search for fixes and do not give up easily.",
259-
],
277+
"After completing your triage analysis, if your decision is backport or rebase, always set appropriate JIRA fields per the instructions using set_jira_fields tool.",
278+
]
260279
)
261280

262281
async def run(input):

beeai/compose.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ services:
4242
- KEYTAB_FILE=/home/mcp/keytab
4343
# default cache location is a keyring
4444
- KRB5CCNAME=FILE:/tmp/krb5cc
45+
- DRY_RUN=${DRY_RUN:-false}
4546
env_file:
4647
- .secrets/mcp-gateway.env
4748
volumes:

beeai/mcp_server/jira_tools.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime
12
import os
23
import json
34
from enum import Enum
@@ -8,6 +9,12 @@
89
from pydantic import Field
910

1011

12+
# Jira custom field IDs
13+
SEVERITY_CUSTOM_FIELD = "customfield_12316142"
14+
PRELIMINARY_TESTING_CUSTOM_FIELD = "customfield_12321540"
15+
TARGET_END_CUSTOM_FIELD = "customfield_12313942"
16+
17+
1118
class Severity(Enum):
1219
NONE = "None"
1320
INFORMATIONAL = "Informational"
@@ -74,26 +81,31 @@ def set_jira_fields(
7481
issue_key: Annotated[str, Field(description="Jira issue key (e.g. RHEL-12345)")],
7582
fix_versions: Annotated[
7683
list[str] | None,
77-
Field(
78-
description="List of Fix Version/s values",
79-
pattern=r"^(CentOS Stream \d+|eln|zstream|rhel-\d+\.\d+(\.(\d+|z)|\.\d+\.z|[._](alpha|beta))?)$",
80-
),
84+
Field(description="List of Fix Version/s values (e.g., ['rhel-9.8'], ['rhel-9.7.z'])"),
8185
] = None,
8286
severity: Annotated[Severity | None, Field(description="Severity value")] = None,
8387
preliminary_testing: Annotated[
8488
PreliminaryTesting | None, Field(description="Preliminary Testing value")
8589
] = None,
90+
target_end: Annotated[datetime.date | None, Field(description="Target End value")] = None,
8691
) -> str:
8792
"""
8893
Updates the specified Jira issue, setting the specified fields (if provided).
8994
"""
95+
if os.getenv("DRY_RUN", "False").lower() == "true":
96+
return "Dry run, not updating Jira fields"
97+
98+
return "Not updating Jira fields"
99+
90100
fields = {}
91101
if fix_versions is not None:
92102
fields["fixVersions"] = [{"name": fv} for fv in fix_versions]
93103
if severity is not None:
94-
fields["customfield_12316142"] = {"value": severity.value}
104+
fields[SEVERITY_CUSTOM_FIELD] = {"value": severity.value}
95105
if preliminary_testing is not None:
96-
fields["customfield_12321540"] = {"value": preliminary_testing.value}
106+
fields[PRELIMINARY_TESTING_CUSTOM_FIELD] = {"value": preliminary_testing.value}
107+
if target_end is not None:
108+
fields[TARGET_END_CUSTOM_FIELD] = {"value": target_end.strftime("%Y-%m-%d")}
97109
if not fields:
98110
return "No fields to update have been specified, not doing anything"
99111
try:

0 commit comments

Comments
 (0)