diff --git a/tools/oc-session-sync.py b/tools/oc-session-sync.py index 8e615e1..96ad631 100644 --- a/tools/oc-session-sync.py +++ b/tools/oc-session-sync.py @@ -173,32 +173,51 @@ except Exception as e: open("/root/.oc_sync_result.json", "w", encoding="utf-8").write(json.dumps(res)) ''' -# ★ 存量 worktree 洗白(2026-10-20 截图实锤「Session location unavailable / C:/Users/ypshidifu」): -# IMPORT 用 INSERT OR IGNORE —— WSL 已存在的 project 行永远不会被 UPDATE, -# 推送侧的路径转换只对「新插入」的行生效,存量 Win 路径洗不掉。 -# 此脚本每次同步无条件跑(幂等 UPDATE,开销可忽略),把 WSL project 表里 -# 所有 C:/Users/ypshidifu 或 C:\Users\ypshidifu 前缀的 worktree 洗成 /root。 +# ★ 存量 Win 路径洗白(2026-10-20 二次实锤:OC 2.x 的 "Session location" 读的是 +# session/session_v2 表自身的 directory 列,不只是 project.worktree! +# 目标会话 ses_eb074c0daffe 的 session_v2.directory = "C:/Users/ypshidifu" 即截图来源。 +# 且 IMPORT 用 INSERT OR IGNORE —— WSL 已存在的行永远不会被 UPDATE, +# 推送侧转换只对「新插入」的行生效。此脚本每次同步无条件跑(幂等 UPDATE), +# 把三张表里所有 Win home 前缀的路径洗成 /root。 FIX_WORKTREE_SRC = r''' import sqlite3 BK = chr(92) PRE_SL = "C:/Users/ypshidifu" PRE_BK = "C:" + BK + "Users" + BK + "ypshidifu" -res = {"fixed": 0, "err": None} +res = {"fixed": {}, "err": None} +def conv(p): + if not p or not isinstance(p, str): + return None + if p.startswith(PRE_SL): + return "/root" + p[len(PRE_SL):] + if p.startswith(PRE_BK): + return "/root" + p[len(PRE_BK):] + return None try: con = sqlite3.connect("/root/.local/share/opencode/opencode.db") cur = con.cursor() - rows = cur.execute("select id, worktree from project").fetchall() - for pid, wt in rows: - if not wt or not isinstance(wt, str): - continue - if wt.startswith(PRE_SL): - cur.execute("update project set worktree=? where id=?", - ("/root" + wt[len(PRE_SL):], pid)) - res["fixed"] += 1 - elif wt.startswith(PRE_BK): - cur.execute("update project set worktree=? where id=?", - ("/root" + wt[len(PRE_BK):], pid)) - res["fixed"] += 1 + # project.worktree + n = 0 + for pid, wt in cur.execute("select id, worktree from project").fetchall(): + nw = conv(wt) + if nw: + cur.execute("update project set worktree=? where id=?", (nw, pid)) + n += 1 + res["fixed"]["project.worktree"] = n + # session.directory(列存在才跑) + def fix_dir(table): + cols = [r[1] for r in cur.execute("PRAGMA table_info(%s)" % table)] + if "directory" not in cols: + return -1 + n = 0 + for sid, d in cur.execute("select id, directory from %s" % table).fetchall(): + nw = conv(d) + if nw: + cur.execute("update %s set directory=? where id=?" % table, (nw, sid)) + n += 1 + return n + res["fixed"]["session.directory"] = fix_dir("session") + res["fixed"]["session_v2.directory"] = fix_dir("session_v2") con.commit() con.close() except Exception as e: @@ -340,16 +359,26 @@ def main(): list(targets), ) ] - # ★ project.worktree 路径转换(Win C:/Users/ypshidifu/... -> WSL /root/...) + # ★ Win 路径转换(C:/Users/ypshidifu / C:\Users\ypshidifu -> /root) # 修 WSL 侧「Session location unavailable / C:/Users/ypshidifu」 + # 2026-10-20 二次实锤:OC 2.x 的 location 显示读 session/session_v2 自己的 + # directory 列,project.worktree 也要转,三处一起。 + def _conv_win_path(p): + if not isinstance(p, str): + return p + if p.startswith(_WIN_HOME_PREFIX_SL): + return _WSL_HOME_PREFIX + p[len(_WIN_HOME_PREFIX_SL):] + if p.startswith("C:" + chr(92) + "Users" + chr(92) + "ypshidifu"): + return _WSL_HOME_PREFIX + p[len("C:" + chr(92) + "Users" + chr(92) + "ypshidifu"):] + return p + if tables.get("project"): - _wkcol = "worktree" for _pr in tables["project"]: - _wk = _pr.get(_wkcol) - if isinstance(_wk, str) and _wk.startswith(_WIN_HOME_PREFIX_SL): - _pr[_wkcol] = _WSL_HOME_PREFIX + _wk[len(_WIN_HOME_PREFIX_SL):] - elif isinstance(_wk, str) and _wk.startswith("C:\\Users\\ypshidifu"): - _pr[_wkcol] = _WSL_HOME_PREFIX + _wk.replace("C:\\Users\\ypshidifu", "") + _pr["worktree"] = _conv_win_path(_pr.get("worktree")) + for _t in ("session", "session_v2"): + for _r in tables.get(_t) or []: + if "directory" in _r: + _r["directory"] = _conv_win_path(_r.get("directory")) try: tables["session_v2"] = [ dict(r)