Files

789 lines
14 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Dict, List, Literal, Optional
# ---------------------------
# Models (UI-friendly)
# ---------------------------
@dataclass(frozen=True)
class Status:
timestamp: str
ip_count: int
domain_count: int
iface: str
table: str
mark: str
# NOTE: backend uses omitempty for these, so they may be absent.
policy_route_ok: Optional[bool]
route_ok: Optional[bool]
@dataclass(frozen=True)
class CmdResult:
ok: bool
message: str
exit_code: Optional[int] = None
stdout: str = ""
stderr: str = ""
@dataclass(frozen=True)
class LoginState:
state: str
email: str
msg: str
# backend may also provide UI-ready fields
text: str
color: str
@dataclass(frozen=True)
class UnitState:
state: str
@dataclass(frozen=True)
class RoutesTimerState:
enabled: bool
@dataclass(frozen=True)
class TrafficModeStatus:
mode: str
desired_mode: str
applied_mode: str
preferred_iface: str
advanced_active: bool
auto_local_bypass: bool
auto_local_active: bool
ingress_reply_bypass: bool
ingress_reply_active: bool
bypass_candidates: int
force_vpn_subnets: List[str]
force_vpn_uids: List[str]
force_vpn_cgroups: List[str]
force_direct_subnets: List[str]
force_direct_uids: List[str]
force_direct_cgroups: List[str]
overrides_applied: int
cgroup_resolved_uids: int
cgroup_warning: str
active_iface: str
iface_reason: str
rule_mark: bool
rule_full: bool
ingress_rule_present: bool
ingress_nft_active: bool
table_default: bool
probe_ok: bool
probe_message: str
healthy: bool
message: str
@dataclass(frozen=True)
class TrafficInterfaces:
interfaces: List[str]
preferred_iface: str
active_iface: str
iface_reason: str
@dataclass(frozen=True)
class TrafficAppMarksStatus:
vpn_count: int
direct_count: int
message: str
@dataclass(frozen=True)
class TrafficAppMarksResult:
ok: bool
message: str
op: str = ""
target: str = ""
cgroup: str = ""
cgroup_id: int = 0
timeout_sec: int = 0
@dataclass(frozen=True)
class TrafficAppMarkItem:
id: int
target: str # vpn|direct
cgroup: str
cgroup_rel: str
level: int
unit: str
command: str
app_key: str
added_at: str
expires_at: str
remaining_sec: int
@dataclass(frozen=True)
class TrafficAppProfile:
id: str
name: str
app_key: str
command: str
target: str # vpn|direct
ttl_sec: int
vpn_profile: str
created_at: str
updated_at: str
@dataclass(frozen=True)
class TrafficAppProfileSaveResult:
ok: bool
message: str
profile: Optional[TrafficAppProfile] = None
@dataclass(frozen=True)
class TrafficAudit:
ok: bool
message: str
now: str
pretty: str
issues: List[str]
@dataclass(frozen=True)
class TransportClientHealth:
last_check: str
latency_ms: int
last_error: str
@dataclass(frozen=True)
class TransportClient:
id: str
name: str
kind: str
enabled: bool
status: str
iface: str
routing_table: str
mark_hex: str
priority_base: int
capabilities: List[str]
health: TransportClientHealth
config: Dict[str, Any]
updated_at: str
@dataclass(frozen=True)
class TransportHealthRefreshItem:
client_id: str
status: str
queued: bool
reason: str
@dataclass(frozen=True)
class TransportHealthRefreshResult:
ok: bool
message: str
code: str
count: int
queued: int
skipped: int
items: List[TransportHealthRefreshItem]
@dataclass(frozen=True)
class TransportClientHealthSnapshot:
client_id: str
status: str
latency_ms: int
last_error: str
last_check: str
@dataclass(frozen=True)
class TransportPolicyIntent:
selector_type: str
selector_value: str
client_id: str
priority: int = 100
mode: str = "strict"
@dataclass(frozen=True)
class TransportPolicy:
revision: int
intents: List[TransportPolicyIntent]
@dataclass(frozen=True)
class TransportConflict:
key: str
type: str
severity: str
owners: List[str]
reason: str
suggested_resolution: str
@dataclass(frozen=True)
class TransportPolicyValidateSummary:
block_count: int
warn_count: int
@dataclass(frozen=True)
class TransportPolicyDiff:
added: int
changed: int
removed: int
@dataclass(frozen=True)
class TransportPolicyValidateResult:
ok: bool
message: str
code: str
valid: bool
base_revision: int
confirm_token: str
summary: TransportPolicyValidateSummary
conflicts: List[TransportConflict]
diff: TransportPolicyDiff
@dataclass(frozen=True)
class TransportPolicyApplyResult:
ok: bool
message: str
code: str
policy_revision: int
current_revision: int
apply_id: str
rollback_available: bool
conflicts: List[TransportConflict]
@dataclass(frozen=True)
class TransportConflicts:
has_blocking: bool
items: List[TransportConflict]
@dataclass(frozen=True)
class TransportCapabilities:
clients: Dict[str, Dict[str, bool]]
@dataclass(frozen=True)
class TransportInterfaceItem:
id: str
name: str
mode: str
runtime_iface: str
netns_name: str
routing_table: str
client_ids: List[str]
client_count: int
up_count: int
updated_at: str
config: Dict[str, Any]
@dataclass(frozen=True)
class TransportInterfacesSnapshot:
ok: bool
message: str
code: str
count: int
items: List[TransportInterfaceItem]
@dataclass(frozen=True)
class TransportOwnershipRecord:
key: str
selector_type: str
selector_value: str
client_id: str
client_kind: str
owner_scope: str
owner_status: str
lock_active: bool
iface_id: str
routing_table: str
mark_hex: str
priority_base: int
mode: str
priority: int
updated_at: str
@dataclass(frozen=True)
class TransportOwnershipSnapshot:
ok: bool
message: str
code: str
policy_revision: int
plan_digest: str
count: int
lock_count: int
items: List[TransportOwnershipRecord]
@dataclass(frozen=True)
class TransportOwnerLockRecord:
destination_ip: str
client_id: str
client_kind: str
iface_id: str
mark_hex: str
proto: str
updated_at: str
@dataclass(frozen=True)
class TransportOwnerLocksSnapshot:
ok: bool
message: str
code: str
policy_revision: int
count: int
items: List[TransportOwnerLockRecord]
@dataclass(frozen=True)
class TransportOwnerLocksClearResult:
ok: bool
message: str
code: str
base_revision: int
confirm_required: bool
confirm_token: str
match_count: int
cleared_count: int
remaining_count: int
items: List[TransportOwnerLockRecord]
@dataclass(frozen=True)
class TransportClientActionResult:
ok: bool
message: str
code: str
client_id: str
kind: str
action: str
status_before: str
status_after: str
last_error: str
exit_code: Optional[int] = None
stdout: str = ""
stderr: str = ""
@dataclass(frozen=True)
class TransportNetnsToggleItem:
ok: bool
message: str
code: str
client_id: str
kind: str
status_before: str
status_after: str
netns_enabled: bool
config_updated: bool
provisioned: bool
restarted: bool
stdout: str = ""
stderr: str = ""
@dataclass(frozen=True)
class TransportNetnsToggleResult:
ok: bool
message: str
code: str
enabled: bool
count: int
success_count: int
failure_count: int
items: List[TransportNetnsToggleItem]
@dataclass(frozen=True)
class SingBoxProfileIssue:
field: str
severity: str
code: str
message: str
@dataclass(frozen=True)
class SingBoxProfileRenderDiff:
added: int
changed: int
removed: int
@dataclass(frozen=True)
class SingBoxProfileValidateResult:
ok: bool
message: str
code: str
profile_id: str
profile_revision: int
valid: bool
errors: List[SingBoxProfileIssue]
warnings: List[SingBoxProfileIssue]
render_digest: str
diff: SingBoxProfileRenderDiff
@dataclass(frozen=True)
class SingBoxProfileApplyResult:
ok: bool
message: str
code: str
profile_id: str
client_id: str
config_path: str
profile_revision: int
render_revision: int
last_applied_at: str
render_path: str
render_digest: str
rollback_available: bool
valid: bool
errors: List[SingBoxProfileIssue]
warnings: List[SingBoxProfileIssue]
diff: SingBoxProfileRenderDiff
@dataclass(frozen=True)
class SingBoxProfile:
id: str
name: str
mode: str
protocol: str
enabled: bool
schema_version: int
profile_revision: int
render_revision: int
last_validated_at: str
last_applied_at: str
last_error: str
typed: Dict[str, Any]
raw_config: Dict[str, Any]
meta: Dict[str, Any]
has_secrets: bool
secrets_masked: Dict[str, str]
created_at: str
updated_at: str
@dataclass(frozen=True)
class SingBoxProfilesState:
ok: bool
message: str
code: str
count: int
active_profile_id: str
items: List[SingBoxProfile]
item: Optional[SingBoxProfile] = None
@dataclass(frozen=True)
class SingBoxProfileRenderResult:
ok: bool
message: str
code: str
profile_id: str
profile_revision: int
render_revision: int
render_path: str
render_digest: str
changed: bool
valid: bool
errors: List[SingBoxProfileIssue]
warnings: List[SingBoxProfileIssue]
diff: SingBoxProfileRenderDiff
config: Dict[str, Any]
@dataclass(frozen=True)
class SingBoxProfileRollbackResult:
ok: bool
message: str
code: str
profile_id: str
client_id: str
config_path: str
history_id: str
profile_revision: int
last_applied_at: str
@dataclass(frozen=True)
class SingBoxProfileHistoryEntry:
id: str
at: str
profile_id: str
action: str
status: str
code: str
message: str
profile_revision: int
render_revision: int
render_digest: str
render_path: str
client_id: str
@dataclass(frozen=True)
class SingBoxProfileHistoryResult:
ok: bool
message: str
code: str
profile_id: str
count: int
items: List[SingBoxProfileHistoryEntry]
@dataclass(frozen=True)
class TrafficCandidateSubnet:
cidr: str
dev: str
kind: str
linkdown: bool
@dataclass(frozen=True)
class TrafficCandidateUnit:
unit: str
description: str
cgroup: str
@dataclass(frozen=True)
class TrafficCandidateUID:
uid: int
user: str
examples: List[str]
@dataclass(frozen=True)
class TrafficCandidates:
generated_at: str
subnets: List[TrafficCandidateSubnet]
units: List[TrafficCandidateUnit]
uids: List[TrafficCandidateUID]
@dataclass(frozen=True)
class DnsUpstreams:
default1: str
default2: str
meta1: str
meta2: str
@dataclass(frozen=True)
class DNSBenchmarkUpstream:
addr: str
enabled: bool = True
@dataclass(frozen=True)
class DNSBenchmarkResult:
upstream: str
attempts: int
ok: int
fail: int
nxdomain: int
timeout: int
temporary: int
other: int
avg_ms: int
p95_ms: int
score: float
color: str
@dataclass(frozen=True)
class DNSBenchmarkResponse:
results: List[DNSBenchmarkResult]
domains_used: List[str]
timeout_ms: int
attempts_per_domain: int
profile: str
recommended_default: List[str]
recommended_meta: List[str]
@dataclass(frozen=True)
class DNSUpstreamPoolState:
items: List[DNSBenchmarkUpstream]
@dataclass(frozen=True)
class SmartdnsServiceState:
state: str
@dataclass(frozen=True)
class DNSStatus:
via_smartdns: bool
smartdns_addr: str
mode: str
unit_state: str
runtime_nftset: bool
wildcard_source: str
runtime_config_path: str
runtime_config_error: str
@dataclass(frozen=True)
class SmartdnsRuntimeState:
enabled: bool
applied_enabled: bool
wildcard_source: str
unit_state: str
config_path: str
changed: bool = False
restarted: bool = False
message: str = ""
@dataclass(frozen=True)
class DomainsTable:
lines: List[str]
@dataclass(frozen=True)
class DomainsFile:
name: str
content: str
source: str = ""
@dataclass(frozen=True)
class VpnAutoloopStatus:
raw_text: str
status_word: str
@dataclass(frozen=True)
class VpnStatus:
desired_location: str
status_word: str
raw_text: str
unit_state: str
@dataclass(frozen=True)
class VpnLocation:
label: str
iso: str
target: str
@dataclass(frozen=True)
class VpnLocationsState:
locations: List[VpnLocation]
updated_at: str
stale: bool
refresh_in_progress: bool
last_error: str
next_retry_at: str
@dataclass(frozen=True)
class EgressIdentity:
scope: str
source: str
source_id: str
ip: str
country_code: str
country_name: str
updated_at: str
stale: bool
refresh_in_progress: bool
last_error: str
next_retry_at: str
@dataclass(frozen=True)
class EgressIdentityRefreshItem:
scope: str
status: str
queued: bool
reason: str
@dataclass(frozen=True)
class EgressIdentityRefreshResult:
ok: bool
message: str
count: int
queued: int
skipped: int
items: List[EgressIdentityRefreshItem]
@dataclass(frozen=True)
class TraceDump:
lines: List[str]
@dataclass(frozen=True)
class Event:
id: int
kind: str
ts: str
data: Any
# ---------------------------
# AdGuard VPN interactive login-session (PTY)
# ---------------------------
@dataclass(frozen=True)
class LoginSessionStart:
ok: bool
phase: str
level: str
pid: Optional[int] = None
email: str = ""
error: str = ""
@dataclass(frozen=True)
class LoginSessionState:
ok: bool
phase: str
level: str
alive: bool
url: str
email: str
cursor: int
lines: List[str]
can_open: bool
can_check: bool
can_cancel: bool
@dataclass(frozen=True)
class LoginSessionAction:
ok: bool
phase: str = ""
level: str = ""
error: str = ""
TraceMode = Literal["full", "gui", "smartdns"]
ServiceAction = Literal["start", "stop", "restart"]
TransportClientAction = Literal["provision", "start", "stop", "restart"]