Files
xiaoli-cli/plugins/operit_scripts/market_reader.py
T
shuiyu67 388ac493af feat(operit): 增强转译层并接入 5 个 Operit 市场插件
operit_loader.py:
- OkHttp 新增 newClient()(真实市场插件普遍使用,而非 newBuilder)
- OkHttpRequest.execute() 改为 async,与 Operit 运行时异步语义对齐
- OkHttpResponse 新增 json() 与 statusMessage()(基于 http.HTTPStatus)

operit_translate.py(新增):
- Operit .ts 插件 -> xiaoli-cli .py 脚手架生成器
- 自动提取 METADATA、生成 exports 胶水,原 TS 作参考注释保留

plugins/operit_scripts/ 新增 5 个已跑通的真实插件:
- market_time        时间查询/格式化
- market_duckduckgo  网页内容抓取与清洗
- market_crossref    Crossref 学术文献检索
- market_network_test HTTP 连通性测试
- market_reader      本地代码递归搜索

注: 工具需注册为 async 包装函数,同步 lambda 会导致 complete() 不执行的假阳性
2026-08-07 16:38:58 +08:00

86 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# METADATA
# {
# "name": "reader",
# "display_name": { "zh": "代码读取器", "en": "Code Reader" },
# "description": { "zh": "在文件夹中搜索匹配的代码(本地文件,无需 Android)", "en": "Search matching code in a folder." },
# "category": "File",
# "tools": [
# { "name": "search_code_in_folder", "description": { "zh": "在文件夹中搜索匹配的代码", "en": "Search matching code in a folder" } }
# ]
# }
import os
import re
def getErrorMessage(error):
return str(error) if error else "unknown"
def getErrorStack(error):
import traceback
return traceback.format_exc()
async def search_code_in_folder(params):
folder_path = params.get("folder_path")
pattern = params.get("pattern")
file_extensions = params.get("file_extensions", ".js,.ts,.jsx,.tsx,.java,.cs,.py")
recursive = str(params.get("recursive", "true")).lower() in ("true", "1", "yes")
if not folder_path:
return {"success": False, "message": "文件夹路径不能为空"}
if not pattern:
return {"success": False, "message": "搜索模式不能为空"}
try:
exts = [e.strip().lower() for e in file_extensions.split(",") if e.strip()]
rx = re.compile(pattern, re.MULTILINE)
files = []
if recursive:
for root, _, fnames in os.walk(folder_path):
for fn in fnames:
if any(fn.lower().endswith(e) for e in exts):
files.append(os.path.join(root, fn))
else:
for fn in os.listdir(folder_path):
fp = os.path.join(folder_path, fn)
if os.path.isfile(fp) and any(fn.lower().endswith(e) for e in exts):
files.append(fp)
results = []
for fp in files:
try:
with open(fp, "r", encoding="utf-8", errors="replace") as fh:
content = fh.read()
except Exception as e:
console.error(f"处理文件 {fp} 时出错: {getErrorMessage(e)}")
continue
matches = []
for m in rx.finditer(content):
ln = content.count("\n", 0, m.start()) + 1
matches.append({"match": m.group(0), "line": ln,
"content": content.split("\n")[ln - 1] if ln - 1 < len(content.split("\n")) else ""})
if matches:
results.append({"file": fp, "matches": matches})
total = sum(len(r["matches"]) for r in results)
return {"success": True, "message": f"在 {len(files)} 个文件中找到 {total} 处匹配",
"data": {"files_searched": len(files), "files_with_matches": len(results),
"total_matches": total, "results": results[:50]}}
except Exception as e:
return {"success": False, "message": f"搜索失败: {getErrorMessage(e)}"}
async def wrap(func, params, ok_msg="操作成功", err_msg="操作失败"):
try:
result = await func(params)
complete({"success": True, "message": result.get("message", ok_msg),
"data": result.get("data"), **{k: v for k, v in result.items() if k not in ("success", "message", "data")}})
except Exception as error:
console.error(f"Error: {getErrorMessage(error)}")
complete({"success": False, "message": getErrorMessage(error), "error_stack": getErrorStack(error)})
async def search_code_in_folder_wrapper(params):
await wrap(search_code_in_folder, params, "代码搜索完成", "代码搜索失败")
exports.search_code_in_folder = search_code_in_folder_wrapper