fix: content quality, image format, task monitor, calendar data source, search UI & sort
This commit is contained in:
+60
-21
@@ -23,13 +23,57 @@ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(level
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
SEARCH_CACHE_FILE = PROJECT_ROOT / "automation" / "data" / "search_cache.json"
|
||||
SESSION_FILE = PROJECT_ROOT / "automation" / "data" / "opencode_session.txt"
|
||||
|
||||
|
||||
def _get_or_create_session() -> Optional[str]:
|
||||
"""获取或创建持久 session ID"""
|
||||
if SESSION_FILE.exists():
|
||||
try:
|
||||
sid = SESSION_FILE.read_text().strip()
|
||||
if sid:
|
||||
result = subprocess.run(
|
||||
["npx", "opencode", "run", "ping", "--session", sid, "--format", "json"],
|
||||
capture_output=True, text=True, timeout=10,
|
||||
cwd=str(PROJECT_ROOT),
|
||||
env={**os.environ, "OPENCODE_DISABLE_AUTOUPDATE": "1"}
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return sid
|
||||
except Exception:
|
||||
pass
|
||||
result = subprocess.run(
|
||||
["npx", "opencode", "run", "init", "--format", "json"],
|
||||
capture_output=True, text=True, timeout=30,
|
||||
cwd=str(PROJECT_ROOT),
|
||||
env={**os.environ, "OPENCODE_DISABLE_AUTOUPDATE": "1"}
|
||||
)
|
||||
for line in result.stdout.strip().split("\n"):
|
||||
try:
|
||||
event = json.loads(line)
|
||||
sid = event.get("sessionID") or event.get("part", {}).get("sessionID")
|
||||
if sid:
|
||||
SESSION_FILE.write_text(sid)
|
||||
return sid
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
_session_id = None
|
||||
|
||||
|
||||
def _run_opencode(prompt: str, timeout: int = 60) -> Optional[str]:
|
||||
"""调用 opencode run 执行任务,返回文本输出"""
|
||||
global _session_id
|
||||
if _session_id is None:
|
||||
_session_id = _get_or_create_session()
|
||||
args = ["npx", "opencode", "run", prompt, "--format", "json"]
|
||||
if _session_id:
|
||||
args.extend(["--session", _session_id, "--continue"])
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["npx", "opencode", "run", prompt, "--format", "json"],
|
||||
args,
|
||||
capture_output=True, text=True, timeout=timeout,
|
||||
cwd=str(PROJECT_ROOT),
|
||||
env={**os.environ, "OPENCODE_DISABLE_AUTOUPDATE": "1"}
|
||||
@@ -66,28 +110,23 @@ def _run_opencode(prompt: str, timeout: int = 60) -> Optional[str]:
|
||||
|
||||
|
||||
def search_via_opencode(query: str, max_results: int = 5) -> List[Dict]:
|
||||
"""通过 opencode 联网搜索"""
|
||||
prompt = f"""用 webfetch 搜索:{query}
|
||||
只输出 JSON 数组 [{{"title":"标题","url":"链接","content":"摘要"}}],最多 {max_results} 条,不要其他文字。"""
|
||||
|
||||
output = _run_opencode(prompt, timeout=90)
|
||||
if not output:
|
||||
return []
|
||||
|
||||
m = re.search(r'\[\s*\{.*\}\s*\]', output, re.DOTALL)
|
||||
if not m:
|
||||
logger.warning(f"未找到JSON数组: {output[:150]}")
|
||||
return []
|
||||
"""通过 MCP 搜索工具联网搜索(替代脆弱的 npx prompt 方式)"""
|
||||
try:
|
||||
results = json.loads(m.group())
|
||||
if isinstance(results, list):
|
||||
for r in results:
|
||||
r["source"] = "opencode_webfetch"
|
||||
logger.info(f"opencode 搜索 '{query[:20]}': {len(results)} 条")
|
||||
return results[:max_results]
|
||||
from search_utils import search
|
||||
return search(query, max_results)
|
||||
except Exception as e:
|
||||
logger.warning(f"JSON解析失败: {e}")
|
||||
return []
|
||||
logger.warning("search_utils 不可用,回退子进程: %s", e)
|
||||
result = subprocess.run(
|
||||
[sys.executable, str(PROJECT_ROOT / "scripts" / "mcp_search_server.py"),
|
||||
"--query", query],
|
||||
capture_output=True, text=True, timeout=90,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
try:
|
||||
return json.loads(result.stdout)[:max_results]
|
||||
except Exception:
|
||||
pass
|
||||
return []
|
||||
|
||||
|
||||
def refresh_cache():
|
||||
|
||||
Reference in New Issue
Block a user