feat: 服务层配置接线——email/push/rate_limit/AI凭据/行为开关/映射表/种子键
Task 9: 服务层对全局 settings 的业务引用清零,每个 DEFAULT_CONFIG 组 都有真实消费方。resolve_*_settings(email/push/ai)以空槽回退 env (平台默认层);contact 行为开关/种子白名单/国名扩表/限流上限经 manager 的 runtime.config 接线。收口: lead_push session_factory 必填、 config.py 死代码清理、PromptProvider frozen、no_contact 视图直取、 AIService wall 参数定型 CompiledWall。403 测试全绿(389+14)。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,8 @@ Red lines (see spec):
|
||||
- WS path (`app/api/routes/chat.py`) shares `ConversationManager` with these
|
||||
routes; both paths stay drift-free.
|
||||
- `context` seeding is conditional + whitelist (handled in
|
||||
`ConversationManager.create_conversation`).
|
||||
`ConversationManager.create_conversation`; Task 9 起白名单 =
|
||||
租户 config.engine.context_seed_keys——jiancai product_*/auto vehicle_*).
|
||||
- The message route consumes `stream_process_message`; lead email is
|
||||
triggered inside `ConversationManager` when contact info is detected
|
||||
(contact-driven-lead-email plan).
|
||||
@@ -20,6 +21,7 @@ from sqlalchemy import select
|
||||
from app.engine.models import ConversationSource, ConversationStatus, Message
|
||||
from app.engine.routes.runtime import get_runtime
|
||||
from app.engine.services.conversation import ConversationManager
|
||||
from app.engine.services.rate_limit import DEFAULT_MAX
|
||||
from app.engine.services.rate_limit import check as rate_check
|
||||
|
||||
router = APIRouter(prefix="/api/chat", tags=["chat-rest"])
|
||||
@@ -111,15 +113,19 @@ async def chat_message(req: MessageRequest, request: Request):
|
||||
`ConversationManager` when contact info is detected
|
||||
(contact-driven-lead-email plan) — this route carries no email logic.
|
||||
|
||||
A light in-memory rate limit (per ip + X-Device-Id, 30/h) guards GLM
|
||||
spend; only this route is throttled.
|
||||
A light in-memory rate limit (per tenant + ip + X-Device-Id, rolling 1h)
|
||||
guards GLM spend; only this route is throttled. Task 9: 桶键加租户维度
|
||||
(两租户同出口 IP 不互挤配额),上限读租户 config.engine.rate_limit_per_hour
|
||||
(默认 30,与出厂一致)。
|
||||
"""
|
||||
runtime = get_runtime(request)
|
||||
ip = request.client.host if request.client else ""
|
||||
dev = request.headers.get("X-Device-Id", "")
|
||||
if not rate_check(ip, dev):
|
||||
engine_cfg = runtime.config.data.get("engine") or {}
|
||||
limit = engine_cfg.get("rate_limit_per_hour") or DEFAULT_MAX
|
||||
if not rate_check(runtime.config.slug, ip, dev, max_requests=limit):
|
||||
raise HTTPException(status_code=429, detail="rate limit exceeded")
|
||||
|
||||
runtime = get_runtime(request)
|
||||
async with runtime.session_factory() as db:
|
||||
manager = ConversationManager(db, runtime=runtime)
|
||||
conv = await manager.get_by_session(req.session_id)
|
||||
|
||||
Reference in New Issue
Block a user