amd-gaia 0.15.0__py3-none-any.whl → 0.15.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.2.dist-info}/METADATA +222 -223
- amd_gaia-0.15.2.dist-info/RECORD +182 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.2.dist-info}/WHEEL +1 -1
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.2.dist-info}/entry_points.txt +1 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.2.dist-info}/licenses/LICENSE.md +20 -20
- gaia/__init__.py +29 -29
- gaia/agents/__init__.py +19 -19
- gaia/agents/base/__init__.py +9 -9
- gaia/agents/base/agent.py +2132 -2177
- gaia/agents/base/api_agent.py +119 -120
- gaia/agents/base/console.py +1967 -1841
- gaia/agents/base/errors.py +237 -237
- gaia/agents/base/mcp_agent.py +86 -86
- gaia/agents/base/tools.py +88 -83
- gaia/agents/blender/__init__.py +7 -0
- gaia/agents/blender/agent.py +553 -556
- gaia/agents/blender/agent_simple.py +133 -135
- gaia/agents/blender/app.py +211 -211
- gaia/agents/blender/app_simple.py +41 -41
- gaia/agents/blender/core/__init__.py +16 -16
- gaia/agents/blender/core/materials.py +506 -506
- gaia/agents/blender/core/objects.py +316 -316
- gaia/agents/blender/core/rendering.py +225 -225
- gaia/agents/blender/core/scene.py +220 -220
- gaia/agents/blender/core/view.py +146 -146
- gaia/agents/chat/__init__.py +9 -9
- gaia/agents/chat/agent.py +809 -835
- gaia/agents/chat/app.py +1065 -1058
- gaia/agents/chat/session.py +508 -508
- gaia/agents/chat/tools/__init__.py +15 -15
- gaia/agents/chat/tools/file_tools.py +96 -96
- gaia/agents/chat/tools/rag_tools.py +1744 -1729
- gaia/agents/chat/tools/shell_tools.py +437 -436
- gaia/agents/code/__init__.py +7 -7
- gaia/agents/code/agent.py +549 -549
- gaia/agents/code/cli.py +377 -0
- gaia/agents/code/models.py +135 -135
- gaia/agents/code/orchestration/__init__.py +24 -24
- gaia/agents/code/orchestration/checklist_executor.py +1763 -1763
- gaia/agents/code/orchestration/checklist_generator.py +713 -713
- gaia/agents/code/orchestration/factories/__init__.py +9 -9
- gaia/agents/code/orchestration/factories/base.py +63 -63
- gaia/agents/code/orchestration/factories/nextjs_factory.py +118 -118
- gaia/agents/code/orchestration/factories/python_factory.py +106 -106
- gaia/agents/code/orchestration/orchestrator.py +841 -841
- gaia/agents/code/orchestration/project_analyzer.py +391 -391
- gaia/agents/code/orchestration/steps/__init__.py +67 -67
- gaia/agents/code/orchestration/steps/base.py +188 -188
- gaia/agents/code/orchestration/steps/error_handler.py +314 -314
- gaia/agents/code/orchestration/steps/nextjs.py +828 -828
- gaia/agents/code/orchestration/steps/python.py +307 -307
- gaia/agents/code/orchestration/template_catalog.py +469 -469
- gaia/agents/code/orchestration/workflows/__init__.py +14 -14
- gaia/agents/code/orchestration/workflows/base.py +80 -80
- gaia/agents/code/orchestration/workflows/nextjs.py +186 -186
- gaia/agents/code/orchestration/workflows/python.py +94 -94
- gaia/agents/code/prompts/__init__.py +11 -11
- gaia/agents/code/prompts/base_prompt.py +77 -77
- gaia/agents/code/prompts/code_patterns.py +2034 -2036
- gaia/agents/code/prompts/nextjs_prompt.py +40 -40
- gaia/agents/code/prompts/python_prompt.py +109 -109
- gaia/agents/code/schema_inference.py +365 -365
- gaia/agents/code/system_prompt.py +41 -41
- gaia/agents/code/tools/__init__.py +42 -42
- gaia/agents/code/tools/cli_tools.py +1138 -1138
- gaia/agents/code/tools/code_formatting.py +319 -319
- gaia/agents/code/tools/code_tools.py +769 -769
- gaia/agents/code/tools/error_fixing.py +1347 -1347
- gaia/agents/code/tools/external_tools.py +180 -180
- gaia/agents/code/tools/file_io.py +845 -845
- gaia/agents/code/tools/prisma_tools.py +190 -190
- gaia/agents/code/tools/project_management.py +1016 -1016
- gaia/agents/code/tools/testing.py +321 -321
- gaia/agents/code/tools/typescript_tools.py +122 -122
- gaia/agents/code/tools/validation_parsing.py +461 -461
- gaia/agents/code/tools/validation_tools.py +806 -806
- gaia/agents/code/tools/web_dev_tools.py +1758 -1758
- gaia/agents/code/validators/__init__.py +16 -16
- gaia/agents/code/validators/antipattern_checker.py +241 -241
- gaia/agents/code/validators/ast_analyzer.py +197 -197
- gaia/agents/code/validators/requirements_validator.py +145 -145
- gaia/agents/code/validators/syntax_validator.py +171 -171
- gaia/agents/docker/__init__.py +7 -7
- gaia/agents/docker/agent.py +643 -642
- gaia/agents/emr/__init__.py +8 -8
- gaia/agents/emr/agent.py +1504 -1506
- gaia/agents/emr/cli.py +1322 -1322
- gaia/agents/emr/constants.py +475 -475
- gaia/agents/emr/dashboard/__init__.py +4 -4
- gaia/agents/emr/dashboard/server.py +1972 -1974
- gaia/agents/jira/__init__.py +11 -11
- gaia/agents/jira/agent.py +894 -894
- gaia/agents/jira/jql_templates.py +299 -299
- gaia/agents/routing/__init__.py +7 -7
- gaia/agents/routing/agent.py +567 -570
- gaia/agents/routing/system_prompt.py +75 -75
- gaia/agents/summarize/__init__.py +11 -0
- gaia/agents/summarize/agent.py +885 -0
- gaia/agents/summarize/prompts.py +129 -0
- gaia/api/__init__.py +23 -23
- gaia/api/agent_registry.py +238 -238
- gaia/api/app.py +305 -305
- gaia/api/openai_server.py +575 -575
- gaia/api/schemas.py +186 -186
- gaia/api/sse_handler.py +373 -373
- gaia/apps/__init__.py +4 -4
- gaia/apps/llm/__init__.py +6 -6
- gaia/apps/llm/app.py +184 -169
- gaia/apps/summarize/app.py +116 -633
- gaia/apps/summarize/html_viewer.py +133 -133
- gaia/apps/summarize/pdf_formatter.py +284 -284
- gaia/audio/__init__.py +2 -2
- gaia/audio/audio_client.py +439 -439
- gaia/audio/audio_recorder.py +269 -269
- gaia/audio/kokoro_tts.py +599 -599
- gaia/audio/whisper_asr.py +432 -432
- gaia/chat/__init__.py +16 -16
- gaia/chat/app.py +428 -430
- gaia/chat/prompts.py +522 -522
- gaia/chat/sdk.py +1228 -1225
- gaia/cli.py +5659 -5632
- gaia/database/__init__.py +10 -10
- gaia/database/agent.py +176 -176
- gaia/database/mixin.py +290 -290
- gaia/database/testing.py +64 -64
- gaia/eval/batch_experiment.py +2332 -2332
- gaia/eval/claude.py +542 -542
- gaia/eval/config.py +37 -37
- gaia/eval/email_generator.py +512 -512
- gaia/eval/eval.py +3179 -3179
- gaia/eval/groundtruth.py +1130 -1130
- gaia/eval/transcript_generator.py +582 -582
- gaia/eval/webapp/README.md +167 -167
- gaia/eval/webapp/package-lock.json +875 -875
- gaia/eval/webapp/package.json +20 -20
- gaia/eval/webapp/public/app.js +3402 -3402
- gaia/eval/webapp/public/index.html +87 -87
- gaia/eval/webapp/public/styles.css +3661 -3661
- gaia/eval/webapp/server.js +415 -415
- gaia/eval/webapp/test-setup.js +72 -72
- gaia/installer/__init__.py +23 -0
- gaia/installer/init_command.py +1275 -0
- gaia/installer/lemonade_installer.py +619 -0
- gaia/llm/__init__.py +10 -2
- gaia/llm/base_client.py +60 -0
- gaia/llm/exceptions.py +12 -0
- gaia/llm/factory.py +70 -0
- gaia/llm/lemonade_client.py +3421 -3221
- gaia/llm/lemonade_manager.py +294 -294
- gaia/llm/providers/__init__.py +9 -0
- gaia/llm/providers/claude.py +108 -0
- gaia/llm/providers/lemonade.py +118 -0
- gaia/llm/providers/openai_provider.py +79 -0
- gaia/llm/vlm_client.py +382 -382
- gaia/logger.py +189 -189
- gaia/mcp/agent_mcp_server.py +245 -245
- gaia/mcp/blender_mcp_client.py +138 -138
- gaia/mcp/blender_mcp_server.py +648 -648
- gaia/mcp/context7_cache.py +332 -332
- gaia/mcp/external_services.py +518 -518
- gaia/mcp/mcp_bridge.py +811 -550
- gaia/mcp/servers/__init__.py +6 -6
- gaia/mcp/servers/docker_mcp.py +83 -83
- gaia/perf_analysis.py +361 -0
- gaia/rag/__init__.py +10 -10
- gaia/rag/app.py +293 -293
- gaia/rag/demo.py +304 -304
- gaia/rag/pdf_utils.py +235 -235
- gaia/rag/sdk.py +2194 -2194
- gaia/security.py +183 -163
- gaia/talk/app.py +287 -289
- gaia/talk/sdk.py +538 -538
- gaia/testing/__init__.py +87 -87
- gaia/testing/assertions.py +330 -330
- gaia/testing/fixtures.py +333 -333
- gaia/testing/mocks.py +493 -493
- gaia/util.py +46 -46
- gaia/utils/__init__.py +33 -33
- gaia/utils/file_watcher.py +675 -675
- gaia/utils/parsing.py +223 -223
- gaia/version.py +100 -100
- amd_gaia-0.15.0.dist-info/RECORD +0 -168
- gaia/agents/code/app.py +0 -266
- gaia/llm/llm_client.py +0 -723
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.2.dist-info}/top_level.txt +0 -0
|
@@ -1,299 +1,299 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
# Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
3
|
-
# SPDX-License-Identifier: MIT
|
|
4
|
-
"""
|
|
5
|
-
JQL Template System for GAIA Orchestrator Agent.
|
|
6
|
-
Provides templates and patterns for generating valid JQL queries from natural language.
|
|
7
|
-
|
|
8
|
-
Reference: https://support.atlassian.com/jira-service-management-cloud/docs/what-is-advanced-search-in-jira-cloud/
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
# JQL Templates for common patterns
|
|
12
|
-
JQL_TEMPLATES = {
|
|
13
|
-
# Issue Types (always quote values)
|
|
14
|
-
"bug": 'issuetype = "Bug"',
|
|
15
|
-
"bugs": 'issuetype = "Bug"',
|
|
16
|
-
"story": 'issuetype = "Story"',
|
|
17
|
-
"stories": 'issuetype = "Story"',
|
|
18
|
-
"task": 'issuetype = "Task"',
|
|
19
|
-
"tasks": 'issuetype = "Task"',
|
|
20
|
-
"epic": 'issuetype = "Epic"',
|
|
21
|
-
"epics": 'issuetype = "Epic"',
|
|
22
|
-
"sub-task": 'issuetype = "Sub-task"',
|
|
23
|
-
"subtask": 'issuetype = "Sub-task"',
|
|
24
|
-
# Priority Levels (always quote values)
|
|
25
|
-
"blocker": 'priority = "Blocker"',
|
|
26
|
-
"critical": 'priority = "Critical"',
|
|
27
|
-
"high priority": 'priority = "High"',
|
|
28
|
-
"high-priority": 'priority = "High"',
|
|
29
|
-
"medium priority": 'priority = "Medium"',
|
|
30
|
-
"low priority": 'priority = "Low"',
|
|
31
|
-
"urgent": 'priority in ("Blocker", "Critical")',
|
|
32
|
-
# Status Values (always quote values)
|
|
33
|
-
"open": 'resolution = "Unresolved"',
|
|
34
|
-
"unresolved": 'resolution = "Unresolved"',
|
|
35
|
-
"resolved": 'resolution != "Unresolved"',
|
|
36
|
-
"closed": 'status = "Closed"',
|
|
37
|
-
"done": 'status = "Done"',
|
|
38
|
-
"in progress": 'status = "In Progress"',
|
|
39
|
-
"in-progress": 'status = "In Progress"',
|
|
40
|
-
"todo": 'status = "To Do"',
|
|
41
|
-
"to do": 'status = "To Do"',
|
|
42
|
-
"blocked": 'status = "Blocked"',
|
|
43
|
-
# Assignment Patterns (using functions)
|
|
44
|
-
"my issues": "assignee = currentUser() OR reporter = currentUser()",
|
|
45
|
-
"assigned to me": "assignee = currentUser()",
|
|
46
|
-
"unassigned": "assignee is EMPTY",
|
|
47
|
-
"no assignee": "assignee is EMPTY",
|
|
48
|
-
"reported by me": "reporter = currentUser()",
|
|
49
|
-
"i reported": "reporter = currentUser()",
|
|
50
|
-
"watching": "watcher = currentUser()",
|
|
51
|
-
"i'm watching": "watcher = currentUser()",
|
|
52
|
-
# Time Functions (proper date functions)
|
|
53
|
-
"created today": "created >= startOfDay()",
|
|
54
|
-
"today's": "created >= startOfDay()",
|
|
55
|
-
"created yesterday": "created >= startOfDay(-1d) AND created < startOfDay()",
|
|
56
|
-
"created this week": "created >= startOfWeek()",
|
|
57
|
-
"this week": "created >= startOfWeek()",
|
|
58
|
-
"created last week": "created >= startOfWeek(-1w) AND created < startOfWeek()",
|
|
59
|
-
"last week": "created >= startOfWeek(-1w) AND created < startOfWeek()",
|
|
60
|
-
"created this month": "created >= startOfMonth()",
|
|
61
|
-
"this month": "created >= startOfMonth()",
|
|
62
|
-
"created last month": "created >= startOfMonth(-1M) AND created < startOfMonth()",
|
|
63
|
-
"last month": "created >= startOfMonth(-1M) AND created < startOfMonth()",
|
|
64
|
-
"last 24 hours": "created >= -24h",
|
|
65
|
-
"last 7 days": "created >= -7d",
|
|
66
|
-
"past week": "created >= -7d",
|
|
67
|
-
"last 30 days": "created >= -30d",
|
|
68
|
-
"past month": "created >= -30d",
|
|
69
|
-
"last 90 days": "created >= -90d",
|
|
70
|
-
"last quarter": "created >= -90d",
|
|
71
|
-
# Updated Time Patterns
|
|
72
|
-
"updated today": "updated >= startOfDay()",
|
|
73
|
-
"recently updated": "updated >= -7d",
|
|
74
|
-
"recent changes": "updated >= -7d",
|
|
75
|
-
"updated this week": "updated >= startOfWeek()",
|
|
76
|
-
"stale": "updated < -30d",
|
|
77
|
-
"not recently updated": "updated < -30d",
|
|
78
|
-
# Sprint Patterns (Agile)
|
|
79
|
-
"current sprint": "sprint in openSprints()",
|
|
80
|
-
"active sprint": "sprint in openSprints()",
|
|
81
|
-
"last sprint": "sprint in closedSprints()",
|
|
82
|
-
"previous sprint": "sprint in closedSprints()",
|
|
83
|
-
"future sprint": "sprint in futureSprints()",
|
|
84
|
-
"no sprint": "sprint is EMPTY",
|
|
85
|
-
"backlog": "sprint is EMPTY",
|
|
86
|
-
# Due Date Patterns
|
|
87
|
-
"overdue": 'duedate < now() AND resolution = "Unresolved"',
|
|
88
|
-
"past due": 'duedate < now() AND resolution = "Unresolved"',
|
|
89
|
-
"due today": "duedate = startOfDay()",
|
|
90
|
-
"due this week": "duedate >= startOfWeek() AND duedate <= endOfWeek()",
|
|
91
|
-
"due soon": "duedate >= now() AND duedate <= 7d",
|
|
92
|
-
"no due date": "duedate is EMPTY",
|
|
93
|
-
# Fix Version Patterns
|
|
94
|
-
"no fix version": "fixVersion is EMPTY",
|
|
95
|
-
"unscheduled": "fixVersion is EMPTY",
|
|
96
|
-
"released": "fixVersion in releasedVersions()",
|
|
97
|
-
"unreleased": "fixVersion in unreleasedVersions()",
|
|
98
|
-
# Component Patterns
|
|
99
|
-
"no component": "component is EMPTY",
|
|
100
|
-
# Epic Link Patterns
|
|
101
|
-
"no epic": '"Epic Link" is EMPTY',
|
|
102
|
-
# Comments and Attachments
|
|
103
|
-
"has comments": 'comment ~ "*"',
|
|
104
|
-
"with comments": 'comment ~ "*"',
|
|
105
|
-
"no comments": "comment is EMPTY",
|
|
106
|
-
"has attachments": "attachments is not EMPTY",
|
|
107
|
-
"with attachments": "attachments is not EMPTY",
|
|
108
|
-
"no attachments": "attachments is EMPTY",
|
|
109
|
-
# Story Points (Agile)
|
|
110
|
-
"no story points": '"Story Points" is EMPTY',
|
|
111
|
-
"unestimated": '"Story Points" is EMPTY',
|
|
112
|
-
# Common explicit queries
|
|
113
|
-
"all issues": "created >= -90d",
|
|
114
|
-
"show all": "created >= -90d",
|
|
115
|
-
"show me all": "created >= -90d",
|
|
116
|
-
"list all": "created >= -90d",
|
|
117
|
-
"everything": "created >= -90d",
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
# Complex patterns that need regex matching
|
|
121
|
-
REGEX_PATTERNS = [
|
|
122
|
-
# Project patterns
|
|
123
|
-
(r"project\s+([A-Z0-9]+)", lambda m: f"project = {m.group(1).upper()}"),
|
|
124
|
-
(r"in\s+([A-Z0-9]+)\s+project", lambda m: f"project = {m.group(1).upper()}"),
|
|
125
|
-
# Story points comparisons
|
|
126
|
-
(
|
|
127
|
-
r"story points?\s*(?:>|greater than)\s*(\d+)",
|
|
128
|
-
lambda m: f'"Story Points" > {m.group(1)}',
|
|
129
|
-
),
|
|
130
|
-
(
|
|
131
|
-
r"story points?\s*(?:<|less than)\s*(\d+)",
|
|
132
|
-
lambda m: f'"Story Points" < {m.group(1)}',
|
|
133
|
-
),
|
|
134
|
-
(
|
|
135
|
-
r"story points?\s*(?:>=|at least)\s*(\d+)",
|
|
136
|
-
lambda m: f'"Story Points" >= {m.group(1)}',
|
|
137
|
-
),
|
|
138
|
-
(
|
|
139
|
-
r"story points?\s*(?:<=|at most)\s*(\d+)",
|
|
140
|
-
lambda m: f'"Story Points" <= {m.group(1)}',
|
|
141
|
-
),
|
|
142
|
-
(
|
|
143
|
-
r"story points?\s*(?:=|equals?|is)\s*(\d+)",
|
|
144
|
-
lambda m: f'"Story Points" = {m.group(1)}',
|
|
145
|
-
),
|
|
146
|
-
# Time comparisons for custom fields
|
|
147
|
-
(
|
|
148
|
-
r"created\s+(?:after|since)\s+(\d{4}-\d{2}-\d{2})",
|
|
149
|
-
lambda m: f'created >= "{m.group(1)}"',
|
|
150
|
-
),
|
|
151
|
-
(r"created\s+before\s+(\d{4}-\d{2}-\d{2})", lambda m: f'created < "{m.group(1)}"'),
|
|
152
|
-
(
|
|
153
|
-
r"updated\s+(?:after|since)\s+(\d{4}-\d{2}-\d{2})",
|
|
154
|
-
lambda m: f'updated >= "{m.group(1)}"',
|
|
155
|
-
),
|
|
156
|
-
(r"updated\s+before\s+(\d{4}-\d{2}-\d{2})", lambda m: f'updated < "{m.group(1)}"'),
|
|
157
|
-
# Assignee patterns
|
|
158
|
-
(
|
|
159
|
-
r"assigned to\s+([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+)",
|
|
160
|
-
lambda m: f'assignee = "{m.group(1)}"',
|
|
161
|
-
),
|
|
162
|
-
(r'assigned to\s+"([^"]+)"', lambda m: f'assignee = "{m.group(1)}"'),
|
|
163
|
-
# Exact phrase search
|
|
164
|
-
(r'"([^"]+)"', lambda m: f'text ~ "{m.group(1)}"'),
|
|
165
|
-
]
|
|
166
|
-
|
|
167
|
-
# Label mappings
|
|
168
|
-
LABEL_MAPPINGS = {
|
|
169
|
-
"security": ["security", "vulnerability", "sec"],
|
|
170
|
-
"performance": ["performance", "perf", "slow"],
|
|
171
|
-
"ui": ["ui", "ux", "frontend"],
|
|
172
|
-
"ux": ["ui", "ux", "frontend"],
|
|
173
|
-
"backend": ["backend", "api", "server"],
|
|
174
|
-
"api": ["backend", "api", "server"],
|
|
175
|
-
"database": ["database", "db", "sql"],
|
|
176
|
-
"testing": ["testing", "test", "qa"],
|
|
177
|
-
"documentation": ["documentation", "docs", "doc"],
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
# Team mappings
|
|
181
|
-
TEAM_PATTERNS = {
|
|
182
|
-
"backend team": 'assignee in membersOf("backend-team")',
|
|
183
|
-
"frontend team": 'assignee in membersOf("frontend-team")',
|
|
184
|
-
"qa team": 'assignee in membersOf("qa-team")',
|
|
185
|
-
"test team": 'assignee in membersOf("qa-team")',
|
|
186
|
-
"security team": 'assignee in membersOf("security-team")',
|
|
187
|
-
"devops team": 'assignee in membersOf("devops-team")',
|
|
188
|
-
"my team": 'assignee in membersOf("dev-team")',
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
# Composite patterns (combine multiple conditions)
|
|
192
|
-
COMPOSITE_PATTERNS = {
|
|
193
|
-
"critical bugs": 'priority = "Critical" AND issuetype = "Bug"',
|
|
194
|
-
"high priority bugs": 'priority = "High" AND issuetype = "Bug"',
|
|
195
|
-
"open bugs": 'issuetype = "Bug" AND resolution = "Unresolved"',
|
|
196
|
-
"my open issues": 'assignee = currentUser() AND resolution = "Unresolved"',
|
|
197
|
-
"overdue tasks": 'issuetype = "Task" AND duedate < now() AND resolution = "Unresolved"',
|
|
198
|
-
"unassigned bugs": 'issuetype = "Bug" AND assignee is EMPTY',
|
|
199
|
-
"blocked stories": 'issuetype = "Story" AND status = "Blocked"',
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
# Order by patterns
|
|
203
|
-
ORDER_PATTERNS = {
|
|
204
|
-
"recent": "ORDER BY created DESC",
|
|
205
|
-
"recently created": "ORDER BY created DESC",
|
|
206
|
-
"latest": "ORDER BY created DESC",
|
|
207
|
-
"newest": "ORDER BY created DESC",
|
|
208
|
-
"oldest": "ORDER BY created ASC",
|
|
209
|
-
"urgent": "ORDER BY priority DESC, created DESC",
|
|
210
|
-
"by priority": "ORDER BY priority DESC",
|
|
211
|
-
"priority": "ORDER BY priority DESC",
|
|
212
|
-
"due date": "ORDER BY duedate ASC",
|
|
213
|
-
"by due date": "ORDER BY duedate ASC",
|
|
214
|
-
"updated": "ORDER BY updated DESC",
|
|
215
|
-
"recently updated": "ORDER BY updated DESC",
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
def generate_jql_from_templates(query: str) -> str:
|
|
220
|
-
"""
|
|
221
|
-
Generate JQL query from natural language using templates.
|
|
222
|
-
|
|
223
|
-
Args:
|
|
224
|
-
query: Natural language query
|
|
225
|
-
|
|
226
|
-
Returns:
|
|
227
|
-
Valid JQL query string
|
|
228
|
-
"""
|
|
229
|
-
import re
|
|
230
|
-
|
|
231
|
-
query_lower = query.lower()
|
|
232
|
-
jql_parts = []
|
|
233
|
-
used_templates = set()
|
|
234
|
-
|
|
235
|
-
# Check for exact phrase matches first (most specific)
|
|
236
|
-
for pattern, jql in JQL_TEMPLATES.items():
|
|
237
|
-
if pattern in query_lower and pattern not in used_templates:
|
|
238
|
-
jql_parts.append(jql)
|
|
239
|
-
used_templates.add(pattern)
|
|
240
|
-
# Mark overlapping patterns as used
|
|
241
|
-
break # Use only the first match to avoid duplicates
|
|
242
|
-
|
|
243
|
-
# If no template matched, check composite patterns
|
|
244
|
-
if not jql_parts:
|
|
245
|
-
for pattern, jql in COMPOSITE_PATTERNS.items():
|
|
246
|
-
if pattern in query_lower:
|
|
247
|
-
jql_parts.append(jql)
|
|
248
|
-
break
|
|
249
|
-
|
|
250
|
-
# Apply regex patterns
|
|
251
|
-
for pattern, generator in REGEX_PATTERNS:
|
|
252
|
-
match = re.search(pattern, query, re.IGNORECASE)
|
|
253
|
-
if match:
|
|
254
|
-
jql_part = generator(match)
|
|
255
|
-
# Avoid duplicates
|
|
256
|
-
if jql_part not in jql_parts:
|
|
257
|
-
jql_parts.append(jql_part)
|
|
258
|
-
|
|
259
|
-
# Handle labels
|
|
260
|
-
labels_to_add = set()
|
|
261
|
-
for keyword, labels in LABEL_MAPPINGS.items():
|
|
262
|
-
if keyword in query_lower:
|
|
263
|
-
labels_to_add.update(labels)
|
|
264
|
-
|
|
265
|
-
if labels_to_add:
|
|
266
|
-
labels_str = ", ".join(f'"{label}"' for label in labels_to_add)
|
|
267
|
-
jql_parts.append(f"labels in ({labels_str})")
|
|
268
|
-
|
|
269
|
-
# Handle teams
|
|
270
|
-
for team_pattern, jql in TEAM_PATTERNS.items():
|
|
271
|
-
if team_pattern in query_lower:
|
|
272
|
-
jql_parts.append(jql)
|
|
273
|
-
break
|
|
274
|
-
|
|
275
|
-
# Build the final JQL - no fallbacks, explicit mapping only
|
|
276
|
-
if jql_parts:
|
|
277
|
-
# Combine with AND by default
|
|
278
|
-
if " or " in query_lower:
|
|
279
|
-
jql = " OR ".join(jql_parts)
|
|
280
|
-
else:
|
|
281
|
-
jql = " AND ".join(jql_parts)
|
|
282
|
-
else:
|
|
283
|
-
# If no templates match, return a simple default query
|
|
284
|
-
jql = "created >= -30d"
|
|
285
|
-
|
|
286
|
-
# Add ordering
|
|
287
|
-
order_clause = ""
|
|
288
|
-
for order_pattern, order_jql in ORDER_PATTERNS.items():
|
|
289
|
-
if order_pattern in query_lower:
|
|
290
|
-
order_clause = f" {order_jql}"
|
|
291
|
-
break
|
|
292
|
-
|
|
293
|
-
# Default ordering if none specified
|
|
294
|
-
if not order_clause:
|
|
295
|
-
order_clause = " ORDER BY updated DESC"
|
|
296
|
-
|
|
297
|
-
jql += order_clause
|
|
298
|
-
|
|
299
|
-
return jql
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""
|
|
5
|
+
JQL Template System for GAIA Orchestrator Agent.
|
|
6
|
+
Provides templates and patterns for generating valid JQL queries from natural language.
|
|
7
|
+
|
|
8
|
+
Reference: https://support.atlassian.com/jira-service-management-cloud/docs/what-is-advanced-search-in-jira-cloud/
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# JQL Templates for common patterns
|
|
12
|
+
JQL_TEMPLATES = {
|
|
13
|
+
# Issue Types (always quote values)
|
|
14
|
+
"bug": 'issuetype = "Bug"',
|
|
15
|
+
"bugs": 'issuetype = "Bug"',
|
|
16
|
+
"story": 'issuetype = "Story"',
|
|
17
|
+
"stories": 'issuetype = "Story"',
|
|
18
|
+
"task": 'issuetype = "Task"',
|
|
19
|
+
"tasks": 'issuetype = "Task"',
|
|
20
|
+
"epic": 'issuetype = "Epic"',
|
|
21
|
+
"epics": 'issuetype = "Epic"',
|
|
22
|
+
"sub-task": 'issuetype = "Sub-task"',
|
|
23
|
+
"subtask": 'issuetype = "Sub-task"',
|
|
24
|
+
# Priority Levels (always quote values)
|
|
25
|
+
"blocker": 'priority = "Blocker"',
|
|
26
|
+
"critical": 'priority = "Critical"',
|
|
27
|
+
"high priority": 'priority = "High"',
|
|
28
|
+
"high-priority": 'priority = "High"',
|
|
29
|
+
"medium priority": 'priority = "Medium"',
|
|
30
|
+
"low priority": 'priority = "Low"',
|
|
31
|
+
"urgent": 'priority in ("Blocker", "Critical")',
|
|
32
|
+
# Status Values (always quote values)
|
|
33
|
+
"open": 'resolution = "Unresolved"',
|
|
34
|
+
"unresolved": 'resolution = "Unresolved"',
|
|
35
|
+
"resolved": 'resolution != "Unresolved"',
|
|
36
|
+
"closed": 'status = "Closed"',
|
|
37
|
+
"done": 'status = "Done"',
|
|
38
|
+
"in progress": 'status = "In Progress"',
|
|
39
|
+
"in-progress": 'status = "In Progress"',
|
|
40
|
+
"todo": 'status = "To Do"',
|
|
41
|
+
"to do": 'status = "To Do"',
|
|
42
|
+
"blocked": 'status = "Blocked"',
|
|
43
|
+
# Assignment Patterns (using functions)
|
|
44
|
+
"my issues": "assignee = currentUser() OR reporter = currentUser()",
|
|
45
|
+
"assigned to me": "assignee = currentUser()",
|
|
46
|
+
"unassigned": "assignee is EMPTY",
|
|
47
|
+
"no assignee": "assignee is EMPTY",
|
|
48
|
+
"reported by me": "reporter = currentUser()",
|
|
49
|
+
"i reported": "reporter = currentUser()",
|
|
50
|
+
"watching": "watcher = currentUser()",
|
|
51
|
+
"i'm watching": "watcher = currentUser()",
|
|
52
|
+
# Time Functions (proper date functions)
|
|
53
|
+
"created today": "created >= startOfDay()",
|
|
54
|
+
"today's": "created >= startOfDay()",
|
|
55
|
+
"created yesterday": "created >= startOfDay(-1d) AND created < startOfDay()",
|
|
56
|
+
"created this week": "created >= startOfWeek()",
|
|
57
|
+
"this week": "created >= startOfWeek()",
|
|
58
|
+
"created last week": "created >= startOfWeek(-1w) AND created < startOfWeek()",
|
|
59
|
+
"last week": "created >= startOfWeek(-1w) AND created < startOfWeek()",
|
|
60
|
+
"created this month": "created >= startOfMonth()",
|
|
61
|
+
"this month": "created >= startOfMonth()",
|
|
62
|
+
"created last month": "created >= startOfMonth(-1M) AND created < startOfMonth()",
|
|
63
|
+
"last month": "created >= startOfMonth(-1M) AND created < startOfMonth()",
|
|
64
|
+
"last 24 hours": "created >= -24h",
|
|
65
|
+
"last 7 days": "created >= -7d",
|
|
66
|
+
"past week": "created >= -7d",
|
|
67
|
+
"last 30 days": "created >= -30d",
|
|
68
|
+
"past month": "created >= -30d",
|
|
69
|
+
"last 90 days": "created >= -90d",
|
|
70
|
+
"last quarter": "created >= -90d",
|
|
71
|
+
# Updated Time Patterns
|
|
72
|
+
"updated today": "updated >= startOfDay()",
|
|
73
|
+
"recently updated": "updated >= -7d",
|
|
74
|
+
"recent changes": "updated >= -7d",
|
|
75
|
+
"updated this week": "updated >= startOfWeek()",
|
|
76
|
+
"stale": "updated < -30d",
|
|
77
|
+
"not recently updated": "updated < -30d",
|
|
78
|
+
# Sprint Patterns (Agile)
|
|
79
|
+
"current sprint": "sprint in openSprints()",
|
|
80
|
+
"active sprint": "sprint in openSprints()",
|
|
81
|
+
"last sprint": "sprint in closedSprints()",
|
|
82
|
+
"previous sprint": "sprint in closedSprints()",
|
|
83
|
+
"future sprint": "sprint in futureSprints()",
|
|
84
|
+
"no sprint": "sprint is EMPTY",
|
|
85
|
+
"backlog": "sprint is EMPTY",
|
|
86
|
+
# Due Date Patterns
|
|
87
|
+
"overdue": 'duedate < now() AND resolution = "Unresolved"',
|
|
88
|
+
"past due": 'duedate < now() AND resolution = "Unresolved"',
|
|
89
|
+
"due today": "duedate = startOfDay()",
|
|
90
|
+
"due this week": "duedate >= startOfWeek() AND duedate <= endOfWeek()",
|
|
91
|
+
"due soon": "duedate >= now() AND duedate <= 7d",
|
|
92
|
+
"no due date": "duedate is EMPTY",
|
|
93
|
+
# Fix Version Patterns
|
|
94
|
+
"no fix version": "fixVersion is EMPTY",
|
|
95
|
+
"unscheduled": "fixVersion is EMPTY",
|
|
96
|
+
"released": "fixVersion in releasedVersions()",
|
|
97
|
+
"unreleased": "fixVersion in unreleasedVersions()",
|
|
98
|
+
# Component Patterns
|
|
99
|
+
"no component": "component is EMPTY",
|
|
100
|
+
# Epic Link Patterns
|
|
101
|
+
"no epic": '"Epic Link" is EMPTY',
|
|
102
|
+
# Comments and Attachments
|
|
103
|
+
"has comments": 'comment ~ "*"',
|
|
104
|
+
"with comments": 'comment ~ "*"',
|
|
105
|
+
"no comments": "comment is EMPTY",
|
|
106
|
+
"has attachments": "attachments is not EMPTY",
|
|
107
|
+
"with attachments": "attachments is not EMPTY",
|
|
108
|
+
"no attachments": "attachments is EMPTY",
|
|
109
|
+
# Story Points (Agile)
|
|
110
|
+
"no story points": '"Story Points" is EMPTY',
|
|
111
|
+
"unestimated": '"Story Points" is EMPTY',
|
|
112
|
+
# Common explicit queries
|
|
113
|
+
"all issues": "created >= -90d",
|
|
114
|
+
"show all": "created >= -90d",
|
|
115
|
+
"show me all": "created >= -90d",
|
|
116
|
+
"list all": "created >= -90d",
|
|
117
|
+
"everything": "created >= -90d",
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# Complex patterns that need regex matching
|
|
121
|
+
REGEX_PATTERNS = [
|
|
122
|
+
# Project patterns
|
|
123
|
+
(r"project\s+([A-Z0-9]+)", lambda m: f"project = {m.group(1).upper()}"),
|
|
124
|
+
(r"in\s+([A-Z0-9]+)\s+project", lambda m: f"project = {m.group(1).upper()}"),
|
|
125
|
+
# Story points comparisons
|
|
126
|
+
(
|
|
127
|
+
r"story points?\s*(?:>|greater than)\s*(\d+)",
|
|
128
|
+
lambda m: f'"Story Points" > {m.group(1)}',
|
|
129
|
+
),
|
|
130
|
+
(
|
|
131
|
+
r"story points?\s*(?:<|less than)\s*(\d+)",
|
|
132
|
+
lambda m: f'"Story Points" < {m.group(1)}',
|
|
133
|
+
),
|
|
134
|
+
(
|
|
135
|
+
r"story points?\s*(?:>=|at least)\s*(\d+)",
|
|
136
|
+
lambda m: f'"Story Points" >= {m.group(1)}',
|
|
137
|
+
),
|
|
138
|
+
(
|
|
139
|
+
r"story points?\s*(?:<=|at most)\s*(\d+)",
|
|
140
|
+
lambda m: f'"Story Points" <= {m.group(1)}',
|
|
141
|
+
),
|
|
142
|
+
(
|
|
143
|
+
r"story points?\s*(?:=|equals?|is)\s*(\d+)",
|
|
144
|
+
lambda m: f'"Story Points" = {m.group(1)}',
|
|
145
|
+
),
|
|
146
|
+
# Time comparisons for custom fields
|
|
147
|
+
(
|
|
148
|
+
r"created\s+(?:after|since)\s+(\d{4}-\d{2}-\d{2})",
|
|
149
|
+
lambda m: f'created >= "{m.group(1)}"',
|
|
150
|
+
),
|
|
151
|
+
(r"created\s+before\s+(\d{4}-\d{2}-\d{2})", lambda m: f'created < "{m.group(1)}"'),
|
|
152
|
+
(
|
|
153
|
+
r"updated\s+(?:after|since)\s+(\d{4}-\d{2}-\d{2})",
|
|
154
|
+
lambda m: f'updated >= "{m.group(1)}"',
|
|
155
|
+
),
|
|
156
|
+
(r"updated\s+before\s+(\d{4}-\d{2}-\d{2})", lambda m: f'updated < "{m.group(1)}"'),
|
|
157
|
+
# Assignee patterns
|
|
158
|
+
(
|
|
159
|
+
r"assigned to\s+([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+)",
|
|
160
|
+
lambda m: f'assignee = "{m.group(1)}"',
|
|
161
|
+
),
|
|
162
|
+
(r'assigned to\s+"([^"]+)"', lambda m: f'assignee = "{m.group(1)}"'),
|
|
163
|
+
# Exact phrase search
|
|
164
|
+
(r'"([^"]+)"', lambda m: f'text ~ "{m.group(1)}"'),
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
# Label mappings
|
|
168
|
+
LABEL_MAPPINGS = {
|
|
169
|
+
"security": ["security", "vulnerability", "sec"],
|
|
170
|
+
"performance": ["performance", "perf", "slow"],
|
|
171
|
+
"ui": ["ui", "ux", "frontend"],
|
|
172
|
+
"ux": ["ui", "ux", "frontend"],
|
|
173
|
+
"backend": ["backend", "api", "server"],
|
|
174
|
+
"api": ["backend", "api", "server"],
|
|
175
|
+
"database": ["database", "db", "sql"],
|
|
176
|
+
"testing": ["testing", "test", "qa"],
|
|
177
|
+
"documentation": ["documentation", "docs", "doc"],
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
# Team mappings
|
|
181
|
+
TEAM_PATTERNS = {
|
|
182
|
+
"backend team": 'assignee in membersOf("backend-team")',
|
|
183
|
+
"frontend team": 'assignee in membersOf("frontend-team")',
|
|
184
|
+
"qa team": 'assignee in membersOf("qa-team")',
|
|
185
|
+
"test team": 'assignee in membersOf("qa-team")',
|
|
186
|
+
"security team": 'assignee in membersOf("security-team")',
|
|
187
|
+
"devops team": 'assignee in membersOf("devops-team")',
|
|
188
|
+
"my team": 'assignee in membersOf("dev-team")',
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
# Composite patterns (combine multiple conditions)
|
|
192
|
+
COMPOSITE_PATTERNS = {
|
|
193
|
+
"critical bugs": 'priority = "Critical" AND issuetype = "Bug"',
|
|
194
|
+
"high priority bugs": 'priority = "High" AND issuetype = "Bug"',
|
|
195
|
+
"open bugs": 'issuetype = "Bug" AND resolution = "Unresolved"',
|
|
196
|
+
"my open issues": 'assignee = currentUser() AND resolution = "Unresolved"',
|
|
197
|
+
"overdue tasks": 'issuetype = "Task" AND duedate < now() AND resolution = "Unresolved"',
|
|
198
|
+
"unassigned bugs": 'issuetype = "Bug" AND assignee is EMPTY',
|
|
199
|
+
"blocked stories": 'issuetype = "Story" AND status = "Blocked"',
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
# Order by patterns
|
|
203
|
+
ORDER_PATTERNS = {
|
|
204
|
+
"recent": "ORDER BY created DESC",
|
|
205
|
+
"recently created": "ORDER BY created DESC",
|
|
206
|
+
"latest": "ORDER BY created DESC",
|
|
207
|
+
"newest": "ORDER BY created DESC",
|
|
208
|
+
"oldest": "ORDER BY created ASC",
|
|
209
|
+
"urgent": "ORDER BY priority DESC, created DESC",
|
|
210
|
+
"by priority": "ORDER BY priority DESC",
|
|
211
|
+
"priority": "ORDER BY priority DESC",
|
|
212
|
+
"due date": "ORDER BY duedate ASC",
|
|
213
|
+
"by due date": "ORDER BY duedate ASC",
|
|
214
|
+
"updated": "ORDER BY updated DESC",
|
|
215
|
+
"recently updated": "ORDER BY updated DESC",
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def generate_jql_from_templates(query: str) -> str:
|
|
220
|
+
"""
|
|
221
|
+
Generate JQL query from natural language using templates.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
query: Natural language query
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
Valid JQL query string
|
|
228
|
+
"""
|
|
229
|
+
import re
|
|
230
|
+
|
|
231
|
+
query_lower = query.lower()
|
|
232
|
+
jql_parts = []
|
|
233
|
+
used_templates = set()
|
|
234
|
+
|
|
235
|
+
# Check for exact phrase matches first (most specific)
|
|
236
|
+
for pattern, jql in JQL_TEMPLATES.items():
|
|
237
|
+
if pattern in query_lower and pattern not in used_templates:
|
|
238
|
+
jql_parts.append(jql)
|
|
239
|
+
used_templates.add(pattern)
|
|
240
|
+
# Mark overlapping patterns as used
|
|
241
|
+
break # Use only the first match to avoid duplicates
|
|
242
|
+
|
|
243
|
+
# If no template matched, check composite patterns
|
|
244
|
+
if not jql_parts:
|
|
245
|
+
for pattern, jql in COMPOSITE_PATTERNS.items():
|
|
246
|
+
if pattern in query_lower:
|
|
247
|
+
jql_parts.append(jql)
|
|
248
|
+
break
|
|
249
|
+
|
|
250
|
+
# Apply regex patterns
|
|
251
|
+
for pattern, generator in REGEX_PATTERNS:
|
|
252
|
+
match = re.search(pattern, query, re.IGNORECASE)
|
|
253
|
+
if match:
|
|
254
|
+
jql_part = generator(match)
|
|
255
|
+
# Avoid duplicates
|
|
256
|
+
if jql_part not in jql_parts:
|
|
257
|
+
jql_parts.append(jql_part)
|
|
258
|
+
|
|
259
|
+
# Handle labels
|
|
260
|
+
labels_to_add = set()
|
|
261
|
+
for keyword, labels in LABEL_MAPPINGS.items():
|
|
262
|
+
if keyword in query_lower:
|
|
263
|
+
labels_to_add.update(labels)
|
|
264
|
+
|
|
265
|
+
if labels_to_add:
|
|
266
|
+
labels_str = ", ".join(f'"{label}"' for label in labels_to_add)
|
|
267
|
+
jql_parts.append(f"labels in ({labels_str})")
|
|
268
|
+
|
|
269
|
+
# Handle teams
|
|
270
|
+
for team_pattern, jql in TEAM_PATTERNS.items():
|
|
271
|
+
if team_pattern in query_lower:
|
|
272
|
+
jql_parts.append(jql)
|
|
273
|
+
break
|
|
274
|
+
|
|
275
|
+
# Build the final JQL - no fallbacks, explicit mapping only
|
|
276
|
+
if jql_parts:
|
|
277
|
+
# Combine with AND by default
|
|
278
|
+
if " or " in query_lower:
|
|
279
|
+
jql = " OR ".join(jql_parts)
|
|
280
|
+
else:
|
|
281
|
+
jql = " AND ".join(jql_parts)
|
|
282
|
+
else:
|
|
283
|
+
# If no templates match, return a simple default query
|
|
284
|
+
jql = "created >= -30d"
|
|
285
|
+
|
|
286
|
+
# Add ordering
|
|
287
|
+
order_clause = ""
|
|
288
|
+
for order_pattern, order_jql in ORDER_PATTERNS.items():
|
|
289
|
+
if order_pattern in query_lower:
|
|
290
|
+
order_clause = f" {order_jql}"
|
|
291
|
+
break
|
|
292
|
+
|
|
293
|
+
# Default ordering if none specified
|
|
294
|
+
if not order_clause:
|
|
295
|
+
order_clause = " ORDER BY updated DESC"
|
|
296
|
+
|
|
297
|
+
jql += order_clause
|
|
298
|
+
|
|
299
|
+
return jql
|
gaia/agents/routing/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
-
# SPDX-License-Identifier: MIT
|
|
3
|
-
"""Routing agent for intelligent agent selection and disambiguation."""
|
|
4
|
-
|
|
5
|
-
from .agent import RoutingAgent
|
|
6
|
-
|
|
7
|
-
__all__ = ["RoutingAgent"]
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""Routing agent for intelligent agent selection and disambiguation."""
|
|
4
|
+
|
|
5
|
+
from .agent import RoutingAgent
|
|
6
|
+
|
|
7
|
+
__all__ = ["RoutingAgent"]
|