feat: aether-proxy 远程配置下发、连通性测试与 setup TUI

- 后端新增远程配置管理 API (PUT /config) 和连通性测试 API (POST /test)
- 前端新增远程配置编辑对话框和节点连通性测试按钮
- aether-proxy 支持通过心跳接收并热加载远程配置 (端口白名单、日志级别、心跳间隔、时间戳容差)
- aether-proxy 新增 TOML 配置文件支持和交互式 setup TUI
- aether-proxy 心跳 404 时自动重注册节点
- plain proxy 响应改为流式传输,减少内存缓冲
- 新增 remote_config 和 config_version 数据库字段及迁移
This commit is contained in:
fawney19
2026-02-07 19:20:09 +08:00
parent 3b8398b2e5
commit 31bc452374
18 changed files with 2771 additions and 113 deletions

View File

@@ -0,0 +1,61 @@
"""Add remote_config and config_version to proxy_nodes
Revision ID: 3aff3ffc4a0e
Revises: e1b2c3d4f5a6
Create Date: 2026-02-07 15:00:00.000000
"""
from __future__ import annotations
from collections.abc import Sequence
import sqlalchemy as sa
from sqlalchemy import inspect
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "3aff3ffc4a0e"
down_revision: str | None = "e1b2c3d4f5a6"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def column_exists(table_name: str, column_name: str) -> bool:
bind = op.get_bind()
inspector = inspect(bind)
columns = [c["name"] for c in inspector.get_columns(table_name)]
return column_name in columns
def upgrade() -> None:
if not column_exists("proxy_nodes", "remote_config"):
op.add_column(
"proxy_nodes",
sa.Column(
"remote_config",
sa.JSON(),
nullable=True,
comment="管理端下发的远程配置 (allowed_ports, log_level, heartbeat_interval, timestamp_tolerance)",
),
)
if not column_exists("proxy_nodes", "config_version"):
op.add_column(
"proxy_nodes",
sa.Column(
"config_version",
sa.Integer(),
nullable=False,
server_default="0",
comment="远程配置版本号,每次更新 +1",
),
)
def downgrade() -> None:
if column_exists("proxy_nodes", "config_version"):
op.drop_column("proxy_nodes", "config_version")
if column_exists("proxy_nodes", "remote_config"):
op.drop_column("proxy_nodes", "remote_config")