数据库与模型:新增多版迁移(章节证据快照、对话血缘、记忆事实/时间线 lineage 等),把「成稿 ↔ 对话/记忆」的溯源信息落到表结构里。 业务链路:会话与 WS、回忆录/故事流水线、记忆写入与 enrichment 等跟着接上线索与快照;新增章节证据快照与评测侧 EvalTraceService 等模块,方便组评审用的证据包。 内部评测:自动化 run 与手工 memoir 评审共用可追溯证据;rubric/ judge 相关脚本与文档有配套调整。 app-eval-web:Memoir/实验详情里能展开看证据摘要与 evidence_trace(含对话轮次 id);Vite 代理与 development.sh 注入的 API 端口与当前默认内部评测端口一致,避免改端口后页面连错服务。 工程杂项:GitHub Actions / 仓库说明有更新;各适配器与支付/配额/plan 等多处为小改动或跟随主改动的收尾;新增/扩充了?
84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
"""Tencent Cloud SMS adapter — implements SmsSender port."""
|
|
|
|
from tencentcloud.common import credential
|
|
from tencentcloud.common.exception.tencent_cloud_sdk_exception import (
|
|
TencentCloudSDKException,
|
|
)
|
|
from tencentcloud.sms.v20210111 import models as sms_models
|
|
from tencentcloud.sms.v20210111 import sms_client
|
|
|
|
from app.core.logging import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
CODE_EXPIRE_MINUTES = 5
|
|
|
|
|
|
class TencentSmsSender:
|
|
def __init__(
|
|
self,
|
|
secret_id: str,
|
|
secret_key: str,
|
|
sdk_app_id: str,
|
|
sign_name: str,
|
|
template_id: str,
|
|
template_param_count: int = 2,
|
|
):
|
|
self._secret_id = secret_id
|
|
self._secret_key = secret_key
|
|
self._sdk_app_id = sdk_app_id
|
|
self._sign_name = sign_name
|
|
self._template_id = template_id
|
|
self._template_param_count = template_param_count
|
|
|
|
def send_verification_code(self, phone: str, code: str) -> bool:
|
|
if not self._secret_id or not self._secret_key:
|
|
logger.error("Tencent SMS credentials not configured")
|
|
return False
|
|
|
|
cred = credential.Credential(self._secret_id, self._secret_key)
|
|
client = sms_client.SmsClient(cred, "ap-guangzhou")
|
|
|
|
param_configs = [
|
|
[code, str(CODE_EXPIRE_MINUTES)],
|
|
[code],
|
|
]
|
|
if self._template_param_count == 1:
|
|
param_configs = [[code], [code, str(CODE_EXPIRE_MINUTES)]]
|
|
|
|
for template_params in param_configs:
|
|
try:
|
|
req = sms_models.SendSmsRequest()
|
|
req.SmsSdkAppId = self._sdk_app_id
|
|
req.SignName = self._sign_name
|
|
req.TemplateId = self._template_id
|
|
req.TemplateParamSet = template_params
|
|
req.PhoneNumberSet = [f"+86{phone}"]
|
|
|
|
resp = client.SendSms(req)
|
|
if resp.SendStatusSet and resp.SendStatusSet[0].Code == "Ok":
|
|
return True
|
|
|
|
status = resp.SendStatusSet[0] if resp.SendStatusSet else None
|
|
error_code = status.Code if status else "UNKNOWN"
|
|
if "TemplateParamSetNotMatchApprovedTemplate" in error_code:
|
|
continue
|
|
logger.error(
|
|
"SMS send failed: {} - {}",
|
|
error_code,
|
|
status.Message if status else "",
|
|
)
|
|
return False
|
|
|
|
except TencentCloudSDKException as e:
|
|
if "TemplateParamSetNotMatchApprovedTemplate" in str(e):
|
|
continue
|
|
logger.error("Tencent SMS SDK error: {}", e)
|
|
return False
|
|
except Exception as e:
|
|
logger.error("SMS send exception: {}", e)
|
|
return False
|
|
|
|
logger.error("All SMS template param configs failed")
|
|
return False
|