feat(v1.8.1): Windows 兼容性修复 + SKILL.md 铁律区块
Windows 兼容性修复(基于真实使用痛点):
- force_utf8_stdout(): 强制 stdout/stderr 为 UTF-8,修复 Windows GBK 崩溃(print('\\xa0') 不再炸)
- resolve_instances/load_config 新增 %APPDATA%/searxng-cli/ 路径,覆盖 Windows 配置约定
- fetch.py 失败诊断增强:输出 status_code=/cause=/url= 字段,AI Agent 可程序化区分 404/403/DNS 失败
SKILL.md 铁律区块(5 条,置顶):
- stdout=数据/stderr=日志 永不混淆
- 禁用 2>/dev/null(丢弃 stderr = 失败时零诊断)
- 排错去 --quiet 加 --verbose
- 配置查找覆盖 WSL + Windows 双路径
- 实例 URL 必填,公共实例发现已移除
测试: 352 -> 362(新增 10 个:force_utf8_stdout 幂等性/GBK 替换/非 ASCII 打印/APPDATA 路径发现/txt 回退/空 APPDATA)
This commit is contained in:
+25
-1
@@ -30,6 +30,7 @@ from common import (
|
||||
apply_proxy,
|
||||
build_auth_headers,
|
||||
detect_charset,
|
||||
force_utf8_stdout,
|
||||
is_retryable_error,
|
||||
resolve_auth_basic,
|
||||
resolve_auth_bearer,
|
||||
@@ -676,6 +677,7 @@ Examples:
|
||||
|
||||
args = parser.parse_args()
|
||||
setup_logging(verbose=args.verbose, quiet=args.quiet)
|
||||
force_utf8_stdout() # Windows: prevent GBK crash on non-ASCII chars
|
||||
|
||||
if not args.url.startswith(("http://", "https://")):
|
||||
logger.error("Error: URL must start with http:// or https://")
|
||||
@@ -711,7 +713,29 @@ Examples:
|
||||
result.content, result.content_type, result.final_url,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error: {e}")
|
||||
# 诊断信息增强:从 __cause__ 链中提取 HTTP 状态码、原始异常类型,
|
||||
# 让 AI Agent 能程序化判断失败原因(404 vs 403 vs DNS 失败等),
|
||||
# 而不是只看到一句 "HTTP 404 for ..."。
|
||||
cause = e.__cause__
|
||||
status_code = None
|
||||
cause_type = type(cause).__name__ if cause else type(e).__name__
|
||||
# urllib HTTPError 有 .code 属性;requests HTTPError 有 .response.status_code
|
||||
if cause is not None:
|
||||
status_code = (getattr(cause, "code", None) or
|
||||
getattr(getattr(cause, "response", None), "status_code", None))
|
||||
if status_code is None:
|
||||
# 最后一道兜底:从异常消息里提取 "HTTP NNN" 模式
|
||||
m = re.search(r'HTTP (\d{3})', str(e))
|
||||
if m:
|
||||
status_code = int(m.group(1))
|
||||
diag_parts = [f"Error: {e}"]
|
||||
if status_code is not None:
|
||||
diag_parts.append(f"status_code={status_code}")
|
||||
diag_parts.append(f"cause={cause_type}")
|
||||
diag_parts.append(f"url={args.url}")
|
||||
if args.no_redirect:
|
||||
diag_parts.append("redirects=disabled")
|
||||
logger.error(" | ".join(diag_parts))
|
||||
sys.exit(1)
|
||||
|
||||
if final_url != args.url:
|
||||
|
||||
Reference in New Issue
Block a user