feat: 将 47 个 Operit TypeScript 脚本全面翻译为 Python

- 新增 operit_runtime.py: 跨平台 Python 运行时
  - 实现 Tools.System/Files/Net/UI/Memory/FFmpeg/Workflow/Chat/SoftwareSettings/Tasker
  - 实现 OkHttp 链式 HTTP 客户端兼容层
  - 实现 complete()/exports/console 全局对象
  - 实现 OperitScriptLoader 脚本加载器
  - 支持 Windows/macOS/Linux 三平台

- 新增 operit_py/ 目录: 47 个 Python 翻译脚本
  - 搜索类: duckduckgo, google_search, tavily, zhipu_search, various_search, crossref
  - 绘图类: openai_draw, qwen_draw, xai_draw, minimax_draw, siliconflow_draw, zhipu_draw, nanobanana_draw
  - 媒体类: ffmpeg, file_converter, douyin_download, bilibili_tools, jmcomic
  - 文件类: extended_file_tools, hex_editor, reader, beeimg_image_uploader
  - 网络类: extended_http_tools, network_test
  - 自动化类: browser, automatic_ui_base, automatic_ui_subagent, automatic_bilibili_assistant, automatic_xiaohongshu_assistant, automatic_baidu_map_assistant
  - 系统类: system_tools, super_admin, daily_life, operit_editor
  - 对话类: ai_chat, extended_chat, qq_intelligent
  - 工作流类: workflow, vflow_trigger, tasker
  - 工具类: time, code_runner, quick_start, extended_memory_tools, baidu_map, 12306, pdf_vision_parser

- 测试结果: 47/47 语法检查通过, 38 脚本加载成功, 280 个工具注册
- Android 专属功能已降级处理(保留接口,返回不支持提示)
This commit is contained in:
shuiyu1123 committed 2026-06-23 12:27:18 +00:00
1 parent 6fa759665d
commit dc77dfd304
48 files changed
+22273

No files matched your search

