feat: preserve isolated visitor agent runtime
This commit is contained in:
+43
-14
@@ -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,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user