修 oc-model-sync:NOT NULL 动态补列 + 推 4 个插件状态文件

WSL import 因 kv.time_created NOT NULL 回滚,catalog/credential 全没写入:
- kv/credential 改按 WSL 实际表列 PRAGMA 动态补全默认值(time_* 补 now,active 补 0,
  id 缺时生成稳定 win_xxx,label NOT NULL 兜底),杜绝 NOT NULL 约束失败
- 新增 4 个 model-manager 状态文件进同步(cfg/removed/disabled/stoplist.bak),
  让 WSL 侧感知 Win 已停用 xiaomi、已删 Agnes;pristine 不推(WSL 自补)
- 同步 runtime -> tools/ 真源
This commit is contained in:
ypshidifu
2026-10-20 19:17:22 +08:00
parent f7688bf27e
commit 5cd94dc4e1
+44 -4
View File
@@ -66,6 +66,18 @@ PLUGINS = [
"/root/.config/opencode/plugins/model-manager.ts"),
(os.path.join(HOME, ".config", "opencode", "mcpcfg.txt"),
"/root/.config/opencode/mcpcfg.txt"),
# ── 2026-10-20 补:插件「状态文件」也要推(修「格式化 xiaomi 后 WSL 仍可见」)──
# WSL 侧的 model-manager 读的是 WSL 自己的 cfg/removed/disabled 清单,若不同步,
# Win 上「停用/删除」的厂商在 WSL 无从感知 → WSL 仍按旧 catalog 显示 xiaomi/Agnes。
# pristine 不推:6.5MB 巨大,且 WSL 侧若缺时会自动按当前 catalog 重新拍一份,无需强同步。
(os.path.join(HOME, ".config", "opencode", "model-manager.cfg.json"),
"/root/.config/opencode/model-manager.cfg.json"),
(os.path.join(HOME, ".config", "opencode", "model-manager.removed.json"),
"/root/.config/opencode/model-manager.removed.json"),
(os.path.join(HOME, ".config", "opencode", "model-manager.disabled.json"),
"/root/.config/opencode/model-manager.disabled.json"),
(os.path.join(HOME, ".config", "opencode", "model-manager.stoplist.bak.json"),
"/root/.config/opencode/model-manager.stoplist.bak.json"),
]
@@ -197,9 +209,21 @@ try:
time_created INTEGER, time_updated INTEGER)""")
if catalog_raw:
cur.execute("DELETE FROM kv WHERE key='models-dev:catalog'")
cur.execute("INSERT INTO kv (key, value, time_updated) VALUES (?,?,?)",
("models-dev:catalog", catalog_raw, int(time.time())))
res["steps"].append("catalog-cleared+overwritten")
# ★ 按 WSL kv 表实际列动态插入(补 time_created 等, 避免 NOT NULL 约束失败)
kv_cols = [r[1] for r in cur.execute("PRAGMA table_info(kv)")]
now = int(time.time())
row = {"key": "models-dev:catalog", "value": catalog_raw,
"time_created": now, "time_updated": now}
cols = [k for k in row.keys() if k in kv_cols]
# WSL kv 有但上面没给的列 -> 补 NULL/0
for k in kv_cols:
if k not in row:
row[k] = now if k.startswith("time_") else None
cols.append(k)
cur.execute(
"INSERT INTO kv (%s) VALUES (%s)" % (",".join(cols), ",".join("?" * len(cols))),
[row[k] for k in cols])
res["steps"].append("catalog-cleared+overwritten(cols=%s)" % cols)
else:
res["steps"].append("catalog-missing-skip")
# credential: 并集语义 —— Win 的 credential 整份灌入, 但 WSL 独有的 integration_id
@@ -220,8 +244,24 @@ try:
else:
wsl_only_integs.append(integ) # WSL 独有, 保留
for integ, c in win_by_integ.items():
row = c
row = dict(c)
cols = [k for k in row.keys() if k in cred_cols]
# WSL credential 有但 Win 没给的列 -> 按类型补默认值, 避免 NOT NULL 约束失败
for k in cred_cols:
if k not in row:
if k.startswith("time_"):
row[k] = int(time.time())
elif k == "active":
row[k] = 0
elif k == "id":
# 无 id 或 id 缺失时生成稳定 id(避免 PRIMARY KEY 冲突与 NOT NULL)
row[k] = "win_" + (integ or "unknown").replace("/", "_")
else:
row[k] = None
cols.append(k)
# label 是 NOT NULL:Win 可能给空串/None,确保非 None
if row.get("label") is None:
row["label"] = row.get("id") or row.get("integration_id") or "win"
if not cols:
continue
# 防重复: 若 WSL 里已存在同名(可能上面没删净), 先清