feat: preserve isolated visitor agent runtime

This commit is contained in:
张胜宇
2026-09-10 17:36:39 +08:00
parent 8e36a9941d
commit ba22a2220f
10 changed files with 154 additions and 17 deletions
+43 -14
View File
@@ -102,6 +102,35 @@ class WorkerRuntime:
# episode 聚合是低频批处理,按轮次节流而不是每轮都查。
self._episode_rounds = 0
async def restore_context(
self, *, actor_type: str, actor_id: str, trace_id: str
) -> RequestContext:
"""按已验证的内部事件身份恢复执行上下文。"""
identity = RequestContext(user_id=actor_id, trace_id=trace_id)
if actor_type == "visitor":
return identity.model_copy(update={
"roles": ("visitor",),
"permissions": ("agent:run",),
"data_scope": "public",
})
return await self.resolve_identity(identity)
@staticmethod
def should_request_memory_extraction(
*, context: RequestContext, message: str, result: AgentResult,
business_events: tuple[str, ...] | list[str],
) -> bool:
"""只允许已登录用户的明确业务事实进入客户记忆抽取队列。"""
if "visitor" in context.roles:
return False
return MemoryService.should_extract_memory(
conversation_content=message,
role="user",
tool_result=any(call.status == "succeeded" for call in result.result.tool_calls),
event_type=business_events[0] if business_events else None,
signals=MemoryService.detect_memory_signals(message),
)
async def dispatch_one(self, *, run_id: str | None = None) -> bool:
# Outbox acknowledges a durable SQL queue entry, not an in-memory task.
async with SessionFactory() as session:
@@ -428,9 +457,15 @@ class WorkerRuntime:
idempotency_key=idem.idempotency_key,
metadata=AgentRequestMetadata.model_validate(metadata),
)
identity = RequestContext(user_id=str(run.user_id), trace_id=run.trace_id)
# Re-check account and permissions at execution time, including delayed jobs.
context = await self.resolve_identity(identity)
actor_type = (
str(event.payload.get("actor_type", "authenticated"))
if event else "authenticated"
)
actor_id = str(run.user_id)
trace_id = run.trace_id
context = await self.restore_context(
actor_type=actor_type, actor_id=actor_id, trace_id=trace_id
)
result: AgentResult | None = None
async for event_data in AgentExecutor(self.factory).execute(
request.agent_type, request, context, run_id
@@ -452,17 +487,11 @@ class WorkerRuntime:
async with SessionFactory() as session:
await AgentPersistenceService(session).complete_run(
run_id, result, worker_id=worker_id,
memory_extraction_requested=MemoryService.should_extract_memory(
conversation_content=request.message,
role="user",
# 工具产出的权威事实同样构成持久记忆(工具调用记录来自终态结果)。
tool_result=any(
call.status == "succeeded" for call in result.result.tool_calls
),
# 本 run 落库的业务事件(风险评估完成、交易完成等)。
event_type=business_events[0] if business_events else None,
# 用户明确陈述的偏好/约束/身份/目标,命中才触发抽取。
signals=MemoryService.detect_memory_signals(request.message),
memory_extraction_requested=self.should_request_memory_extraction(
context=context,
message=request.message,
result=result,
business_events=business_events,
),
)