mirror of
https://github.com/TheSmallHanCat/sora2api.git
synced 2026-03-15 00:17:31 +08:00
feat(pow): 新增计算pow支持传入token
This commit is contained in:
@@ -64,6 +64,10 @@ timezone_offset = 8
|
|||||||
# beta测试,目前仍处于测试阶段
|
# beta测试,目前仍处于测试阶段
|
||||||
# POW 计算模式:local(本地计算)或 external(外部服务)
|
# POW 计算模式:local(本地计算)或 external(外部服务)
|
||||||
mode = "external"
|
mode = "external"
|
||||||
|
# 是否使用对应 token 进行 POW 计算(默认关闭)
|
||||||
|
# local 模式开启后会使用当前轮询 token 获取 POW
|
||||||
|
# external 模式开启后会向外部服务传递 accesstoken 字段
|
||||||
|
use_token_for_pow = false
|
||||||
# 外部 POW 服务地址(仅在 external 模式下使用)
|
# 外部 POW 服务地址(仅在 external 模式下使用)
|
||||||
server_url = "http://localhost:8002"
|
server_url = "http://localhost:8002"
|
||||||
# 外部 POW 服务访问密钥(仅在 external 模式下使用)
|
# 外部 POW 服务访问密钥(仅在 external 模式下使用)
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ class UpdatePowProxyConfigRequest(BaseModel):
|
|||||||
|
|
||||||
class UpdatePowServiceConfigRequest(BaseModel):
|
class UpdatePowServiceConfigRequest(BaseModel):
|
||||||
mode: str # "local" or "external"
|
mode: str # "local" or "external"
|
||||||
|
use_token_for_pow: Optional[bool] = False
|
||||||
server_url: Optional[str] = None
|
server_url: Optional[str] = None
|
||||||
api_key: Optional[str] = None
|
api_key: Optional[str] = None
|
||||||
proxy_enabled: Optional[bool] = None
|
proxy_enabled: Optional[bool] = None
|
||||||
@@ -1408,6 +1409,7 @@ async def update_pow_proxy_config(
|
|||||||
config_obj = await db.get_pow_service_config()
|
config_obj = await db.get_pow_service_config()
|
||||||
await db.update_pow_service_config(
|
await db.update_pow_service_config(
|
||||||
mode=config_obj.mode,
|
mode=config_obj.mode,
|
||||||
|
use_token_for_pow=config_obj.use_token_for_pow,
|
||||||
server_url=config_obj.server_url,
|
server_url=config_obj.server_url,
|
||||||
api_key=config_obj.api_key,
|
api_key=config_obj.api_key,
|
||||||
proxy_enabled=request.pow_proxy_enabled,
|
proxy_enabled=request.pow_proxy_enabled,
|
||||||
@@ -1432,6 +1434,7 @@ async def get_pow_service_config(token: str = Depends(verify_admin_token)) -> di
|
|||||||
"success": True,
|
"success": True,
|
||||||
"config": {
|
"config": {
|
||||||
"mode": config_obj.mode,
|
"mode": config_obj.mode,
|
||||||
|
"use_token_for_pow": config_obj.use_token_for_pow,
|
||||||
"server_url": config_obj.server_url or "",
|
"server_url": config_obj.server_url or "",
|
||||||
"api_key": config_obj.api_key or "",
|
"api_key": config_obj.api_key or "",
|
||||||
"proxy_enabled": config_obj.proxy_enabled,
|
"proxy_enabled": config_obj.proxy_enabled,
|
||||||
@@ -1448,6 +1451,7 @@ async def update_pow_service_config(
|
|||||||
try:
|
try:
|
||||||
await db.update_pow_service_config(
|
await db.update_pow_service_config(
|
||||||
mode=request.mode,
|
mode=request.mode,
|
||||||
|
use_token_for_pow=request.use_token_for_pow or False,
|
||||||
server_url=request.server_url,
|
server_url=request.server_url,
|
||||||
api_key=request.api_key,
|
api_key=request.api_key,
|
||||||
proxy_enabled=request.proxy_enabled,
|
proxy_enabled=request.proxy_enabled,
|
||||||
@@ -1455,6 +1459,7 @@ async def update_pow_service_config(
|
|||||||
)
|
)
|
||||||
# Update runtime config
|
# Update runtime config
|
||||||
config.set_pow_service_mode(request.mode)
|
config.set_pow_service_mode(request.mode)
|
||||||
|
config.set_pow_service_use_token_for_pow(request.use_token_for_pow or False)
|
||||||
config.set_pow_service_server_url(request.server_url or "")
|
config.set_pow_service_server_url(request.server_url or "")
|
||||||
config.set_pow_service_api_key(request.api_key or "")
|
config.set_pow_service_api_key(request.api_key or "")
|
||||||
config.set_pow_service_proxy_enabled(request.proxy_enabled or False)
|
config.set_pow_service_proxy_enabled(request.proxy_enabled or False)
|
||||||
|
|||||||
@@ -285,6 +285,17 @@ class Config:
|
|||||||
self._config["pow_service"] = {}
|
self._config["pow_service"] = {}
|
||||||
self._config["pow_service"]["mode"] = mode
|
self._config["pow_service"]["mode"] = mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pow_service_use_token_for_pow(self) -> bool:
|
||||||
|
"""Whether to use current token for POW calculation"""
|
||||||
|
return self._config.get("pow_service", {}).get("use_token_for_pow", False)
|
||||||
|
|
||||||
|
def set_pow_service_use_token_for_pow(self, enabled: bool):
|
||||||
|
"""Set whether to use current token for POW calculation"""
|
||||||
|
if "pow_service" not in self._config:
|
||||||
|
self._config["pow_service"] = {}
|
||||||
|
self._config["pow_service"]["use_token_for_pow"] = enabled
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pow_service_server_url(self) -> str:
|
def pow_service_server_url(self) -> str:
|
||||||
"""Get POW service server URL"""
|
"""Get POW service server URL"""
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ class Database:
|
|||||||
if count[0] == 0:
|
if count[0] == 0:
|
||||||
# Get POW service config from config_dict if provided, otherwise use defaults
|
# Get POW service config from config_dict if provided, otherwise use defaults
|
||||||
mode = "local"
|
mode = "local"
|
||||||
|
use_token_for_pow = False
|
||||||
server_url = None
|
server_url = None
|
||||||
api_key = None
|
api_key = None
|
||||||
proxy_enabled = False
|
proxy_enabled = False
|
||||||
@@ -238,6 +239,7 @@ class Database:
|
|||||||
if config_dict:
|
if config_dict:
|
||||||
pow_service_config = config_dict.get("pow_service", {})
|
pow_service_config = config_dict.get("pow_service", {})
|
||||||
mode = pow_service_config.get("mode", "local")
|
mode = pow_service_config.get("mode", "local")
|
||||||
|
use_token_for_pow = pow_service_config.get("use_token_for_pow", False)
|
||||||
server_url = pow_service_config.get("server_url", "")
|
server_url = pow_service_config.get("server_url", "")
|
||||||
api_key = pow_service_config.get("api_key", "")
|
api_key = pow_service_config.get("api_key", "")
|
||||||
proxy_enabled = pow_service_config.get("proxy_enabled", False)
|
proxy_enabled = pow_service_config.get("proxy_enabled", False)
|
||||||
@@ -248,9 +250,9 @@ class Database:
|
|||||||
proxy_url = proxy_url if proxy_url else None
|
proxy_url = proxy_url if proxy_url else None
|
||||||
|
|
||||||
await db.execute("""
|
await db.execute("""
|
||||||
INSERT INTO pow_service_config (id, mode, server_url, api_key, proxy_enabled, proxy_url)
|
INSERT INTO pow_service_config (id, mode, use_token_for_pow, server_url, api_key, proxy_enabled, proxy_url)
|
||||||
VALUES (1, ?, ?, ?, ?, ?)
|
VALUES (1, ?, ?, ?, ?, ?, ?)
|
||||||
""", (mode, server_url, api_key, proxy_enabled, proxy_url))
|
""", (mode, use_token_for_pow, server_url, api_key, proxy_enabled, proxy_url))
|
||||||
|
|
||||||
|
|
||||||
async def check_and_migrate_db(self, config_dict: dict = None):
|
async def check_and_migrate_db(self, config_dict: dict = None):
|
||||||
@@ -319,6 +321,35 @@ class Database:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ✗ Failed to add column '{col_name}': {e}")
|
print(f" ✗ Failed to add column '{col_name}': {e}")
|
||||||
|
|
||||||
|
# Check and add missing columns to pow_service_config table
|
||||||
|
if await self._table_exists(db, "pow_service_config"):
|
||||||
|
added_use_token_for_pow_column = False
|
||||||
|
columns_to_add = [
|
||||||
|
("use_token_for_pow", "BOOLEAN DEFAULT 0"),
|
||||||
|
]
|
||||||
|
|
||||||
|
for col_name, col_type in columns_to_add:
|
||||||
|
if not await self._column_exists(db, "pow_service_config", col_name):
|
||||||
|
try:
|
||||||
|
await db.execute(f"ALTER TABLE pow_service_config ADD COLUMN {col_name} {col_type}")
|
||||||
|
print(f" ✓ Added column '{col_name}' to pow_service_config table")
|
||||||
|
if col_name == "use_token_for_pow":
|
||||||
|
added_use_token_for_pow_column = True
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Failed to add column '{col_name}': {e}")
|
||||||
|
|
||||||
|
# On upgrade, initialize value from setting.toml only when this column is newly added
|
||||||
|
if config_dict and added_use_token_for_pow_column:
|
||||||
|
try:
|
||||||
|
use_token_for_pow = config_dict.get("pow_service", {}).get("use_token_for_pow", False)
|
||||||
|
await db.execute("""
|
||||||
|
UPDATE pow_service_config
|
||||||
|
SET use_token_for_pow = ?
|
||||||
|
WHERE id = 1
|
||||||
|
""", (use_token_for_pow,))
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Failed to initialize use_token_for_pow from config: {e}")
|
||||||
|
|
||||||
# Check and add missing columns to watermark_free_config table
|
# Check and add missing columns to watermark_free_config table
|
||||||
if await self._table_exists(db, "watermark_free_config"):
|
if await self._table_exists(db, "watermark_free_config"):
|
||||||
columns_to_add = [
|
columns_to_add = [
|
||||||
@@ -551,6 +582,7 @@ class Database:
|
|||||||
CREATE TABLE IF NOT EXISTS pow_service_config (
|
CREATE TABLE IF NOT EXISTS pow_service_config (
|
||||||
id INTEGER PRIMARY KEY DEFAULT 1,
|
id INTEGER PRIMARY KEY DEFAULT 1,
|
||||||
mode TEXT DEFAULT 'local',
|
mode TEXT DEFAULT 'local',
|
||||||
|
use_token_for_pow BOOLEAN DEFAULT 0,
|
||||||
server_url TEXT,
|
server_url TEXT,
|
||||||
api_key TEXT,
|
api_key TEXT,
|
||||||
proxy_enabled BOOLEAN DEFAULT 0,
|
proxy_enabled BOOLEAN DEFAULT 0,
|
||||||
@@ -1354,6 +1386,7 @@ class Database:
|
|||||||
return PowServiceConfig(**dict(row))
|
return PowServiceConfig(**dict(row))
|
||||||
return PowServiceConfig(
|
return PowServiceConfig(
|
||||||
mode="local",
|
mode="local",
|
||||||
|
use_token_for_pow=False,
|
||||||
server_url=None,
|
server_url=None,
|
||||||
api_key=None,
|
api_key=None,
|
||||||
proxy_enabled=False,
|
proxy_enabled=False,
|
||||||
@@ -1373,6 +1406,7 @@ class Database:
|
|||||||
async def update_pow_service_config(
|
async def update_pow_service_config(
|
||||||
self,
|
self,
|
||||||
mode: str,
|
mode: str,
|
||||||
|
use_token_for_pow: bool = False,
|
||||||
server_url: Optional[str] = None,
|
server_url: Optional[str] = None,
|
||||||
api_key: Optional[str] = None,
|
api_key: Optional[str] = None,
|
||||||
proxy_enabled: Optional[bool] = None,
|
proxy_enabled: Optional[bool] = None,
|
||||||
@@ -1382,9 +1416,9 @@ class Database:
|
|||||||
async with aiosqlite.connect(self.db_path) as db:
|
async with aiosqlite.connect(self.db_path) as db:
|
||||||
# Use INSERT OR REPLACE to ensure the row exists
|
# Use INSERT OR REPLACE to ensure the row exists
|
||||||
await db.execute("""
|
await db.execute("""
|
||||||
INSERT OR REPLACE INTO pow_service_config (id, mode, server_url, api_key, proxy_enabled, proxy_url, updated_at)
|
INSERT OR REPLACE INTO pow_service_config (id, mode, use_token_for_pow, server_url, api_key, proxy_enabled, proxy_url, updated_at)
|
||||||
VALUES (1, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
VALUES (1, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||||
""", (mode, server_url, api_key, proxy_enabled, proxy_url))
|
""", (mode, use_token_for_pow, server_url, api_key, proxy_enabled, proxy_url))
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ class PowServiceConfig(BaseModel):
|
|||||||
"""POW service configuration"""
|
"""POW service configuration"""
|
||||||
id: int = 1
|
id: int = 1
|
||||||
mode: str = "local" # "local" or "external"
|
mode: str = "local" # "local" or "external"
|
||||||
|
use_token_for_pow: bool = False # Whether to use current token for POW calculation
|
||||||
server_url: Optional[str] = None # External POW service URL
|
server_url: Optional[str] = None # External POW service URL
|
||||||
api_key: Optional[str] = None # External POW service API key
|
api_key: Optional[str] = None # External POW service API key
|
||||||
proxy_enabled: bool = False # Whether to enable proxy for POW service
|
proxy_enabled: bool = False # Whether to enable proxy for POW service
|
||||||
|
|||||||
@@ -147,11 +147,12 @@ async def startup_event():
|
|||||||
# Load POW service configuration from database
|
# Load POW service configuration from database
|
||||||
pow_service_config = await db.get_pow_service_config()
|
pow_service_config = await db.get_pow_service_config()
|
||||||
config.set_pow_service_mode(pow_service_config.mode)
|
config.set_pow_service_mode(pow_service_config.mode)
|
||||||
|
config.set_pow_service_use_token_for_pow(pow_service_config.use_token_for_pow)
|
||||||
config.set_pow_service_server_url(pow_service_config.server_url or "")
|
config.set_pow_service_server_url(pow_service_config.server_url or "")
|
||||||
config.set_pow_service_api_key(pow_service_config.api_key or "")
|
config.set_pow_service_api_key(pow_service_config.api_key or "")
|
||||||
config.set_pow_service_proxy_enabled(pow_service_config.proxy_enabled)
|
config.set_pow_service_proxy_enabled(pow_service_config.proxy_enabled)
|
||||||
config.set_pow_service_proxy_url(pow_service_config.proxy_url or "")
|
config.set_pow_service_proxy_url(pow_service_config.proxy_url or "")
|
||||||
print(f"✓ POW service mode: {pow_service_config.mode}")
|
print(f"✓ POW service mode: {pow_service_config.mode}, use_token_for_pow: {pow_service_config.use_token_for_pow}")
|
||||||
|
|
||||||
# Initialize concurrency manager with all tokens
|
# Initialize concurrency manager with all tokens
|
||||||
all_tokens = await db.get_all_tokens()
|
all_tokens = await db.get_all_tokens()
|
||||||
|
|||||||
@@ -39,24 +39,59 @@ class POWServiceClient:
|
|||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {api_key}",
|
"Authorization": f"Bearer {api_key}",
|
||||||
"Accept": "application/json"
|
"Accept": "application/json",
|
||||||
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add access_token to headers if provided
|
# Controlled by config switch: whether to pass current token to POW service
|
||||||
if access_token:
|
send_access_token = bool(config.pow_service_use_token_for_pow and access_token)
|
||||||
headers["X-Access-Token"] = access_token
|
|
||||||
|
def _mask_token(token_value: Optional[str]) -> str:
|
||||||
|
if not token_value:
|
||||||
|
return "none"
|
||||||
|
if len(token_value) <= 10:
|
||||||
|
return "***"
|
||||||
|
return f"{token_value[:6]}...{token_value[-4:]}"
|
||||||
|
|
||||||
|
debug_logger.log_info(
|
||||||
|
f"[POW Service] use_token_for_pow={config.pow_service_use_token_for_pow}, access_token={_mask_token(access_token)}"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
debug_logger.log_info(f"[POW Service] Requesting token from {api_url}")
|
debug_logger.log_info(f"[POW Service] Requesting token from {api_url}")
|
||||||
|
|
||||||
async with AsyncSession(impersonate="chrome131") as session:
|
async with AsyncSession(impersonate="chrome131") as session:
|
||||||
response = await session.get(
|
# Preferred protocol: POST + JSON body
|
||||||
|
payload = {"flow": "sora_init"}
|
||||||
|
if send_access_token:
|
||||||
|
payload["accesstoken"] = access_token
|
||||||
|
|
||||||
|
response = await session.post(
|
||||||
api_url,
|
api_url,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
|
json=payload,
|
||||||
proxy=proxy_url,
|
proxy=proxy_url,
|
||||||
timeout=30
|
timeout=30
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Backward compatibility: older services may only support GET + X-Access-Token
|
||||||
|
if response.status_code in (404, 405, 415):
|
||||||
|
fallback_headers = {
|
||||||
|
"Authorization": f"Bearer {api_key}",
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
if send_access_token:
|
||||||
|
fallback_headers["X-Access-Token"] = access_token
|
||||||
|
debug_logger.log_info(
|
||||||
|
f"[POW Service] POST unsupported ({response.status_code}), fallback to GET compatibility mode"
|
||||||
|
)
|
||||||
|
response = await session.get(
|
||||||
|
api_url,
|
||||||
|
headers=fallback_headers,
|
||||||
|
proxy=proxy_url,
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
error_msg = f"POW service request failed: {response.status_code}"
|
error_msg = f"POW service request failed: {response.status_code}"
|
||||||
debug_logger.log_error(
|
debug_logger.log_error(
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ _playwright = None
|
|||||||
_current_proxy = None
|
_current_proxy = None
|
||||||
|
|
||||||
# Sentinel token cache
|
# Sentinel token cache
|
||||||
_cached_sentinel_token = None
|
_cached_sentinel_token_map = {}
|
||||||
_cached_device_id = None
|
_cached_device_id = None
|
||||||
|
|
||||||
|
|
||||||
@@ -245,13 +245,19 @@ async def _get_cached_sentinel_token(proxy_url: str = None, force_refresh: bool
|
|||||||
Raises:
|
Raises:
|
||||||
Exception: If 403/429 when fetching oai-did
|
Exception: If 403/429 when fetching oai-did
|
||||||
"""
|
"""
|
||||||
global _cached_sentinel_token
|
global _cached_sentinel_token_map
|
||||||
|
|
||||||
|
# Whether current request should be token-aware for POW
|
||||||
|
use_token_for_pow = bool(config.pow_service_use_token_for_pow and access_token)
|
||||||
|
cache_key = access_token if use_token_for_pow else "__default__"
|
||||||
|
|
||||||
# Check if external POW service is configured
|
# Check if external POW service is configured
|
||||||
if config.pow_service_mode == "external":
|
if config.pow_service_mode == "external":
|
||||||
debug_logger.log_info("[POW] Using external POW service (cached sentinel)")
|
debug_logger.log_info("[POW] Using external POW service (cached sentinel)")
|
||||||
from .pow_service_client import pow_service_client
|
from .pow_service_client import pow_service_client
|
||||||
result = await pow_service_client.get_sentinel_token(access_token=access_token)
|
result = await pow_service_client.get_sentinel_token(
|
||||||
|
access_token=access_token if use_token_for_pow else None
|
||||||
|
)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
sentinel_token, device_id, service_user_agent = result
|
sentinel_token, device_id, service_user_agent = result
|
||||||
@@ -263,25 +269,36 @@ async def _get_cached_sentinel_token(proxy_url: str = None, force_refresh: bool
|
|||||||
|
|
||||||
# Local mode (original logic)
|
# Local mode (original logic)
|
||||||
# Return cached token if available and not forcing refresh
|
# Return cached token if available and not forcing refresh
|
||||||
if _cached_sentinel_token and not force_refresh:
|
if not force_refresh and cache_key in _cached_sentinel_token_map:
|
||||||
debug_logger.log_info("[Sentinel] Using cached token")
|
if use_token_for_pow:
|
||||||
return _cached_sentinel_token
|
debug_logger.log_info("[Sentinel] Using token-scoped cached token")
|
||||||
|
else:
|
||||||
|
debug_logger.log_info("[Sentinel] Using shared cached token")
|
||||||
|
return _cached_sentinel_token_map[cache_key]
|
||||||
|
|
||||||
# Generate new token
|
# Generate new token
|
||||||
debug_logger.log_info("[Sentinel] Generating new token...")
|
debug_logger.log_info("[Sentinel] Generating new token...")
|
||||||
token = await _generate_sentinel_token_lightweight(proxy_url)
|
token = await _generate_sentinel_token_lightweight(proxy_url)
|
||||||
|
|
||||||
if token:
|
if token:
|
||||||
_cached_sentinel_token = token
|
_cached_sentinel_token_map[cache_key] = token
|
||||||
debug_logger.log_info("[Sentinel] Token cached successfully")
|
debug_logger.log_info("[Sentinel] Token cached successfully")
|
||||||
|
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
|
||||||
def _invalidate_sentinel_cache():
|
def _invalidate_sentinel_cache(access_token: Optional[str] = None):
|
||||||
"""Invalidate cached sentinel token (call after 400 error)"""
|
"""Invalidate cached sentinel token (call after 400 error)
|
||||||
global _cached_sentinel_token
|
|
||||||
_cached_sentinel_token = None
|
Args:
|
||||||
|
access_token: Optional current access token for token-scoped cache invalidation
|
||||||
|
"""
|
||||||
|
global _cached_sentinel_token_map
|
||||||
|
use_token_for_pow = bool(config.pow_service_use_token_for_pow and access_token)
|
||||||
|
cache_key = access_token if use_token_for_pow else "__default__"
|
||||||
|
|
||||||
|
if cache_key in _cached_sentinel_token_map:
|
||||||
|
del _cached_sentinel_token_map[cache_key]
|
||||||
debug_logger.log_info("[Sentinel] Cache invalidated")
|
debug_logger.log_info("[Sentinel] Cache invalidated")
|
||||||
|
|
||||||
|
|
||||||
@@ -755,7 +772,9 @@ class SoraClient:
|
|||||||
# Check if external POW service is configured
|
# Check if external POW service is configured
|
||||||
if config.pow_service_mode == "external":
|
if config.pow_service_mode == "external":
|
||||||
debug_logger.log_info("[Sentinel] Using external POW service...")
|
debug_logger.log_info("[Sentinel] Using external POW service...")
|
||||||
result = await pow_service_client.get_sentinel_token(access_token=token)
|
result = await pow_service_client.get_sentinel_token(
|
||||||
|
access_token=token if config.pow_service_use_token_for_pow else None
|
||||||
|
)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
sentinel_token, device_id, service_user_agent = result
|
sentinel_token, device_id, service_user_agent = result
|
||||||
@@ -1173,7 +1192,7 @@ class SoraClient:
|
|||||||
debug_logger.log_info("[Sentinel] Got 400 error, refreshing token and retrying...")
|
debug_logger.log_info("[Sentinel] Got 400 error, refreshing token and retrying...")
|
||||||
|
|
||||||
# Invalidate cache and get fresh token
|
# Invalidate cache and get fresh token
|
||||||
_invalidate_sentinel_cache()
|
_invalidate_sentinel_cache(token)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sentinel_token = await _get_cached_sentinel_token(pow_proxy_url, force_refresh=True, access_token=token)
|
sentinel_token = await _get_cached_sentinel_token(pow_proxy_url, force_refresh=True, access_token=token)
|
||||||
|
|||||||
@@ -402,6 +402,13 @@
|
|||||||
</select>
|
</select>
|
||||||
<p class="text-xs text-muted-foreground mt-1">选择 POW 计算方式</p>
|
<p class="text-xs text-muted-foreground mt-1">选择 POW 计算方式</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="inline-flex items-center gap-2 cursor-pointer">
|
||||||
|
<input type="checkbox" id="cfgPowUseTokenForPow" class="h-4 w-4 rounded border-input">
|
||||||
|
<span class="text-sm font-medium">使用对应 Token 进行计算</span>
|
||||||
|
</label>
|
||||||
|
<p class="text-xs text-muted-foreground mt-1">默认关闭。local 模式下使用当前轮询 Token 计算;external 模式下会传递 accesstoken 字段。</p>
|
||||||
|
</div>
|
||||||
<div id="powExternalFields" style="display: none;">
|
<div id="powExternalFields" style="display: none;">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -1142,8 +1149,8 @@
|
|||||||
deleteCharacter=async(id)=>{if(!confirm('确定要删除这个角色卡吗?'))return;try{const r=await apiRequest(`/api/characters/${id}`,{method:'DELETE'});if(!r)return;const d=await r.json();if(d.success){showToast('删除成功','success');await loadCharacters()}else{showToast('删除失败','error')}}catch(e){showToast('删除失败: '+e.message,'error')}},
|
deleteCharacter=async(id)=>{if(!confirm('确定要删除这个角色卡吗?'))return;try{const r=await apiRequest(`/api/characters/${id}`,{method:'DELETE'});if(!r)return;const d=await r.json();if(d.success){showToast('删除成功','success');await loadCharacters()}else{showToast('删除失败','error')}}catch(e){showToast('删除失败: '+e.message,'error')}},
|
||||||
loadCallLogicConfig=async()=>{try{const r=await apiRequest('/api/call-logic/config');if(!r)return;const d=await r.json();if(d.success&&d.config){const mode=d.config.call_mode||((d.config.polling_mode_enabled||false)?'polling':'default');$('cfgCallLogicMode').value=mode}else{console.error('调用逻辑配置数据格式错误:',d)}}catch(e){console.error('加载调用逻辑配置失败:',e)}},
|
loadCallLogicConfig=async()=>{try{const r=await apiRequest('/api/call-logic/config');if(!r)return;const d=await r.json();if(d.success&&d.config){const mode=d.config.call_mode||((d.config.polling_mode_enabled||false)?'polling':'default');$('cfgCallLogicMode').value=mode}else{console.error('调用逻辑配置数据格式错误:',d)}}catch(e){console.error('加载调用逻辑配置失败:',e)}},
|
||||||
saveCallLogicConfig=async()=>{try{const mode=$('cfgCallLogicMode').value||'default';const r=await apiRequest('/api/call-logic/config',{method:'POST',body:JSON.stringify({call_mode:mode})});if(!r)return;const d=await r.json();if(d.success){showToast('调用逻辑配置保存成功','success')}else{showToast('保存失败','error')}}catch(e){showToast('保存失败: '+e.message,'error')}},
|
saveCallLogicConfig=async()=>{try{const mode=$('cfgCallLogicMode').value||'default';const r=await apiRequest('/api/call-logic/config',{method:'POST',body:JSON.stringify({call_mode:mode})});if(!r)return;const d=await r.json();if(d.success){showToast('调用逻辑配置保存成功','success')}else{showToast('保存失败','error')}}catch(e){showToast('保存失败: '+e.message,'error')}},
|
||||||
loadPowConfig=async()=>{try{const r=await apiRequest('/api/pow/config');if(!r)return;const d=await r.json();if(d.success&&d.config){$('cfgPowMode').value=d.config.mode||'local';$('cfgPowServerUrl').value=d.config.server_url||'';$('cfgPowApiKey').value=d.config.api_key||'';$('cfgPowProxyEnabled').checked=d.config.proxy_enabled||false;$('cfgPowProxyUrl').value=d.config.proxy_url||'';togglePowFields();togglePowProxyFields()}else{console.error('POW配置数据格式错误:',d)}}catch(e){console.error('加载POW配置失败:',e)}},
|
loadPowConfig=async()=>{try{const r=await apiRequest('/api/pow/config');if(!r)return;const d=await r.json();if(d.success&&d.config){$('cfgPowMode').value=d.config.mode||'local';$('cfgPowUseTokenForPow').checked=d.config.use_token_for_pow||false;$('cfgPowServerUrl').value=d.config.server_url||'';$('cfgPowApiKey').value=d.config.api_key||'';$('cfgPowProxyEnabled').checked=d.config.proxy_enabled||false;$('cfgPowProxyUrl').value=d.config.proxy_url||'';togglePowFields();togglePowProxyFields()}else{console.error('POW配置数据格式错误:',d)}}catch(e){console.error('加载POW配置失败:',e)}},
|
||||||
savePowConfig=async()=>{try{const mode=$('cfgPowMode').value;const serverUrl=$('cfgPowServerUrl').value.trim();const apiKey=$('cfgPowApiKey').value.trim();const proxyEnabled=$('cfgPowProxyEnabled').checked;const proxyUrl=$('cfgPowProxyUrl').value.trim();if(mode==='external'){if(!serverUrl)return showToast('请输入服务器地址','error');if(!apiKey)return showToast('请输入API密钥','error')}const r=await apiRequest('/api/pow/config',{method:'POST',body:JSON.stringify({mode:mode,server_url:serverUrl||null,api_key:apiKey||null,proxy_enabled:proxyEnabled,proxy_url:proxyUrl||null})});if(!r)return;const d=await r.json();if(d.success){showToast('POW配置保存成功','success')}else{showToast('保存失败','error')}}catch(e){showToast('保存失败: '+e.message,'error')}},
|
savePowConfig=async()=>{try{const mode=$('cfgPowMode').value;const useTokenForPow=$('cfgPowUseTokenForPow').checked;const serverUrl=$('cfgPowServerUrl').value.trim();const apiKey=$('cfgPowApiKey').value.trim();const proxyEnabled=$('cfgPowProxyEnabled').checked;const proxyUrl=$('cfgPowProxyUrl').value.trim();if(mode==='external'){if(!serverUrl)return showToast('请输入服务器地址','error');if(!apiKey)return showToast('请输入API密钥','error')}const r=await apiRequest('/api/pow/config',{method:'POST',body:JSON.stringify({mode:mode,use_token_for_pow:useTokenForPow,server_url:serverUrl||null,api_key:apiKey||null,proxy_enabled:proxyEnabled,proxy_url:proxyUrl||null})});if(!r)return;const d=await r.json();if(d.success){showToast('POW配置保存成功','success')}else{showToast('保存失败','error')}}catch(e){showToast('保存失败: '+e.message,'error')}},
|
||||||
loadPowProxyConfig=loadPowConfig,savePowProxyConfig=savePowConfig,loadPowServiceConfig=loadPowConfig,savePowServiceConfig=savePowConfig,
|
loadPowProxyConfig=loadPowConfig,savePowProxyConfig=savePowConfig,loadPowServiceConfig=loadPowConfig,savePowServiceConfig=savePowConfig,
|
||||||
togglePowFields=()=>{const mode=$('cfgPowMode').value;const externalFields=$('powExternalFields');if(externalFields){externalFields.style.display=mode==='external'?'block':'none'}},
|
togglePowFields=()=>{const mode=$('cfgPowMode').value;const externalFields=$('powExternalFields');if(externalFields){externalFields.style.display=mode==='external'?'block':'none'}},
|
||||||
togglePowProxyFields=()=>{const enabled=$('cfgPowProxyEnabled').checked;const proxyUrlField=$('powProxyUrlField');if(proxyUrlField){proxyUrlField.style.display=enabled?'block':'none'}},
|
togglePowProxyFields=()=>{const enabled=$('cfgPowProxyEnabled').checked;const proxyUrlField=$('powProxyUrlField');if(proxyUrlField){proxyUrlField.style.display=enabled?'block':'none'}},
|
||||||
|
|||||||
Reference in New Issue
Block a user