Skip to content

Commit e6d3298

Browse files
authored
Merge pull request #108 from MLAI-AUS-Inc/codex/domain-scan-routing-fix
Codex/domain scan routing fix
2 parents 599ff68 + 27c68a9 commit e6d3298

File tree

3 files changed

+363
-34
lines changed

3 files changed

+363
-34
lines changed

roo-standalone/roo/skills/executor.py

Lines changed: 131 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,60 @@ async def _execute_connect_users(
10031003
# Note: Vector search is disabled until API endpoint is implemented
10041004
# For now, fall back to LLM-based execution
10051005
return await self._execute_with_llm(skill, text, params, user_id)
1006+
1007+
async def _save_content_factory_pending_intent(
1008+
self,
1009+
api_client: Any,
1010+
user_id: str,
1011+
params: dict,
1012+
text: str,
1013+
channel_id: Optional[str],
1014+
thread_ts: Optional[str],
1015+
) -> None:
1016+
"""Persist the original content request so GitHub auth/repo selection can resume it."""
1017+
if params.get("confirmed"):
1018+
return
1019+
1020+
intent_data = json.dumps({
1021+
"skill": "content-factory",
1022+
"params": params,
1023+
"text": text,
1024+
"channel": channel_id,
1025+
"ts": thread_ts,
1026+
})
1027+
await api_client.save_pending_intent(user_id, intent_data)
1028+
1029+
def _get_connected_domain_info(
1030+
self,
1031+
connected_domains: List[dict],
1032+
domain: Optional[str],
1033+
) -> Optional[dict]:
1034+
"""Return the connected domain record for the requested domain."""
1035+
if not domain or not connected_domains:
1036+
return None
1037+
1038+
return next(
1039+
(domain_info for domain_info in connected_domains if domain_info.get("domain") == domain),
1040+
None,
1041+
)
1042+
1043+
def _resolve_content_factory_repo_name(
1044+
self,
1045+
integration: dict,
1046+
connected_domains: List[dict],
1047+
domain: Optional[str],
1048+
) -> tuple[Optional[str], Optional[dict]]:
1049+
"""Resolve the repo Roo should use for content-factory flows."""
1050+
domain_info = self._get_connected_domain_info(connected_domains, domain)
1051+
1052+
if domain:
1053+
return (
1054+
integration.get("domain_github_repo")
1055+
or (domain_info or {}).get("github_repo"),
1056+
domain_info,
1057+
)
1058+
1059+
return integration.get("github_repo"), domain_info
10061060

10071061
async def _execute_content_factory(
10081062
self,
@@ -1182,15 +1236,14 @@ async def _execute_content_factory(
11821236

11831237
# Save pending intent before asking for auth
11841238
# Critically: Do NOT overwrite the intent if we are just confirming requirements (which has no domain/topic)
1185-
if not params.get("confirmed"):
1186-
intent_data = json.dumps({
1187-
"skill": "content-factory",
1188-
"params": params,
1189-
"text": text,
1190-
"channel": channel_id,
1191-
"ts": thread_ts
1192-
})
1193-
await api_client.save_pending_intent(user_id, intent_data)
1239+
await self._save_content_factory_pending_intent(
1240+
api_client,
1241+
user_id,
1242+
params,
1243+
text,
1244+
channel_id,
1245+
thread_ts,
1246+
)
11941247

11951248
if channel_id:
11961249
post_message(channel_id, "Please connect GitHub", thread_ts=thread_ts, blocks=blocks)
@@ -1232,19 +1285,60 @@ async def _execute_content_factory(
12321285
integration = domain_integration
12331286
connected_domains = integration.get("connected_domains", connected_domains)
12341287

1235-
# Look up repo from connected_domains
1236-
repo_name = None
1237-
domain_info = None
1238-
if domain and connected_domains:
1239-
domain_info = next(
1240-
(d for d in connected_domains if d.get("domain") == domain), None
1288+
repo_name, domain_info = self._resolve_content_factory_repo_name(
1289+
integration,
1290+
connected_domains,
1291+
domain,
1292+
)
1293+
1294+
if domain and integration.get("needs_github_auth"):
1295+
auth_url = integration.get("oauth_url")
1296+
if not auth_url:
1297+
auth_response = await api_client.get_github_auth_url(user_id, domain=domain)
1298+
auth_url = auth_response.get("auth_url")
1299+
1300+
if not auth_url:
1301+
return "Sorry mate, I couldn't get the authorization URL. Try again?"
1302+
1303+
await self._save_content_factory_pending_intent(
1304+
api_client,
1305+
user_id,
1306+
params,
1307+
text,
1308+
channel_id,
1309+
thread_ts,
12411310
)
1242-
if domain_info:
1243-
repo_name = domain_info.get("github_repo")
12441311

1245-
# Fallback to top-level github_repo if domain not in connected_domains
1246-
if not repo_name:
1247-
repo_name = integration.get("github_repo")
1312+
blocks = [
1313+
{
1314+
"type": "section",
1315+
"text": {
1316+
"type": "mrkdwn",
1317+
"text": f"⚠️ GitHub isn't connected for *{domain}*.\nClick below to connect your GitHub repo for this domain."
1318+
}
1319+
},
1320+
{
1321+
"type": "actions",
1322+
"elements": [
1323+
{
1324+
"type": "button",
1325+
"text": {
1326+
"type": "plain_text",
1327+
"text": "Connect GitHub for " + domain,
1328+
"emoji": True
1329+
},
1330+
"url": auth_url,
1331+
"action_id": "connect_github",
1332+
"style": "primary"
1333+
}
1334+
]
1335+
}
1336+
]
1337+
1338+
if channel_id:
1339+
post_message(channel_id, f"GitHub not connected for {domain}", thread_ts=thread_ts, blocks=blocks)
1340+
return f"GitHub isn't connected for {domain}. Click the button above to connect, then try again! 🔌"
1341+
return f"GitHub isn't connected for {domain}. Connect here: {auth_url}"
12481342

12491343
# No repo at all — prompt to connect
12501344
if not repo_name:
@@ -1254,12 +1348,26 @@ async def _execute_content_factory(
12541348
if not auth_url:
12551349
return "Sorry mate, I couldn't get the authorization URL. Try again?"
12561350

1351+
await self._save_content_factory_pending_intent(
1352+
api_client,
1353+
user_id,
1354+
params,
1355+
text,
1356+
channel_id,
1357+
thread_ts,
1358+
)
1359+
12571360
blocks = [
12581361
{
12591362
"type": "section",
12601363
"text": {
12611364
"type": "mrkdwn",
1262-
"text": "I see you're connected, but no repository is selected. Click below to choose one."
1365+
"text": (
1366+
f"I see you're connected for *{domain}*, but no repository is selected for that domain. "
1367+
"Click below to choose one."
1368+
if domain
1369+
else "I see you're connected, but no repository is selected. Click below to choose one."
1370+
)
12631371
}
12641372
},
12651373
{
@@ -2146,7 +2254,7 @@ def _resolve_points_action(self, params: dict, text: str) -> str:
21462254
text_lower = text.lower()
21472255
explicit_points_request = "request" in text_lower and "point" in text_lower and "reward" not in text_lower
21482256

2149-
if explicit_points_request and action in ("", "task", "award", "award_points"):
2257+
if explicit_points_request:
21502258
return "request_points"
21512259

21522260
if action == "book":
@@ -2201,6 +2309,7 @@ def _extract_points_request_reason(self, text: str, fallback_reason: str = "") -
22012309

22022310
patterns = (
22032311
r"request\s+\d+\s*(?:points?|pts?)\s+for\s+(.+)",
2312+
r"(?:i\s*(?:am|'m)\s+)?requesting\s+\d+\s*(?:points?|pts?)\s+for\s+(.+)",
22042313
r"(?:can i|get me|i(?:'d| would)? like)\s+\d+\s*(?:points?|pts?)\s+for\s+(.+)",
22052314
)
22062315
for pattern in patterns:

0 commit comments

Comments
 (0)