Support selecting agent context for screenshots

This commit is contained in:
2025-10-15 04:40:21 -06:00
parent a86231c8f5
commit 41c52590f4
6 changed files with 291 additions and 56 deletions

View File

@@ -5852,14 +5852,22 @@ def get_agents():
if info.get('is_script_agent'):
continue
d = dict(info)
mode = _normalize_service_mode(d.get('service_mode'), aid)
d['service_mode'] = mode
ts = d.get('collector_active_ts') or 0
d['collector_active'] = bool(ts and (now - float(ts) < 130))
host = (d.get('hostname') or '').strip() or 'unknown'
# Select best record per hostname: highest last_seen wins
cur = seen_by_hostname.get(host)
bucket = seen_by_hostname.setdefault(host, {})
cur = bucket.get(mode)
if not cur or int(d.get('last_seen') or 0) >= int(cur[1].get('last_seen') or 0):
seen_by_hostname[host] = (aid, d)
out = { aid: d for host, (aid, d) in seen_by_hostname.items() }
bucket[mode] = (aid, d)
out = {}
for host, bucket in seen_by_hostname.items():
for mode, (aid, d) in bucket.items():
d = dict(d)
d['hostname'] = (d.get('hostname') or '').strip() or host
d['service_mode'] = mode
out[aid] = d
return jsonify(out)
@@ -5869,6 +5877,28 @@ def get_agents():
## dayjs_to_ts removed; scheduling parsing now lives in job_scheduler
def _normalize_service_mode(value, agent_id=None):
try:
if isinstance(value, str):
text = value.strip().lower()
else:
text = ''
except Exception:
text = ''
if not text and agent_id:
try:
aid = agent_id.lower()
if '-svc-' in aid or aid.endswith('-svc'):
return 'system'
except Exception:
pass
if text in {'system', 'svc', 'service', 'system_service'}:
return 'system'
if text in {'interactive', 'currentuser', 'user', 'current_user'}:
return 'currentuser'
return 'currentuser'
def _is_empty(v):
return v is None or v == '' or v == [] or v == {}
@@ -7252,12 +7282,15 @@ def handle_collector_status(data):
if not agent_id:
return
mode = _normalize_service_mode((data or {}).get('service_mode'), agent_id)
rec = registered_agents.setdefault(agent_id, {})
rec['agent_id'] = agent_id
if hostname:
rec['hostname'] = hostname
if active:
rec['collector_active_ts'] = time.time()
if mode:
rec['service_mode'] = mode
# Helper: decide if a reported user string is a real interactive user
def _is_valid_interactive_user(s: str) -> bool:
@@ -7491,12 +7524,14 @@ def connect_agent(data):
except Exception:
pass
service_mode = _normalize_service_mode((data or {}).get("service_mode"), agent_id)
rec = registered_agents.setdefault(agent_id, {})
rec["agent_id"] = agent_id
rec["hostname"] = rec.get("hostname", "unknown")
rec["agent_operating_system"] = rec.get("agent_operating_system", "-")
rec["last_seen"] = int(time.time())
rec["status"] = "provisioned" if agent_id in agent_configurations else "orphaned"
rec["service_mode"] = service_mode
# Flag script agents so they can be filtered out elsewhere if desired
try:
if isinstance(agent_id, str) and agent_id.lower().endswith('-script'):
@@ -7524,6 +7559,8 @@ def on_agent_heartbeat(data):
return
hostname = data.get("hostname")
incoming_mode = _normalize_service_mode(data.get("service_mode"), agent_id)
if hostname:
# Avoid duplicate entries per-hostname by collapsing to the newest agent_id.
# Prefer non-script agents; we do not surface script agents in /api/agents.
@@ -7537,6 +7574,9 @@ def on_agent_heartbeat(data):
if aid == agent_id:
continue
if info.get("hostname") == hostname:
existing_mode = _normalize_service_mode(info.get("service_mode"), aid)
if existing_mode != incoming_mode:
continue
# If the incoming is a script helper and there is a non-script entry, keep non-script
if is_current_script and not info.get('is_script_agent'):
# Do not register duplicate script entry; just update last_seen persistence below
@@ -7561,6 +7601,7 @@ def on_agent_heartbeat(data):
rec["agent_operating_system"] = data.get("agent_operating_system")
rec["last_seen"] = int(data.get("last_seen") or time.time())
rec["status"] = "provisioned" if agent_id in agent_configurations else rec.get("status", "orphaned")
rec["service_mode"] = incoming_mode
# Persist last_seen (and agent_id) into DB keyed by hostname so it survives restarts.
try:
_persist_last_seen(rec.get("hostname") or hostname, rec["last_seen"], rec.get("agent_id"))