tui.js:修 mmReadCatalog Windows GBK 编码坑(sys.stdout.buffer.write + PYTHONUTF8)

This commit is contained in:
youpaishidifu
2026-10-19 10:36:51 +08:00
parent 0d2d1144eb
commit 043fd55ae1
+11 -6
View File
@@ -426,20 +426,25 @@ function mmReadCatalog() {
return new Promise((resolve) => { return new Promise((resolve) => {
try { try {
const py = process.platform === "win32" ? "python" : "python3" const py = process.platform === "win32" ? "python" : "python3"
// 注意:Python `-c` 单行脚本里 `if row: import sys;` 是非法语法(import 不能跟在 if 同行) // 注意两点坑:
// 提前 import sys,用 `sys.stdout.write(row[0]) if row else None` 替代 if 行 // 1. Python `-c` 单行里 `if row: import sys;` 非法(import 不能跟 if 同行)→ 提前 import sys
// 2. Windows 控制台默认 GBK 编码,catalog 含非 GBK 字符(如 U+2011)会 UnicodeEncodeError
// → 用 sys.stdout.buffer.write 走原始字节(utf-8 编码),Node 侧按 utf-8 解码
const script = const script =
"import sqlite3,os,sys;" + "import sqlite3,os,sys;" +
"db=os.path.join(os.path.expanduser('~'),'.local','share','opencode','opencode.db');" + "db=os.path.join(os.path.expanduser('~'),'.local','share','opencode','opencode.db');" +
"con=sqlite3.connect(db);" + "con=sqlite3.connect(db);" +
"row=con.execute(\"SELECT value FROM kv WHERE key='models-dev:catalog'\").fetchone();" + "row=con.execute(\"SELECT value FROM kv WHERE key='models-dev:catalog'\").fetchone();" +
"con.close();" + "con.close();" +
"sys.stdout.write(row[0]) if row else None" "sys.stdout.buffer.write(row[0].encode('utf-8')) if row else None"
const r = spawn(py, ["-c", script], { stdio: ["ignore", "pipe", "pipe"] }) const r = spawn(py, ["-c", script], {
stdio: ["ignore", "pipe", "pipe"],
env: { ...process.env, PYTHONIOENCODING: "utf-8", PYTHONUTF8: "1" },
})
let out = "" let out = ""
let err = "" let err = ""
r.stdout.on("data", (d) => (out += d)) r.stdout.on("data", (d) => (out += d.toString("utf-8")))
r.stderr.on("data", (d) => (err += d)) r.stderr.on("data", (d) => (err += d.toString("utf-8")))
r.on("close", () => { r.on("close", () => {
try { try {
if (out.trim()) resolve(JSON.parse(out.trim())) if (out.trim()) resolve(JSON.parse(out.trim()))