+390
View File
@@ -0,0 +1,390 @@
# METADATA
# {
# "name": "Automatic_ui_subagent",
# "display_name": {"zh": "自动化AutoGLM子代理", "en": "Automated AutoGLM Sub-agent"},
# "description": {"zh": "兼容AutoGLM,提供基于独立UI控制器模型(例如 autoglm-phone-9b)的高层UI自动化子代理工具,用于根据自然语言意图自动规划并执行点击/输入/滑动等一系列界面操作。当用户提出需要帮忙完成某个界面操作任务(例如打开应用、搜索内容、在多个页面之间完成一套步骤)时,可以调用本包由子代理自动规划和执行具体步骤。", "en": "Compatible with AutoGLM. Provides a high-level UI automation sub-agent based on an independent UI-controller model (e.g. autoglm-phone-9b). It can plan and execute a sequence of UI actions (tap/type/swipe) from natural-language intent. When the user asks you to complete a UI task (e.g. open an app, search content, or finish a multi-step workflow across pages), you can call this package and let the sub-agent plan and execute the steps."},
# "category": "Automatic",
# "tools": [],
# "states": [
# {"id": "virtual_display", "condition": "ui.virtual_display", "inheritTools": True, "tools": [
# {"name": "usage_advice", "description": {"zh": "UI子代理使用建议", "en": "UI sub-agent usage advice."}, "advice": True, "parameters": []},
# {"name": "run_subagent_main", "description": {"zh": "在主屏幕运行 UI 子代理(强制主屏)。", "en": "Run the UI sub-agent on the main screen (forced main screen)."}, "parameters": [
# {"name": "intent", "description": {"zh": "任务意图描述", "en": "Task intent description"}, "type": "string", "required": True},
# {"name": "target_app", "description": {"zh": "目标应用名/包名(可选)", "en": "Target app name/package (optional)"}, "type": "string", "required": False},
# {"name": "max_steps", "description": {"zh": "最大执行步数(默认20)", "en": "Maximum execution steps (default: 20)"}, "type": "number", "required": False}
# ]},
# {"name": "run_subagent_virtual", "description": {"zh": "在虚拟屏幕会话运行 UI 子代理(强制虚拟屏)。", "en": "Run the UI sub-agent on a virtual-display session (forced virtual screen)."}, "parameters": [
# {"name": "intent", "description": {"zh": "任务意图描述", "en": "Task intent description"}, "type": "string", "required": True},
# {"name": "target_app", "description": {"zh": "目标应用名/包名(可选)", "en": "Target app name/package (optional)"}, "type": "string", "required": False},
# {"name": "max_steps", "description": {"zh": "最大执行步数(默认20)", "en": "Maximum execution steps (default: 20)"}, "type": "number", "required": False},
# {"name": "agent_id", "description": {"zh": "虚拟屏会话 agent_id(必须为非 'default';可传入复用,或留空复用上次返回的 data.agentId)。", "en": "Virtual-screen session agent_id (must be non-'default'; pass to reuse, or omit to reuse returned data.agentId)."}, "type": "string", "required": False}
# ]},
# {"name": "run_subagent_parallel_virtual", "description": {"zh": "并行运行 1-4 个 UI 子代理(强制虚拟屏)。", "en": "Run 1-4 UI sub-agents in parallel (forced virtual screen)."}, "parameters": []},
# {"name": "close_all_virtual_displays", "description": {"zh": "关闭所有虚拟屏幕。", "en": "Close all virtual displays."}, "parameters": []}
# ]},
# {"id": "main_screen", "condition": "!ui.virtual_display", "inheritTools": True, "tools": [
# {"name": "usage_advice", "description": {"zh": "UI子代理使用建议(主屏模式)", "en": "UI sub-agent usage advice (main-screen mode)."}, "advice": True, "parameters": []},
# {"name": "run_subagent_main", "description": {"zh": "在主屏幕运行 UI 子代理(强制主屏)。", "en": "Run the UI sub-agent on the main screen (forced main screen)."}, "parameters": [
# {"name": "intent", "description": {"zh": "任务意图描述", "en": "Task intent description"}, "type": "string", "required": True},
# {"name": "target_app", "description": {"zh": "目标应用名/包名(可选)", "en": "Target app name/package (optional)"}, "type": "string", "required": False},
# {"name": "max_steps", "description": {"zh": "最大执行步数(默认20)", "en": "Maximum execution steps (default: 20)"}, "type": "number", "required": False}
# ]}
# ]}
# ]
# }
import json
import re
import asyncio
from urllib.parse import quote, unquote
Error = Exception
CACHE_KEY = '__operit_ui_subagent_cached_agent_id'
_global_cache = {}
def getCachedAgentId():
try:
return _global_cache.get(CACHE_KEY)
except Exception:
return None
def setCachedAgentId(value):
try:
if value is None or len(str(value)) == 0:
_global_cache.pop(CACHE_KEY, None)
else:
_global_cache[CACHE_KEY] = str(value)
except Exception:
pass
def getPackageState():
try:
return getState()
except Exception:
return None
def errorMessage(e):
if isinstance(e, Exception):
return str(e)
return str(e)
def getStringArrayFromUnknown(v):
if not isinstance(v, list):
return []
return [str(x or '').strip() for x in v if str(x or '').strip()]
def parseInstalledAppEntry(raw):
s = str(raw or '').strip()
if not s:
return {"name": '', "raw": ''}
open_idx = s.rfind('(')
close_idx = s.rfind(')')
if open_idx >= 0 and close_idx == len(s) - 1 and open_idx < close_idx:
name = s[:open_idx].strip()
pkg = s[open_idx + 1:close_idx].strip()
if name and pkg:
return {"name": name, "pkg": pkg, "raw": s}
return {"name": s, "raw": s}
async def getInstalledApps():
appList = await Tools.System.listApps(False)
rawItems = getStringArrayFromUnknown(getattr(appList, "packages", None) if appList else None)
entries = [e for e in [parseInstalledAppEntry(r) for r in rawItems] if e["name"]]
nameMap = {}
for e in entries:
nameMap[e["name"].lower()] = e["name"]
names = sorted(nameMap.values())
return {"entries": entries, "names": names}
def matchTarget(targetApp, installed):
t = str(targetApp or '').strip()
if not t:
return None
tl = t.lower()
m = None
for a in installed:
if (a.get("pkg") or '').lower() == tl:
m = a
break
if not m:
for a in installed:
if a["name"].lower() == tl:
m = a
break
if not m:
for a in installed:
if a["raw"].lower() == tl:
m = a
break
if not m:
return None
run = m.get("pkg") or m["name"]
return {"run": run, "key": run.lower()}
async def usage_advice(params):
state = getPackageState()
isMainScreen = str(state).lower() == 'main_screen'
return {
"success": True,
"message": 'UI子代理使用建议',
"data": {
"advice": (
"主屏模式:不支持 agent_id,会话复用策略不适用;不支持并行工具,一次只做一个明确子目标(必要时拆多次)。\n"
"屏幕选择规则:不传 agent_id 或传 'default' => 主屏幕;传入且不为 'default' => 虚拟屏(主屏模式下会忽略并强制主屏)。\n"
"启动前置(非常重要):当你第一次需要操作某个应用时,intent 开头必须写'启动XXX应用 ...',让子代理直接执行 Launch,而不是在桌面自己找。\n"
"对话无状态:每次调用是新对话,intent 写清 已完成/下一步/关键信息。\n"
"自包含:别用'这五个/继续/同上';多对象要么列清单+当前目标,要么先让子代理在当前页识别并复述清单。\n"
"失败与完成:半成功不算完成;未达成目标继续推进,连续 2-3 次失败再停并说明原因。"
) if isMainScreen else (
"虚拟屏模式:尽量复用 agent_id(沿用 data.agentId)保持同一虚拟屏/同一应用上下文。\n"
"屏幕选择规则:不传 agent_id 或传 'default' => 主屏幕;传入且不为 'default' => 对应虚拟屏会话(虚拟屏必须可用,否则失败)。为避免误操作主屏,虚拟屏模式下首次调用建议显式传入 agent_id。\n"
"启动前置(非常重要):当你第一次使用某个 agent_id(新建或更换 agent_id)时,intent 开头必须写'启动XXX应用 ...',让子代理直接执行 Launch,而不是在桌面自己找。\n"
"对话无状态:每次调用是新对话,intent 写清 已完成/下一步/关键信息。\n"
"自包含:别用'这五个/继续/同上';多对象要么列清单+当前目标,要么先让子代理在当前页识别并复述清单。\n"
"对齐+并行:先清单后逐项(A→B→C);独立子任务/同一对象多入口优先并行(run_subagent_parallel_virtual),只重试失败分支。\n"
"并行资源约束:并行分支数必须受可用独立App/虚拟屏数量限制;同一个App/包名不能同时出现在两个虚拟屏/两个agent_id 中并行操作(会坏)。并行调用必须传 target_app_i=目标应用名,且各分支 target_app_i 不能重复;第2次/第N次并行不得擅自提高并行度,保持上限,只重试失败分支或改串行。\n"
"失败与完成:半成功不算完成;未达成目标继续推进,连续 2-3 次失败再停并说明原因。"
),
},
}
async def run_subagent_internal(params):
intent = params.get("intent")
max_steps = params.get("max_steps")
agent_id = params.get("agent_id")
target_app = params.get("target_app")
state = getPackageState()
isMainScreen = str(state).lower() == 'main_screen'
explicitAgentId = '' if agent_id is None else str(agent_id).strip()
cachedAgentId = getCachedAgentId()
if isMainScreen:
agentIdToUse = 'default'
else:
agentIdToUse = explicitAgentId if len(explicitAgentId) > 0 else cachedAgentId
if agentIdToUse is None or len(str(agentIdToUse).strip()) == 0:
return {
"success": False,
"message": "虚拟屏模式下未指定 agent_id:为避免误操作主屏幕,请显式传入 agent_id(且不为 'default')来使用虚拟屏会话;或先完成一次成功调用并复用返回的 data.agentId。",
}
targetAppForRun = target_app
if target_app and len(str(target_app).strip()) > 0:
installed = await getInstalledApps()
matched = matchTarget(target_app, installed["entries"])
if not matched:
return {
"success": False,
"message": f"目标应用不存在:当前给定的 target_app='{str(target_app).strip()}' 未在已安装应用中找到。已返回已安装应用名列表。",
"data": {
"target_app": str(target_app).strip(),
"installed_apps": installed["names"],
},
}
targetAppForRun = matched["run"]
result = await Tools.UI.runSubAgent(intent, max_steps, agentIdToUse, targetAppForRun)
agentId = getattr(result, "agentId", None) if result else None
if agentId and len(str(agentId).strip()) > 0 and str(agentId).strip().lower() != 'default':
setCachedAgentId(agentId)
return {
"success": True,
"message": 'UI子代理执行完成',
"data": result,
}
async def run_subagent_main(params):
intent = params.get("intent")
max_steps = params.get("max_steps")
target_app = params.get("target_app")
return await run_subagent_internal({"intent": intent, "max_steps": max_steps, "target_app": target_app, "agent_id": 'default'})
async def run_subagent_virtual(params):
intent = params.get("intent")
max_steps = params.get("max_steps")
agent_id = params.get("agent_id")
target_app = params.get("target_app")
explicitAgentId = '' if agent_id is None else str(agent_id).strip()
cachedAgentId = getCachedAgentId()
agentIdToUse = explicitAgentId if len(explicitAgentId) > 0 else cachedAgentId
if agentIdToUse is None or len(str(agentIdToUse).strip()) == 0 or str(agentIdToUse).strip().lower() == 'default':
return {
"success": False,
"message": "虚拟屏模式必须使用非 'default' 的 agent_id:请显式传入 agent_id(非 'default'),或先完成一次成功调用并复用返回的 data.agentId。",
}
return await run_subagent_internal({"intent": intent, "max_steps": max_steps, "target_app": target_app, "agent_id": str(agentIdToUse)})
async def run_subagent_parallel_internal(params):
state = getPackageState()
isMainScreen = str(state).lower() == 'main_screen'
if isMainScreen:
return {
"success": False,
"message": "主屏模式不支持 run_subagent_parallel_virtual 并行调用。请改用 run_subagent_main 串行执行。",
}
slots = [1, 2, 3, 4]
activeSlots = []
for i in slots:
intent = params.get(f"intent_{i}")
if not intent or len(str(intent).strip()) == 0:
continue
targetApp = params.get(f"target_app_{i}")
activeSlots.append({"index": i, "targetApp": targetApp})
missingTargets = [s["index"] for s in activeSlots if s["targetApp"] is None or len(str(s["targetApp"]).strip()) == 0]
if len(missingTargets) > 0:
_missing_str = ', '.join(str(x) for x in missingTargets)
return {
"success": False,
"message": f"并行参数错误:intent_{_missing_str} 缺少 target_app_{_missing_str}(目标应用名)。并行时必须为每个启用分支传入目标应用名,用于检测'同一应用不能出现在两个虚拟屏/agent_id'的冲突。",
}
missingAgentIds = []
for s in activeSlots:
v = params.get(f"agent_id_{s['index']}")
id_ = '' if v is None else str(v).strip()
if len(id_) == 0 or id_.lower() == 'default':
missingAgentIds.append(s["index"])
if len(missingAgentIds) > 0:
return {
"success": False,
"message": f"并行参数错误:虚拟屏并行模式下,每个启用分支必须显式传入非 'default' 的 agent_id。缺少/非法 agent_id 的分支:{', '.join(f'#{i}' for i in missingAgentIds)}。",
}
installed = await getInstalledApps()
resolvedBySlot = {}
missingApps = []
for s in activeSlots:
t = str(s["targetApp"] or '').strip()
m = matchTarget(t, installed["entries"])
if not m:
missingApps.append(t)
else:
resolvedBySlot[s["index"]] = m
if len(missingApps) > 0:
_apps_str = ', '.join(f"'{str(s).strip()}'" for s in missingApps)
return {
"success": False,
"message": f"目标应用不存在:当前给定的 target_app 列表中包含未安装/不存在的应用:{_apps_str}。已返回已安装应用名列表。",
"data": {
"missing_apps": missingApps,
"installed_apps": installed["names"],
},
}
used = {}
for s in activeSlots:
key = (resolvedBySlot.get(s["index"]) or {}).get("key") or str(s["targetApp"]).strip().lower()
prev = used.get(key)
if prev is not None:
return {
"success": False,
"message": f"并行参数错误:target_app_{prev} 与 target_app_{s['index']} 重复(同一目标应用='{str(s['targetApp']).strip()}')。同一应用不能同时在两个虚拟屏/agent_id 中并行操作。",
}
used[key] = s["index"]
async def runOne(i):
intent = params.get(f"intent_{i}")
if not intent or len(str(intent).strip()) == 0:
return None
maxSteps = params.get(f"max_steps_{i}")
agentId = params.get(f"agent_id_{i}")
targetApp = (resolvedBySlot.get(i) or {}).get("run") or params.get(f"target_app_{i}")
try:
result = await Tools.UI.runSubAgent(
str(intent),
maxSteps,
None if agentId is None or len(str(agentId).strip()) == 0 else str(agentId).strip(),
targetApp,
)
return {"index": i, "success": True, "result": result}
except Exception as e:
return {"index": i, "success": False, "error": errorMessage(e)}
tasks = [runOne(i) for i in slots]
raw_results = await asyncio.gather(*tasks)
results = [r for r in raw_results if r is not None]
okCount = len([r for r in results if r["success"]])
return {
"success": True,
"message": f"并行UI子代理执行完成:成功 {okCount} 个 / 共 {len(results)} 个",
"data": {"results": results},
}
async def run_subagent_parallel_virtual(params):
return await run_subagent_parallel_internal(params)
async def close_all_virtual_displays(params):
result = await toolCall('close_all_virtual_displays', {})
ok = getattr(result, "success", None) if result else None
ok = ok is not False
error = getattr(result, "error", None) if result else None
return {
"success": ok,
"message": '已关闭所有虚拟屏幕。' if ok else f"关闭虚拟屏幕失败:{str(error) if error else 'unknown error'}",
"data": result,
}
async def wrapToolExecution(func, params):
try:
result = await func(params)
complete(result)
except Exception as error:
console.error(f"Tool {func.__name__} failed unexpectedly", error)
complete({
"success": False,
"message": f"工具执行时发生意外错误: {errorMessage(error)}",
})
async def _usage_advice_wrapper(params):
await wrapToolExecution(usage_advice, params)
async def _run_subagent_main_wrapper(params):
await wrapToolExecution(run_subagent_main, params)
async def _run_subagent_virtual_wrapper(params):
await wrapToolExecution(run_subagent_virtual, params)
async def _close_all_virtual_displays_wrapper(params):
await wrapToolExecution(close_all_virtual_displays, params)
async def _run_subagent_parallel_virtual_wrapper(params):
await wrapToolExecution(run_subagent_parallel_virtual, params)
exports.usage_advice = _usage_advice_wrapper
exports.run_subagent_main = _run_subagent_main_wrapper
exports.run_subagent_virtual = _run_subagent_virtual_wrapper
exports.close_all_virtual_displays = _close_all_virtual_displays_wrapper
exports.run_subagent_parallel_virtual = _run_subagent_parallel_virtual_wrapper