merge: 并入同事的场外申购/推广/行情/NL2SQL 线(11 提交、334 文件)

冲突仅 3 个文件,全部取并集(双方都没有需要丢弃的改动):
- app/main.py:import 双方路由(我方 knowledge_management + 同事的 offsite_fund/
  promotion_material);include_router 段本已自动合并
- app/service/agent/bootstrap.py:import 与工具注册均取并集
  (query_customer_profile + query_financial_data 都注册)
- tests/integration/test_config_release_mysql.py:outbox 清理同时保留
  架构师的 event_type 限定(防误删其它域 outbox 行)与同事新增的 peer_release_id

同事这轮带入:11 个 alembic 迁移(建 offsite_* / promotion_* 等表)、
场外申购与推广素材 Agent、financial NL2SQL 工具。
注意:本库尚无 offsite_*/promotion_* 表,跑相关测试前需要执行 alembic upgrade。

边界核对:同事的场外代码未写入场内交易表(fin_sim_order/fin_capital_flow/fin_cash_ledger),
符合 AGENTS.md 规则 8。
This commit is contained in:
qyqy
2026-09-11 18:56:26 +08:00
118 changed files with 18967 additions and 191 deletions
+6 -6
View File
@@ -44,7 +44,7 @@ from app.worker.episode_worker import (
)
from app.worker.knowledge_vector_worker import build_knowledge_handlers
from app.worker.memory_extraction_worker import MemoryExtractionWorker
from app.worker.outbox_worker import OutboxWorker
from app.worker.outbox_worker import OutboxHandlerError, OutboxWorker
logger = logging.getLogger(__name__)
@@ -147,11 +147,11 @@ class WorkerRuntime:
async def dispatch(payload: dict[str, Any]) -> None:
run = await AgentRunRepository(session).get(str(payload["run_id"]))
if run is None:
raise ValueError("run not found")
raise OutboxHandlerError("run not found")
async def dispatch_memory_extraction(payload: dict[str, Any]) -> None:
if "message_id" not in payload or "customer_id" not in payload:
raise ValueError("memory extraction payload is incomplete")
raise OutboxHandlerError("memory extraction payload is incomplete")
# 幂等键只认事件 id,由 worker 自己按 payload 回查,避免调用方漏传。
# 注入召回缓存适配器:写入生效后立即失效该客户的热缓存。
await MemoryExtractionWorker(
@@ -163,7 +163,7 @@ class WorkerRuntime:
# "运行已完成"的对外通知职责。当前没有独立外部消费者,
# 这里显式消费以免事件永久滞留;接入推送链路时在此处扩展。
if not str(payload.get("run_id", "")):
raise ValueError("agent.run_completed payload is incomplete")
raise OutboxHandlerError("agent.run_completed payload is incomplete")
async def dispatch_cache_invalidate(payload: dict[str, Any]) -> None:
await self._invalidate_config_cache(payload)
@@ -177,7 +177,7 @@ class WorkerRuntime:
"""
customer_id = payload.get("customer_id")
if not customer_id:
raise ValueError("profile.rebuild_requested payload is incomplete")
raise OutboxHandlerError("profile.rebuild_requested payload is incomplete")
# 延迟导入:bootstrap 会间接导入本模块,模块级导入会形成循环依赖
from app.service.profile_assembly_service import ProfileAssemblyService
from app.service.profile_graph_projection_service import (
@@ -209,7 +209,7 @@ class WorkerRuntime:
raise ValueError("memory.deletion_requested payload is incomplete")
mode = str(payload.get("mode", "invalidate"))
if mode not in {"invalidate", "delete"}:
raise ValueError("memory.deletion_requested mode is invalid")
raise OutboxHandlerError("memory.deletion_requested mode is invalid")
await MemoryLifecycleService(session).run(
int(customer_id),
mode=cast("Mode", mode),