bugfix
This commit is contained in:
parent
56602d54a0
commit
dc183da3e2
@ -42,7 +42,7 @@ class LLMHandler:
|
||||
exception(f'{e}\n{format_exc()}')
|
||||
return txt
|
||||
|
||||
async def run_subprocess(command, cwd, env, timeout=30.0):
|
||||
async def run_subprocess(command, cwd, env, input_str=None, timeout=30.0):
|
||||
try:
|
||||
# 启动子进程
|
||||
# stdout/stderr 设置为 PIPE 对应原来的 capture_output=True
|
||||
@ -50,6 +50,7 @@ async def run_subprocess(command, cwd, env, timeout=30.0):
|
||||
command,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
cwd=cwd,
|
||||
env=env,
|
||||
# 注意:asyncio 默认处理字节流,如果需要文本,后面需手动 decode
|
||||
@ -58,7 +59,8 @@ async def run_subprocess(command, cwd, env, timeout=30.0):
|
||||
# 使用 wait_for 实现 timeout 功能
|
||||
try:
|
||||
# wait_for 会在超时后抛出 TimeoutError 并自动 cancel 协程
|
||||
stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=timeout)
|
||||
input_bytes = input_str.encode() if input_str else None
|
||||
stdout, stderr = await asyncio.wait_for(process.communicate(input=input_bytes), timeout=timeout)
|
||||
except asyncio.TimeoutError:
|
||||
process.kill() # 超时强制杀掉进程
|
||||
await process.wait() # 确保资源回收
|
||||
@ -130,9 +132,14 @@ class IndustrialSkillEngine:
|
||||
(skill["root"] / ".deps_installed").touch()
|
||||
|
||||
# --- 3. 增强版安全执行器:带重试逻辑与审计 ---
|
||||
async def _execute_with_retry(self, command: str, skill_name: str, retry_count=1) -> str:
|
||||
async def _execute_with_retry(self, cmdjson: dict, skill_name: str, retry_count=1) -> str:
|
||||
await self._ensure_dependencies(skill_name)
|
||||
|
||||
command = cmdjson['cmd']
|
||||
params = cmdjson.get('params')
|
||||
params_str=None
|
||||
if params:
|
||||
params_str = json.dumps(params, ensure_ascii=False)
|
||||
# 安全预检:禁止敏感命令
|
||||
forbidden = ["rm ", "> /dev/", "chmod", "sudo"]
|
||||
if any(f in command for f in forbidden):
|
||||
@ -143,8 +150,11 @@ class IndustrialSkillEngine:
|
||||
try:
|
||||
env = os.environ.copy()
|
||||
env["SKILL_CONTEXT"] = skill_name
|
||||
|
||||
res = await run_subprocess(command, cwd=self.registry[skill_name]["root"], env=env, timeout=30)
|
||||
intput_str = json.dumps(params, ensure_ascii=False)
|
||||
res = await run_subprocess(command, cwd=self.registry[skill_name]["root"],
|
||||
env=env,
|
||||
input_str=params_str,
|
||||
timeout=30)
|
||||
|
||||
if res.return_code != 0:
|
||||
# 工业级特性:自动将错误回传给 LLM 进行自愈 (Self-healing)
|
||||
@ -238,7 +248,7 @@ class IndustrialSkillEngine:
|
||||
context = await self._get_expanded_context(skill_name, user_prompt, context=context)
|
||||
|
||||
# 决策:是直接回答还是执行脚本
|
||||
decision = await self.llm(f"上下文: {context}\n问题: {user_prompt}\n决定动作:EXEC: <command> 或 ANSWER: <text> 或 REPLY: <question>")
|
||||
decision = await self.llm(f"上下文: {context}\n问题: {user_prompt}\n决定动作:EXEC: {"cmd": found_cmd, "params": found_parameters_dict} 或 ANSWER: <text> 或 REPLY: <question>")
|
||||
output = {
|
||||
"status": "PROCESSING",
|
||||
"hint": f"决策完成:{decision=}"
|
||||
@ -262,7 +272,8 @@ class IndustrialSkillEngine:
|
||||
return
|
||||
if "EXEC:" in decision:
|
||||
cmd = decision.split("EXEC:")[1].strip()
|
||||
output = await self._execute_with_retry(cmd, skill_name)
|
||||
jd = json.loads(cmd)
|
||||
output = await self._execute_with_retry(jd, skill_name)
|
||||
if isinstance(output, str):
|
||||
output = {
|
||||
"status": "SUCCEEDED",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user