refactor: parameterize compress/trim intervals, add stop/kill subagent actions, remove web/pet CLI commands
This commit is contained in:
1 parent
ffb268554e
commit
fc6b5ad309
3 files changed
+19
-29
No files matched your search
@@ -228,7 +228,8 @@ def conductor_readme() -> str:
|
||||
"POST /subagent\tbody: {\"prompt\": \"...\"}\t启动新subagent,返回 {\"id\": \"xxx\"}",
|
||||
'POST /subagent/{id}\tbody: {\"action\": \"keyinfo\", \"msg\": \"...\"}\t注入key_info(agent下轮可见)',
|
||||
'POST /subagent/{id}\tbody: {\"action\": \"input\", \"msg\": \"...\"}\t开新一轮任务(agent停下后追加)',
|
||||
'POST /subagent/{id}\tbody: {\"action\": \"abort\"}\t停止该subagent',
|
||||
'POST /subagent/{id}\tbody: {\"action\": \"stop\"}\t中断执行但保留(可继续input/reply)',
|
||||
'POST /subagent/{id}\tbody: {\"action\": \"kill\"}\t彻底杀死(从卡片消失,不可复用)',
|
||||
"GET /chat?last=N\t返回最近N条对话(默认20)",
|
||||
"GET /subagent\t返回 {\"items\": [...]}\t查看所有subagent状态",
|
||||
"GET /readme\t本文档",
|
||||
@@ -363,12 +364,12 @@ def api_subagent_action(sid: str, body: SubagentActionIn):
|
||||
result = input_subagent(sid, body.msg)
|
||||
result["instruction"] = "Task received. I'll handle it from here. You MUST stop now and end your reply."
|
||||
return result
|
||||
if action == "abort":
|
||||
if action in ("abort", "stop"):
|
||||
s.agent.abort()
|
||||
s.status = "aborted"
|
||||
s.status = "stopped"
|
||||
s.updated_at = time.time()
|
||||
push_cards()
|
||||
return {"id": sid, "status": "aborted"}
|
||||
return {"id": sid, "status": "stopped"}
|
||||
if action == "kill":
|
||||
s.agent.abort()
|
||||
s.status = "aborted"
|
||||
|
||||
@@ -50,13 +50,6 @@ COMMANDS = {
|
||||
"desc": "启动基于 PyQt5 的完整桌面聊天界面(气泡代码高亮、文件拖拽、历史搜索)",
|
||||
"cmd": ["python", "{FRONTENDS}/qtapp.py"],
|
||||
},
|
||||
"web": {
|
||||
"help": "启动Web增强版 (stapp2) 加 --native 使用 webview 桌面壳",
|
||||
"desc": "启动 Streamlit Web 界面,浏览器访问,适合远程/跨设备",
|
||||
"cmd": ["python", "-m", "streamlit", "run", "{FRONTENDS}/stapp2.py",
|
||||
"--server.headless", "true"],
|
||||
"flags": {"--native": {"help": "用 webview 原生窗口启动(stapp基础版)", "cmd": ["python", "{PROJECT_DIR}/launch.pyw"]}},
|
||||
},
|
||||
"configure": {
|
||||
"help": "运行初始配置向导 (configure_mykey.py)",
|
||||
"desc": "首次安装后配置 API Key、模型参数等基础设置",
|
||||
@@ -67,11 +60,6 @@ COMMANDS = {
|
||||
"desc": "启动 hub 前端管理面板(系统托盘 + 浏览器界面)",
|
||||
"cmd": ["python", "{PROJECT_DIR}/hub.pyw"],
|
||||
},
|
||||
"pet": {
|
||||
"help": "启动桌面宠物",
|
||||
"desc": "启动桌面宠物皮肤系统,桌面上陪伴你的虚拟宠物",
|
||||
"cmd": ["python", "{FRONTENDS}/desktop_pet_v2.pyw"],
|
||||
},
|
||||
"tui": {
|
||||
"help": "启动终端 TUI (tuiapp)",
|
||||
"desc": "启动终端图形界面(Textual),适合纯终端环境或 SSH",
|
||||
|
||||
+14
-13
@@ -30,11 +30,11 @@ def __getattr__(name): # once guard in PEP 562
|
||||
if name == 'mykeys': return reload_mykeys()[0]
|
||||
raise AttributeError(f"module 'llmcore' has no attribute {name}")
|
||||
|
||||
def compress_history_tags(messages, keep_recent=10, max_len=800, force=False):
|
||||
def compress_history_tags(messages, keep_recent=10, max_len=800, force=False, interval=5):
|
||||
"""Compress <thinking>/<tool_use>/<tool_result> tags in older messages to save tokens."""
|
||||
compress_history_tags._cd = getattr(compress_history_tags, '_cd', 0) + 1
|
||||
if force: compress_history_tags._cd = 0
|
||||
if compress_history_tags._cd % 5 != 0: return messages
|
||||
if compress_history_tags._cd % interval != 0: return messages
|
||||
_before = sum(len(json.dumps(m, ensure_ascii=False)) for m in messages)
|
||||
_pats = {tag: re.compile(rf'(<{tag}>)([\s\S]*?)(</{tag}>)') for tag in ('thinking', 'think', 'tool_use', 'tool_result')}
|
||||
_hist_pat = re.compile(r'<(history|key_info|earlier_context)>[\s\S]*?</\1>')
|
||||
@@ -87,11 +87,11 @@ def safeprint(*argv):
|
||||
except OSError: pass
|
||||
print = safeprint
|
||||
|
||||
def trim_messages_history(history, context_win):
|
||||
cap = context_win * 3
|
||||
target = int(cap * 0.6)
|
||||
def trim_messages_history(history, sess):
|
||||
cap = sess.context_win * 3
|
||||
target = int(cap * getattr(sess, 'trim_keep_rate', 0.6))
|
||||
def cost(): return sum(len(json.dumps(m, ensure_ascii=False)) for m in history)
|
||||
compress_history_tags(history)
|
||||
compress_history_tags(history, interval=getattr(sess, 'cut_msg_interval', 5))
|
||||
print(f'[Debug] Current context: {cost()} chars, {len(history)} messages.')
|
||||
if cost() <= cap: return
|
||||
compress_history_tags(history, keep_recent=4, force=True)
|
||||
@@ -513,12 +513,13 @@ class BaseSession:
|
||||
self.api_key = cfg['apikey']
|
||||
self.api_base = cfg['apibase'].rstrip('/')
|
||||
self.model = cfg.get('model', '')
|
||||
self.context_win = cfg.get('context_win', 30000)
|
||||
self.history = []
|
||||
self.lock = threading.Lock()
|
||||
self.system = ""
|
||||
default_context_win = 30000
|
||||
if 'deepseek' in self.model.lower():
|
||||
default_context_win = 70000; self.cut_msg_interval = 25; self.trim_keep_rate = 0.3
|
||||
self.context_win = cfg.get('context_win', default_context_win)
|
||||
self.history = []; self.lock = threading.Lock(); self.system = ""
|
||||
self.name = cfg.get('name', self.model)
|
||||
proxy = cfg.get('proxy')
|
||||
proxy = cfg.get('proxy');
|
||||
self.proxies = {"http": proxy, "https": proxy} if proxy else None
|
||||
self.max_retries = max(0, int(cfg.get('max_retries', 4)))
|
||||
self.verify = cfg.get('verify', True)
|
||||
@@ -553,7 +554,7 @@ class BaseSession:
|
||||
def _ask_gen():
|
||||
with self.lock:
|
||||
self.history.append({"role": "user", "content": [{"type": "text", "text": prompt}]})
|
||||
trim_messages_history(self.history, self.context_win)
|
||||
trim_messages_history(self.history, self)
|
||||
messages = self.make_messages(self.history)
|
||||
content_blocks = None; content = ''
|
||||
gen = self.raw_ask(messages)
|
||||
@@ -676,7 +677,7 @@ class NativeClaudeSession(BaseSession):
|
||||
assert type(msg) is dict
|
||||
with self.lock:
|
||||
self.history.append(msg)
|
||||
trim_messages_history(self.history, self.context_win)
|
||||
trim_messages_history(self.history, self)
|
||||
messages = [{"role": m["role"], "content": list(m["content"])} for m in self.history]
|
||||
content_blocks = None
|
||||
gen = self.raw_ask(messages)
|
||||
|
||||
Reference in new issue
Block a user