Files
tracer-cloud--opensre/tools/investigation_registry/prioritization.py
T
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

96 lines
3.4 KiB
Python

"""Action prioritization logic based on sources and keywords."""
from __future__ import annotations
from typing import Any
from core.domain.types.evidence import EvidenceSource
from tools.investigation_registry.actions import get_available_actions
from tools.investigation_registry.models import InvestigationAction
# Deterministic fallback set when no tools match detected sources.
# These are low-cost, always-safe tools that provide broad coverage.
FALLBACK_TOOLS: tuple[str, ...] = ("get_sre_guidance",)
DETERMINISTIC_FALLBACK_REASON = "included as deterministic fallback (no high-confidence match)"
def get_prioritized_actions(
sources: list[EvidenceSource] | None = None,
keywords: list[str] | None = None,
) -> list[InvestigationAction]:
"""Get actions prioritized by relevance to sources and keywords."""
actions, _ = get_prioritized_actions_with_reasons(sources, keywords)
return actions
def get_prioritized_actions_with_reasons(
sources: list[EvidenceSource] | None = None,
keywords: list[str] | None = None,
) -> tuple[list[InvestigationAction], list[dict[str, Any]]]:
"""Get actions prioritized by relevance, with human-readable inclusion reasons.
Returns:
Tuple of (prioritized_actions, inclusion_reasons) where each reason is a dict
with keys: name, score, reasons (list of strings), source, tags.
"""
all_actions = get_available_actions()
if not sources and not keywords:
reasons = [
{
"name": a.name,
"score": 0,
"reasons": ["no source/keyword filters applied"],
"source": a.source,
"tags": list(a.tags),
}
for a in all_actions
]
return all_actions, reasons
scored: list[tuple[InvestigationAction, int, list[str]]] = []
keywords_lower = [kw.lower() for kw in keywords] if keywords else []
for action in all_actions:
score = 0
action_reasons: list[str] = []
if sources and action.source in sources:
score += 2
action_reasons.append(f"source '{action.source}' matches detected sources")
if keywords_lower:
use_cases_text = " ".join(action.use_cases).lower()
matched = [kw for kw in keywords_lower if kw in use_cases_text]
if matched:
score += len(matched)
action_reasons.append(f"keywords matched: {', '.join(matched)}")
if not action_reasons:
action_reasons.append("no source or keyword match")
scored.append((action, score, action_reasons))
scored.sort(key=lambda x: (-x[1], x[0].name))
# Deterministic fallback: if no tool scored above 0, ensure the fallback set
# is included so the investigation has at least one safe tool to call.
top_score = scored[0][1] if scored else 0
if top_score == 0:
for action, _score, action_reasons in scored:
if action.name in FALLBACK_TOOLS:
action_reasons.append(DETERMINISTIC_FALLBACK_REASON)
actions = [action for action, _, _ in scored]
reasons = [
{
"name": action.name,
"score": score,
"reasons": action_reasons,
"source": action.source,
"tags": list(action.tags),
}
for action, score, action_reasons in scored
]
return actions, reasons