all the changes
This commit is contained in:
1 parent
94f30165f9
commit
f30adf05af
35 files changed
+2979
-1607
No files matched your search
@@ -16,46 +16,49 @@ import needle
|
||||
PORT = int(os.environ.get("NEEDLE_PORT", 5005))
|
||||
HOST = os.environ.get("NEEDLE_HOST", "0.0.0.0")
|
||||
|
||||
# --- Define Triage Tools for Needle 3 ---
|
||||
# --- Cause-level triage tools ---
|
||||
# These deliberately do not restate what the event already carries (status
|
||||
# code, is_error, severity). Each one is a judgement about *why* it happened
|
||||
# or *who should care*, which is what an alert reader needs.
|
||||
@needle.tool
|
||||
def report_client_javascript_crash(service: str, message: str, url: str):
|
||||
"""Report client-side JavaScript crash or error logged by browser RUM."""
|
||||
return {"action": "client_js_crash", "service": service, "message": message, "url": url}
|
||||
def report_scanner_probe(service: str, path: str, status_code: int):
|
||||
"""Automated scan or exploit crawler requesting sensitive or nonexistent paths such as .env, wp-admin, .git, phpmyadmin. Applies whatever status the probe received, including 500 or 502."""
|
||||
return {"action": "scanner_probe", "service": service, "path": path, "status_code": status_code}
|
||||
|
||||
@needle.tool
|
||||
def alert_vulnerability_probe(scanner: str, target: str, status_code: int):
|
||||
"""Alert on malicious vulnerability scans or exploit crawlers."""
|
||||
return {"action": "security_alert", "scanner": scanner, "target": target, "status_code": status_code}
|
||||
def report_dependency_unreachable(service: str, dependency: str, error_message: str):
|
||||
"""A downstream or upstream service is down, refusing connections, closed the stream (EOF), or returned upstream unavailable."""
|
||||
return {"action": "dependency_unreachable", "service": service, "dependency": dependency, "error": error_message}
|
||||
|
||||
@needle.tool
|
||||
def record_frontend_web_vital(service: str, metric_name: str, duration_ms: int):
|
||||
"""Record RUM performance metrics like TTFB or FCP."""
|
||||
return {"action": "record_vital", "service": service, "metric": metric_name, "ms": duration_ms}
|
||||
def report_client_credential_issue(service: str, route: str, reason: str):
|
||||
"""A caller lacks a valid or unexpired token, for example an unauthenticated client polling an API or a registry pull without login. The caller's fault, not a fault in this service."""
|
||||
return {"action": "client_credential_issue", "service": service, "route": route, "reason": reason}
|
||||
|
||||
@needle.tool
|
||||
def log_missing_resource_404(path: str, host: str):
|
||||
"""Log benign 404 Not Found requests for missing pages or git commits."""
|
||||
return {"action": "log_404", "path": path, "host": host}
|
||||
def report_stale_reference(service: str, path: str):
|
||||
"""Harmless missing resource caused by an old link, removed asset, deleted commit, or dev tooling request."""
|
||||
return {"action": "stale_reference", "service": service, "path": path}
|
||||
|
||||
@needle.tool
|
||||
def report_database_error(service: str, table: str, error_message: str):
|
||||
"""Report database query errors, deadlocks, or connection pool timeouts."""
|
||||
return {"action": "database_error", "service": service, "table": table, "error": error_message}
|
||||
def report_service_defect(service: str, error_message: str):
|
||||
"""A bug in the service's own code: panic, nil dereference, unhandled exception, index out of range, deadlock, or a 500 from a real application route."""
|
||||
return {"action": "service_defect", "service": service, "error": error_message}
|
||||
|
||||
@needle.tool
|
||||
def report_auth_failure(service: str, user_or_token: str, reason: str):
|
||||
"""Report authentication/authorization failure or invalid credentials."""
|
||||
return {"action": "auth_failure", "service": service, "user_or_token": user_or_token, "reason": reason}
|
||||
def report_capacity_saturation(service: str, resource: str, error_message: str):
|
||||
"""Resource exhaustion or overload: timeouts, connection pool exhausted, memory limit exceeded, OOM, queue full."""
|
||||
return {"action": "capacity_saturation", "service": service, "resource": resource, "error": error_message}
|
||||
|
||||
@needle.tool
|
||||
def escalate_backend_outage(service: str, error_message: str):
|
||||
"""Escalate severe backend 5xx crash or unhandled panic to on-call."""
|
||||
return {"action": "escalate_outage", "service": service, "error": error_message}
|
||||
def report_expected_lifecycle(service: str, what: str):
|
||||
"""Normal behaviour that is not a problem: health and readiness checks, keepalive pings, retries, cancellations, client disconnects, redirects, successful requests, routine info logs, web vitals."""
|
||||
return {"action": "expected_lifecycle", "service": service, "what": what}
|
||||
|
||||
@needle.tool
|
||||
def report_unclassified(service: str, summary: str):
|
||||
"""Fallback when the event matches none of the other categories: retries, cancellations, restarts, OOM, health checks, or anything unclear."""
|
||||
return {"action": "unclassified", "service": service, "summary": summary}
|
||||
def report_needs_review(service: str, summary: str):
|
||||
"""Fallback when none of the other categories clearly applies."""
|
||||
return {"action": "needs_review", "service": service, "summary": summary}
|
||||
|
||||
# --- Redaction: nothing PII-bearing should reach the model or the cache ---
|
||||
_REDACTIONS = [
|
||||
@@ -81,14 +84,14 @@ _stats = {"hits": 0, "misses": 0}
|
||||
print(f"Loading Needle 3 model (Cactus-Compute/needle3)...")
|
||||
t0 = time.perf_counter()
|
||||
agent = needle.Needle(tools=[
|
||||
report_client_javascript_crash,
|
||||
alert_vulnerability_probe,
|
||||
record_frontend_web_vital,
|
||||
log_missing_resource_404,
|
||||
report_database_error,
|
||||
report_auth_failure,
|
||||
escalate_backend_outage,
|
||||
report_unclassified
|
||||
report_scanner_probe,
|
||||
report_dependency_unreachable,
|
||||
report_client_credential_issue,
|
||||
report_stale_reference,
|
||||
report_service_defect,
|
||||
report_capacity_saturation,
|
||||
report_expected_lifecycle,
|
||||
report_needs_review,
|
||||
])
|
||||
print(f"Needle 3 loaded in {(time.perf_counter() - t0):.2f}s")
|
||||
|
||||
@@ -116,14 +119,8 @@ class NeedleHandler(BaseHTTPRequestHandler):
|
||||
"model": "Cactus-Compute/needle3",
|
||||
"cache": {**_stats, "size": len(_cache)},
|
||||
"tools": [
|
||||
"client_js_crash",
|
||||
"security_alert",
|
||||
"record_vital",
|
||||
"log_404",
|
||||
"database_error",
|
||||
"auth_failure",
|
||||
"escalate_outage",
|
||||
"unclassified"
|
||||
"scanner_probe", "dependency_unreachable", "client_credential_issue", "stale_reference",
|
||||
"service_defect", "capacity_saturation", "expected_lifecycle", "needs_review"
|
||||
]
|
||||
}
|
||||
self.wfile.write(json.dumps(resp).encode("utf-8"))
|
||||
@@ -193,7 +190,7 @@ class NeedleHandler(BaseHTTPRequestHandler):
|
||||
|
||||
results = res.get("results", [])
|
||||
first_result = results[0] if results and isinstance(results[0], dict) else {}
|
||||
action = first_result.get("action", "unclassified")
|
||||
action = first_result.get("action", "needs_review")
|
||||
|
||||
calls = res.get("function_calls", [])
|
||||
tool_name = calls[0].get("name") if calls else "triage_tool"
|
||||
|
||||
Reference in new issue
Block a user