From aa674655a87fa67091ff62a2b326f9e4ea5262dd Mon Sep 17 00:00:00 2001 From: Liang Jiaqing Date: Thu, 16 Apr 2026 21:03:47 +0800 Subject: [PATCH] refactor: unify docstrings, add /resume command, simplify error msg --- agentmain.py | 8 +++++--- frontends/stapp.py | 2 +- ga.py | 35 ++++++++--------------------------- 3 files changed, 14 insertions(+), 31 deletions(-) diff --git a/agentmain.py b/agentmain.py index ba6eafe..6b7b7f8 100644 --- a/agentmain.py +++ b/agentmain.py @@ -17,13 +17,14 @@ def load_tool_schema(suffix=''): TOOLS_SCHEMA = json.loads(TS if os.name == 'nt' else TS.replace('powershell', 'bash')) load_tool_schema() +lang_suffix = '_en' if os.environ.get('GA_LANG', '') == 'en' else '' mem_dir = os.path.join(script_dir, 'memory') if not os.path.exists(mem_dir): os.makedirs(mem_dir) mem_txt = os.path.join(mem_dir, 'global_mem.txt') if not os.path.exists(mem_txt): open(mem_txt, 'w', encoding='utf-8').write('# [Global Memory - L2]\n') mem_insight = os.path.join(mem_dir, 'global_mem_insight.txt') if not os.path.exists(mem_insight): - t = os.path.join(script_dir, 'assets/global_mem_insight_template.txt') + t = os.path.join(script_dir, f'assets/global_mem_insight_template{lang_suffix}.txt') open(mem_insight, 'w', encoding='utf-8').write(open(t, encoding='utf-8').read() if os.path.exists(t) else '') cdp_cfg = os.path.join(script_dir, 'assets/tmwd_cdp_bridge/config.js') if not os.path.exists(cdp_cfg): @@ -33,8 +34,7 @@ if not os.path.exists(cdp_cfg): except Exception as e: print(f'[WARN] CDP config init failed: {e} — advanced web features (tmwebdriver) will be unavailable.') def get_system_prompt(): - suffix = '_en' if os.environ.get('GA_LANG', '') == 'en' else '' - with open(os.path.join(script_dir, f'assets/sys_prompt{suffix}.txt'), 'r', encoding='utf-8') as f: prompt = f.read() + with open(os.path.join(script_dir, f'assets/sys_prompt{lang_suffix}.txt'), 'r', encoding='utf-8') as f: prompt = f.read() prompt += f"\nToday: {time.strftime('%Y-%m-%d %a')}\n" prompt += get_global_memory() return prompt @@ -111,6 +111,8 @@ class GeneraticAgent: setattr(self.llmclient.backend, k, v) display_queue.put({'done': f"✅ session.{k} = {v!r}"}) self.task_queue.task_done(); continue + if raw_query.strip() == '/resume': + raw_query = '简单看看model_responses中的最近几次对话结尾部分(除了本次),分别简单总结一下让我选择,然后你简单阅读了解情况后作为我们接下来聊天的基础' self.is_running = True rquery = smart_format(raw_query.replace('\n', ' '), max_str_len=200) self.history.append(f"[USER]: {rquery}") diff --git a/frontends/stapp.py b/frontends/stapp.py index f7da316..2fe9afa 100644 --- a/frontends/stapp.py +++ b/frontends/stapp.py @@ -20,7 +20,7 @@ st.set_page_config(page_title="Cowork", layout="wide") def init(): agent = GeneraticAgent() if agent.llmclient is None: - st.error("⚠️ 未配置任何可用的 LLM 接口,请在 mykey.py 中添加 sider_cookie 或 oai_apikey+oai_apibase 等信息后重启。") + st.error("⚠️ 未配置任何可用的 LLM 接口,请设置mykey.py。") st.stop() else: threading.Thread(target=agent.run, daemon=True).start() return agent diff --git a/ga.py b/ga.py index b018497..0315db4 100644 --- a/ga.py +++ b/ga.py @@ -12,8 +12,7 @@ def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop """代码执行器 python: 运行复杂的 .py 脚本(文件模式) powershell/bash: 运行单行指令(命令模式) - 优先使用python,仅在必要系统操作时使用powershell。 - """ + 优先使用python,仅在必要系统操作时使用powershell""" preview = (code[:60].replace('\n', ' ') + '...') if len(code) > 60 else code.strip() yield f"[Action] Running {code_type} in {os.path.basename(cwd)}: {preview}\n" script_dir = os.path.dirname(os.path.abspath(__file__)) @@ -90,9 +89,8 @@ def code_run(code, code_type="python", timeout=60, cwd=None, code_cwd=None, stop if code_type == "python" and tmp_path and os.path.exists(tmp_path): os.remove(tmp_path) -def ask_user(question: str, candidates: list = None): - """question: 向用户提出的问题。candidates: 可选的候选项列表。需要保证should_exit为True - """ +def ask_user(question, candidates=None): + """question: 向用户提出的问题。candidates: 可选的候选项列表""" return {"status": "INTERRUPT", "intent": "HUMAN_INTERVENTION", "data": {"question": question, "candidates": candidates or []}} @@ -165,21 +163,7 @@ def log_memory_access(path): with open(stats_file, 'w', encoding='utf-8') as f: json.dump(stats, f, indent=2, ensure_ascii=False) def web_execute_js(script, switch_tab_id=None, no_monitor=False): - """ - 执行 JS 脚本来控制浏览器,并捕获结果和页面变化。 - script: 要执行的 JavaScript 代码字符串。 - return { - "status": "failed" if error_msg else "success", - "js_return": result, - "error": error_msg, - "transients": transients, - "environment": { - "newTabs": [], - "reloaded": reloaded - }, - "diff": diff_summary, - } - """ + """执行 JS 脚本来控制浏览器,并捕获结果和页面变化""" global driver try: if driver is None: first_init_driver() @@ -187,13 +171,12 @@ def web_execute_js(script, switch_tab_id=None, no_monitor=False): if switch_tab_id: driver.default_session_id = switch_tab_id result = simphtml.execute_js_rich(script, driver, no_monitor=no_monitor) return result - except Exception as e: - return {"status": "error", "msg": format_error(e)} + except Exception as e: return {"status": "error", "msg": format_error(e)} def expand_file_refs(text, base_dir=None): """展开文本中的 {{file:路径:起始行:结束行}} 引用为实际文件内容。 可与普通文本混排。展开失败抛 ValueError。 - base_dir: 相对路径的基准目录,默认为进程 cwd。""" + base_dir: 相对路径的基准目录,默认为进程 cwd""" pattern = r'\{\{file:(.+?):(\d+):(\d+)\}\}' def replacer(match): path, start, end = match.group(1), int(match.group(2)), int(match.group(3)) @@ -205,8 +188,7 @@ def expand_file_refs(text, base_dir=None): return re.sub(pattern, replacer, text) def file_patch(path: str, old_content: str, new_content: str): - """在文件中寻找唯一的 old_content 块并替换为 new_content。 - """ + """在文件中寻找唯一的 old_content 块并替换为 new_content""" path = str(Path(path).resolve()) try: if not os.path.exists(path): return {"status": "error", "msg": "文件不存在"} @@ -218,8 +200,7 @@ def file_patch(path: str, old_content: str, new_content: str): updated_text = full_text.replace(old_content, new_content) with open(path, 'w', encoding='utf-8') as f: f.write(updated_text) return {"status": "success", "msg": "文件局部修改成功"} - except Exception as e: - return {"status": "error", "msg": str(e)} + except Exception as e: return {"status": "error", "msg": str(e)} _read_dirs = set() def _scan_files(base, depth=2):