修复更新同一条记录触发智能体无限循环的问题
This commit is contained in:
parent
20aedb7347
commit
92700c638a
@ -6,12 +6,17 @@ import functools
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
import threading
|
||||
from jingrow.model.page import Page
|
||||
from jingrow.config import Config
|
||||
from jingrow.utils.jingrow_api import upload_file_to_jingrow
|
||||
|
||||
_local = {}
|
||||
|
||||
# 【通用执行上下文标记】用于标记当前调用链的来源,防止循环触发等场景
|
||||
# 使用 thread-local 存储,轻量且精确(同一线程内有效)
|
||||
_update_source_context = threading.local()
|
||||
|
||||
# 统一 Jingrow 日志记录器(仅为本模块及调用方提供最小可用输出,不修改全局 root logger)
|
||||
_root_logger = logging.getLogger("jingrow")
|
||||
|
||||
@ -62,6 +67,38 @@ def update_pg(pagetype: str, name: str, data: Dict[str, Any]):
|
||||
return updated
|
||||
|
||||
|
||||
def skip_hooks(source: str = "agent"):
|
||||
"""
|
||||
设置上下文标记,表示当前调用链来自指定来源(如智能体执行),
|
||||
用于跳过某些钩子防止循环触发等场景。
|
||||
"""
|
||||
try:
|
||||
_update_source_context.source = source
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def restore_hooks():
|
||||
"""
|
||||
清除上下文标记,恢复正常的钩子执行。
|
||||
"""
|
||||
try:
|
||||
if hasattr(_update_source_context, 'source'):
|
||||
delattr(_update_source_context, 'source')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def get_hook_source() -> Optional[str]:
|
||||
"""
|
||||
获取当前调用链的来源标识,用于判断是否跳过某些钩子。
|
||||
"""
|
||||
try:
|
||||
return getattr(_update_source_context, 'source', None)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def delete_pg(pagetype: str, name: str) -> bool:
|
||||
pg = Page(pagetype)
|
||||
res = pg.delete(name)
|
||||
|
||||
@ -160,7 +160,13 @@ def execute(context=None, inputs=None, config=None):
|
||||
|
||||
# 调用 Jingrow 更新记录(仅当有更新)
|
||||
if updated:
|
||||
server_record = jingrow.update_pg(record_type, record_name, mock_record)
|
||||
# 【防无限循环】设置上下文标记,表示当前更新来自智能体执行
|
||||
# 这样在 on_update 钩子中就不会再次触发智能体,防止循环
|
||||
jingrow.skip_hooks("agent")
|
||||
try:
|
||||
server_record = jingrow.update_pg(record_type, record_name, mock_record)
|
||||
finally:
|
||||
jingrow.restore_hooks()
|
||||
if server_record is False:
|
||||
return {"success": False, "error": "更新记录失败"}
|
||||
if server_record is True:
|
||||
|
||||
@ -38,12 +38,17 @@ def run_agent(pg=None, method=None, event=None, page=None, **kwargs):
|
||||
"""本地版 Local Ai Agent 事件驱动机制。
|
||||
- 支持按 pagetype 与 module 分组、合并去重
|
||||
- condition 支持 Jinja2 表达式
|
||||
- 使用本地任务队列,避免链式重复触发
|
||||
- 使用上下文标记防止无限循环
|
||||
"""
|
||||
# 兼容多种调用方式
|
||||
pg = pg or page
|
||||
method = event or method or kwargs.get("event")
|
||||
|
||||
# 【防无限循环】检查上下文标记:如果当前调用来自智能体执行,跳过
|
||||
# 使用轻量级 thread-local 上下文标记,防止循环触发
|
||||
if jingrow.get_hook_source() == "agent":
|
||||
return
|
||||
|
||||
# 支持的事件
|
||||
event_list = [
|
||||
"on_update",
|
||||
@ -91,7 +96,6 @@ def run_agent(pg=None, method=None, event=None, page=None, **kwargs):
|
||||
merged_agents = list({a.get("name"): a for a in agents_by_pagetype + agents_by_module}.values())
|
||||
|
||||
if not merged_agents:
|
||||
jingrow.log_error("LocalAIAgent", "No Local Ai Agents matched for this page")
|
||||
return
|
||||
|
||||
# 一次性准备渲染上下文(仅当至少一个 agent 有 condition 时才构建)
|
||||
@ -112,6 +116,7 @@ def run_agent(pg=None, method=None, event=None, page=None, **kwargs):
|
||||
|
||||
for agent in merged_agents:
|
||||
if agent.get("event_type") == method:
|
||||
agent_name = agent.get("name")
|
||||
|
||||
trigger = False
|
||||
if not agent.get("condition"):
|
||||
@ -131,7 +136,7 @@ def run_agent(pg=None, method=None, event=None, page=None, **kwargs):
|
||||
trigger = False
|
||||
|
||||
if trigger:
|
||||
enqueue_local_ai_agent(pg, agent.get('name'))
|
||||
enqueue_local_ai_agent(pg, agent_name)
|
||||
|
||||
def enqueue_local_ai_agent(pg, agent_name):
|
||||
"""后台实际入队执行 Local Ai Agent。"""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user