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