refactor(server): steward 意图改用声明式注册表编排
- 新增 steward_intent_registry,IntentDescriptor 统一描述意图的识别关键词、动作步骤构建、字段白名单与副作用集合,替代分散的 if/else - 新增 steward_intent_bootstrap 注册 expense_application 等意图;新增 steward_query_executors 提供差旅标准查询的无副作用执行与城市/席别标签化输出 - action_contracts/action_executor/graph_planner/intent_agent/model_plan_builder/planner_extraction/fallback 适配注册表,识别与执行分发自动从注册表取数 - 新增 intent_registry/query_executors 测试,更新 intent_agent 测试
This commit is contained in:
@@ -15,6 +15,11 @@ from app.schemas.steward import (
|
||||
from app.schemas.user_agent import UserAgentRequest
|
||||
from app.services.attachment_association_jobs import AttachmentAssociationJobRunner
|
||||
from app.services.expense_claims import ExpenseClaimService
|
||||
from app.services.steward_intent_registry import (
|
||||
all_noop_actions,
|
||||
all_side_effect_actions,
|
||||
resolve_intent_by_action,
|
||||
)
|
||||
from app.services.user_agent import UserAgentService
|
||||
from app.services.user_agent_application_dates import resolve_application_days_from_time_range
|
||||
|
||||
@@ -31,8 +36,8 @@ SUPPORTED_ACTIONS = {
|
||||
"link_existing_application",
|
||||
"associate_attachments",
|
||||
}
|
||||
APPLICATION_SIDE_EFFECT_ACTIONS = {"save_application_draft", "submit_application"}
|
||||
REIMBURSEMENT_SIDE_EFFECT_ACTIONS = {"create_reimbursement_draft", "link_existing_application"}
|
||||
APPLICATION_SIDE_EFFECT_ACTIONS = {"save_application_draft", "submit_application", "run_duplicate_precheck"}
|
||||
REIMBURSEMENT_SIDE_EFFECT_ACTIONS = {"create_reimbursement_draft", "link_existing_application", "associate_attachments"}
|
||||
NOOP_ACTIONS = {
|
||||
"fill_application_fields",
|
||||
"build_application_preview",
|
||||
@@ -83,7 +88,8 @@ class StewardActionExecutor:
|
||||
) -> StewardActionExecuteResponse:
|
||||
action_type = self._normalize_action_type(request.action_type)
|
||||
trace = [self._trace("received", action_type=action_type, plan_id=request.plan_id)]
|
||||
if action_type not in SUPPORTED_ACTIONS:
|
||||
supported = SUPPORTED_ACTIONS | all_side_effect_actions() | all_noop_actions()
|
||||
if action_type not in supported:
|
||||
return self._blocked(
|
||||
action_type,
|
||||
f"不支持的小财管家动作:{action_type or '空动作'}。",
|
||||
@@ -91,7 +97,8 @@ class StewardActionExecutor:
|
||||
)
|
||||
|
||||
task = request.task
|
||||
if task is None and action_type not in NOOP_ACTIONS:
|
||||
noop_actions = NOOP_ACTIONS | all_noop_actions()
|
||||
if task is None and action_type not in noop_actions:
|
||||
return self._blocked(
|
||||
action_type,
|
||||
"动作缺少任务快照,无法安全执行。",
|
||||
@@ -107,7 +114,7 @@ class StewardActionExecutor:
|
||||
trace=[*trace, self._trace("blocked", reason="missing_fields")],
|
||||
)
|
||||
|
||||
if action_type in NOOP_ACTIONS:
|
||||
if action_type in noop_actions:
|
||||
return StewardActionExecuteResponse(
|
||||
action_type=action_type,
|
||||
status="succeeded",
|
||||
@@ -118,6 +125,13 @@ class StewardActionExecutor:
|
||||
},
|
||||
trace=[*trace, self._trace("completed", mode="noop")],
|
||||
)
|
||||
|
||||
# 优先走注册表:查到 action 所属意图的 executor 即委托执行
|
||||
intent = resolve_intent_by_action(action_type)
|
||||
if intent is not None and intent.executor is not None:
|
||||
return intent.executor(self, request, current_user, trace)
|
||||
|
||||
# 兼容回退:注册表未命中时按旧逻辑分发
|
||||
if action_type == "run_duplicate_precheck":
|
||||
return self._run_duplicate_precheck(request, current_user, trace)
|
||||
if action_type in APPLICATION_SIDE_EFFECT_ACTIONS:
|
||||
@@ -133,6 +147,30 @@ class StewardActionExecutor:
|
||||
trace=[*trace, self._trace("blocked", reason="unwired_action")],
|
||||
)
|
||||
|
||||
def _dispatch_application_action(
|
||||
self,
|
||||
request: StewardActionExecuteRequest,
|
||||
current_user: CurrentUserContext,
|
||||
trace: list[dict[str, Any]],
|
||||
) -> StewardActionExecuteResponse:
|
||||
"""registry 入口:分发申请类副作用动作。"""
|
||||
action_type = self._normalize_action_type(request.action_type)
|
||||
if action_type == "run_duplicate_precheck":
|
||||
return self._run_duplicate_precheck(request, current_user, trace)
|
||||
return self._execute_application_action(request, current_user, action_type, trace)
|
||||
|
||||
def _dispatch_reimbursement_action(
|
||||
self,
|
||||
request: StewardActionExecuteRequest,
|
||||
current_user: CurrentUserContext,
|
||||
trace: list[dict[str, Any]],
|
||||
) -> StewardActionExecuteResponse:
|
||||
"""registry 入口:分发报销类副作用动作。"""
|
||||
action_type = self._normalize_action_type(request.action_type)
|
||||
if action_type == "associate_attachments":
|
||||
return self._execute_associate_attachments_action(request, current_user, trace)
|
||||
return self._execute_reimbursement_action(request, current_user, action_type, trace)
|
||||
|
||||
def _run_duplicate_precheck(
|
||||
self,
|
||||
request: StewardActionExecuteRequest,
|
||||
|
||||
Reference in New Issue
Block a user