core: per-instance print injection (no_print), EXIT sentinel for run loop, log name collision fix, checklist poll hard cap
This commit is contained in:
1 parent
4df1c70bb2
commit
3acd58b36e
3 files changed
+22
-14
No files matched your search
+6
-2
@@ -53,7 +53,8 @@ class GenericAgent:
|
||||
self.inc_out = False; self.verbose = True; self.show_mode = 'text'
|
||||
self.peer_hint = True
|
||||
self.force_non_stream = False
|
||||
self.log_path = os.path.join(script_dir, f'temp/model_responses/model_responses_{int(time.time()*1e6)%1000000:06d}.txt')
|
||||
logid = f'{(time.time_ns() + random.randrange(1_000_000)) % 1_000_000:06d}'
|
||||
self.log_path = os.path.join(script_dir, f'temp/model_responses/model_responses_{logid}.txt')
|
||||
self.load_llm_sessions()
|
||||
|
||||
def load_llm_sessions(self):
|
||||
@@ -129,6 +130,7 @@ class GenericAgent:
|
||||
def run(self):
|
||||
while True:
|
||||
task = self.task_queue.get()
|
||||
if isinstance(task, str): break
|
||||
raw_query, source, display_queue = task["query"], task["source"], task["output"]
|
||||
raw_query = self._handle_slash_cmd(raw_query, display_queue)
|
||||
if raw_query is None:
|
||||
@@ -144,6 +146,7 @@ class GenericAgent:
|
||||
sys_prompt = get_system_prompt() + getattr(self.llmclient.backend, 'extra_sys_prompt', '')
|
||||
if self.peer_hint: sys_prompt += f"\n[Peer] 用户提及其他会话/后台任务状态时: temp/model_responses/ (只找近期修改的文件尾部)\n"
|
||||
handler = GenericAgentHandler(self, self.history, os.path.join(script_dir, 'temp'))
|
||||
if getattr(self, 'no_print', False): handler.print = lambda *a, **k: None
|
||||
if self.handler and 'key_info' in self.handler.working:
|
||||
ki = re.sub(r'\n\[SYSTEM\] 此为.*?工作记忆[。\n]*', '', self.handler.working['key_info']) # 去旧
|
||||
handler.working['key_info'] = ki
|
||||
@@ -168,7 +171,8 @@ class GenericAgent:
|
||||
display_queue.put({'next': full_resp[last_pos:] if self.inc_out else full_resp,
|
||||
'source': source, 'turn': curr_turn, 'outputs': turn_resps[-2:]})
|
||||
last_pos = len(full_resp)
|
||||
if self.inc_out and last_pos < len(full_resp): display_queue.put({'next': full_resp[last_pos:], 'source': source,
|
||||
if self.inc_out and last_pos < len(full_resp):
|
||||
display_queue.put({'next': full_resp[last_pos:], 'source': source,
|
||||
'turn': curr_turn, 'outputs': turn_resps[-2:]})
|
||||
#if '</summary>' in full_resp: full_resp = full_resp.replace('</summary>', '</summary>\n\n')
|
||||
#if '</file_content>' in full_resp: full_resp = re.sub(r'<file_content>\s*(.*?)\s*</file_content>', r'\n````\n<file_content>\n\1\n</file_content>\n````', full_resp, flags=re.DOTALL)
|
||||
|
||||
@@ -9,7 +9,11 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
from agent_loop import BaseHandler, StepOutcome, json_default
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop_signal=None, maxlen=10000):
|
||||
def safe_print(*args, **kwargs):
|
||||
try: print(*args, **kwargs)
|
||||
except: pass
|
||||
|
||||
def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop_signal=None, maxlen=10000, myprint=safe_print):
|
||||
"""代码执行器
|
||||
python: 运行复杂的 .py 脚本(文件模式)
|
||||
powershell/bash: 运行单行指令(命令模式)
|
||||
@@ -33,7 +37,7 @@ def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop
|
||||
else: cmd = ["bash", "-c", code]
|
||||
else:
|
||||
return {"status": "error", "msg": f"不支持的类型: {code_type}"}
|
||||
print("code run output:")
|
||||
myprint("code run output:")
|
||||
startupinfo = None
|
||||
if os.name == 'nt':
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
@@ -47,8 +51,7 @@ def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop
|
||||
try: line = line_bytes.decode('utf-8')
|
||||
except UnicodeDecodeError: line = line_bytes.decode('gbk', errors='ignore')
|
||||
logs.append(line)
|
||||
try: print(line, end="")
|
||||
except: pass
|
||||
myprint(line, end="")
|
||||
except: pass
|
||||
|
||||
try:
|
||||
@@ -65,7 +68,7 @@ def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop
|
||||
istimeout = time.time() - start_t > timeout
|
||||
if istimeout or stop_signal:
|
||||
process.kill()
|
||||
print("[Debug] Process killed due to timeout or stop signal.")
|
||||
myprint("[Debug] Process killed due to timeout or stop signal.")
|
||||
if istimeout: full_stdout.append("\n[Timeout Error] 超时强制终止")
|
||||
else: full_stdout.append("\n[Stopped] 用户强制终止")
|
||||
break
|
||||
@@ -271,6 +274,7 @@ class GenericAgentHandler(BaseHandler):
|
||||
self.history_info = last_history if last_history else []
|
||||
self.code_stop_signal = []
|
||||
self._done_hooks = []
|
||||
self.print = safe_print
|
||||
|
||||
def _get_abs_path(self, path):
|
||||
if not path: return ""
|
||||
@@ -304,7 +308,7 @@ class GenericAgentHandler(BaseHandler):
|
||||
except SyntaxError: exec(code, ns); result = ns.get('_r', 'OK')
|
||||
except Exception as e: result = f'Error: {e}'
|
||||
finally: os.chdir(old_cwd)
|
||||
else: result = yield from code_run(code, code_type, timeout, cwd, code_cwd=code_cwd, stop_signal=self.code_stop_signal, maxlen=maxlen)
|
||||
else: result = yield from code_run(code, code_type, timeout, cwd, code_cwd=code_cwd, stop_signal=self.code_stop_signal, maxlen=maxlen, myprint=self.print)
|
||||
next_prompt = self._get_anchor_prompt(skip=args.get('_index', 0) > 0)
|
||||
return StepOutcome(result, next_prompt=next_prompt)
|
||||
|
||||
@@ -350,8 +354,7 @@ class GenericAgentHandler(BaseHandler):
|
||||
result["js_return"] += f"\n\n[已保存完整内容到 {abs_path}]"
|
||||
except: result['js_return'] += f"\n\n[保存失败,无法写入文件 {abs_path}]"
|
||||
show = smart_format(json.dumps(result, ensure_ascii=False, indent=2, default=json_default), max_str_len=300)
|
||||
try: print("Web Execute JS Result:", show)
|
||||
except: pass
|
||||
self.print("Web Execute JS Result:", show)
|
||||
yield f"JS 执行结果:\n{show}\n"
|
||||
next_prompt = self._get_anchor_prompt(skip=args.get('_index', 0) > 0)
|
||||
result = json.dumps(result, ensure_ascii=False, default=json_default)
|
||||
@@ -429,7 +432,8 @@ class GenericAgentHandler(BaseHandler):
|
||||
def _exit_plan_mode(self): self.working.pop('in_plan_mode', None)
|
||||
def enter_plan_mode(self, plan_path):
|
||||
self.working['in_plan_mode'] = plan_path; self.max_turns = 100
|
||||
print(f"[Info] Entered plan mode with plan file: {plan_path}"); return plan_path
|
||||
self.print(f"[Info] Entered plan mode with plan file: {plan_path}")
|
||||
return plan_path
|
||||
def _check_plan_completion(self):
|
||||
if not os.path.isfile(p:=self._in_plan_mode() or ''): return None
|
||||
try: return len(re.findall(r'\[ \]', open(p, encoding='utf-8', errors='replace').read()))
|
||||
@@ -542,9 +546,7 @@ class GenericAgentHandler(BaseHandler):
|
||||
prompt += f"\nCurrent turn: {self.current_turn}\n"
|
||||
if self.working.get('key_info'): prompt += f"\n<key_info>{self.working.get('key_info')}</key_info>"
|
||||
if self.working.get('related_sop'): prompt += f"\n有不清晰的地方请再次读取{self.working.get('related_sop')}"
|
||||
if getattr(self.parent, 'verbose', False):
|
||||
try: print(prompt)
|
||||
except: pass
|
||||
if getattr(self.parent, 'verbose', False): self.print(prompt)
|
||||
return prompt
|
||||
|
||||
def turn_end_callback(self, response, tool_calls, tool_results, turn, next_prompt, exit_reason):
|
||||
|
||||
@@ -33,6 +33,8 @@ def _poll_bbs(data):
|
||||
return []
|
||||
|
||||
def check():
|
||||
check.times = getattr(check, "times", 0) + 1
|
||||
if check.times > 1000: return '/exit'
|
||||
if not _folder: return '/exit'
|
||||
data = _load()
|
||||
if not data or data.get("closed"): return '/exit'
|
||||
|
||||
Reference in new issue
Block a user