feat: bind monitors by base url hash

This commit is contained in:
2026-06-09 15:59:44 +08:00
parent a59ae55783
commit 16f50172ca
5 changed files with 36 additions and 3 deletions
+3 -1
View File
@@ -82,4 +82,6 @@ aliases exist: `id < slow < fast < sfast`. The table shows `sfast` first, then
When `--status-url` is configured, the status line shows channel monitor When `--status-url` is configured, the status line shows channel monitor
health, and the selected account detail shows the matching monitor status when health, and the selected account detail shows the matching monitor status when
one exists. one exists. Monitor binding first uses the shared `base_url_hash` emitted by
the account API and `sub2api-status`; name-token matching remains only as a
fallback for older status payloads.
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "shusub2" name = "shusub2"
version = "0.1.2" version = "0.1.3"
description = "Terminal UI for Sub2API account quota and daily usage" description = "Terminal UI for Sub2API account quota and daily usage"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"
+6
View File
@@ -226,6 +226,11 @@ def text_tokens(value: Any) -> set[str]:
def matching_monitor(row: dict[str, Any], status_payload: dict[str, Any]) -> dict[str, Any] | None: def matching_monitor(row: dict[str, Any], status_payload: dict[str, Any]) -> dict[str, Any] | None:
base_url_hash = str(row.get("base_url_hash") or "").strip()
if base_url_hash:
for item in monitor_items(status_payload):
if str(item.get("base_url_hash") or "").strip() == base_url_hash:
return item
account_tokens = text_tokens(row.get("name")) account_tokens = text_tokens(row.get("name"))
if not account_tokens: if not account_tokens:
return None return None
@@ -324,6 +329,7 @@ def normalize_account_rows(payload: dict[str, Any], filter_text: str = "") -> li
"id": as_int(account.get("id")), "id": as_int(account.get("id")),
"name": str(account.get("name") or ""), "name": str(account.get("name") or ""),
"routing_group": routing_group, "routing_group": routing_group,
"base_url_hash": str(account.get("base_url_hash") or ""),
"provider": provider_label(account), "provider": provider_label(account),
"kind": str(account.get("kind") or "unknown"), "kind": str(account.get("kind") or "unknown"),
"kind_label": kind_label(account.get("kind")), "kind_label": kind_label(account.get("kind")),
+25
View File
@@ -174,6 +174,31 @@ class Sub2APIQuotaTUITests(unittest.TestCase):
self.assertIn("monitors 5 ok / 0 failed / 1 unknown", mod.monitor_summary(status_payload)) self.assertIn("monitors 5 ok / 0 failed / 1 unknown", mod.monitor_summary(status_payload))
self.assertIn("monitor operational 2606ms", mod.monitor_detail(row, status_payload)) self.assertIn("monitor operational 2606ms", mod.monitor_detail(row, status_payload))
def test_monitor_match_prefers_base_url_hash_over_name_tokens(self) -> None:
mod = load_module()
status_payload = {
"channel_monitors": {
"items": [
{
"name": "input responses",
"base_url_hash": "wrong-hash",
"latest_status": "operational",
"latency_ms": 111,
},
{
"name": "unrelated responses",
"base_url_hash": "right-hash",
"latest_status": "degraded",
"latency_ms": 222,
},
],
}
}
row = {"name": "input 300", "base_url_hash": "right-hash"}
self.assertEqual(mod.matching_monitor(row, status_payload)["name"], "unrelated responses")
self.assertIn("monitor degraded 222ms", mod.monitor_detail(row, status_payload))
def test_monitor_error_is_non_blocking_in_once_output(self) -> None: def test_monitor_error_is_non_blocking_in_once_output(self) -> None:
mod = load_module() mod = load_module()
payload = { payload = {
Generated
+1 -1
View File
@@ -85,7 +85,7 @@ wheels = [
[[package]] [[package]]
name = "shusub2" name = "shusub2"
version = "0.1.2" version = "0.1.3"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "textual" }, { name = "textual" },