codex-model-change 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cx.py +63 -1
- package/package.json +1 -1
package/cx.py
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"""
|
|
14
14
|
import json, os, re, glob, sqlite3, subprocess, sys, shutil, time, urllib.request, urllib.error
|
|
15
15
|
|
|
16
|
-
CX_VERSION = "1.0.
|
|
16
|
+
CX_VERSION = "1.0.5"
|
|
17
17
|
|
|
18
18
|
CODEX_HOME = os.environ.get("CODEX_HOME", os.path.expanduser("~/.codex"))
|
|
19
19
|
CONFIG = os.path.join(CODEX_HOME, "config.toml")
|
|
@@ -153,6 +153,62 @@ def clean_ocx_injections(text):
|
|
|
153
153
|
out.append(ln)
|
|
154
154
|
return "\n".join(out)
|
|
155
155
|
|
|
156
|
+
|
|
157
|
+
# ---------- App 投影缓存对齐 ----------
|
|
158
|
+
# 背景(踩过的坑,务必保留):
|
|
159
|
+
# rollout 每条记录带顶层 "ordinal" 字段,且 App 要求它从 0 起、逐条 +1 连续。
|
|
160
|
+
# cx fix-all 会两处改动 rollout:
|
|
161
|
+
# 1) rewrite_rollout 重新序列化 turn_context/session_meta → 整文件字节偏移漂移;
|
|
162
|
+
# 2) sanitize_rollout 删除 reasoning 行 → ordinal 出现缺口。
|
|
163
|
+
# 而 App 的投影(thread_history_1.sqlite)按 ordinal + 字节偏移增量推进,一旦遇到缺口
|
|
164
|
+
# 就永久卡死("expected ordinal N, got N+1"),新内容再也进不了投影缓存 ——
|
|
165
|
+
# 表现就是"跑完 fix-all 后重开 App,今天聊的内容消失了"(live 会话内存里其实还在)。
|
|
166
|
+
# 因此 fix-all 必须:先重编号 ordinal 消除缺口,再清掉该会话的投影缓存,
|
|
167
|
+
# 让 App 下次打开时从(已连续的)rollout 完整重建。重建是唯一 100% 安全的做法。
|
|
168
|
+
import re as _re
|
|
169
|
+
_ORD_PAT = _re.compile(rb'"ordinal":\s*(\d+)')
|
|
170
|
+
_ORD_SUB = _re.compile(rb'"ordinal":\s*\d+')
|
|
171
|
+
|
|
172
|
+
def read_ordinals(path):
|
|
173
|
+
"""按行序读出每行顶层 ordinal 值(缺失为 None)"""
|
|
174
|
+
out = []
|
|
175
|
+
for ln in open(path, "rb"):
|
|
176
|
+
m = _ORD_PAT.search(ln)
|
|
177
|
+
out.append(int(m.group(1)) if m else None)
|
|
178
|
+
return out
|
|
179
|
+
|
|
180
|
+
def renumber_ordinals(path):
|
|
181
|
+
"""把每行 ordinal 重写为行号,消除删行造成的缺口。返回改写行数。
|
|
182
|
+
正常 rollout 每行都有 ordinal 且原本 ordinal==行号,故以行号为准可完美复原连续性。"""
|
|
183
|
+
lines = open(path, "rb").readlines()
|
|
184
|
+
changed = 0
|
|
185
|
+
for i, ln in enumerate(lines):
|
|
186
|
+
new = _ORD_SUB.sub(b'"ordinal":' + str(i).encode(), ln, count=1)
|
|
187
|
+
if new != ln:
|
|
188
|
+
lines[i] = new; changed += 1
|
|
189
|
+
if changed:
|
|
190
|
+
open(path, "wb").writelines(lines)
|
|
191
|
+
return changed
|
|
192
|
+
|
|
193
|
+
def reset_app_projection(thread_id):
|
|
194
|
+
"""清掉 App 对某会话的投影缓存,强制其下次打开时从 rollout 重建。
|
|
195
|
+
rollout 被改写/删行后这是唯一安全做法:避免 ordinal 缺口与字节偏移错位残留。
|
|
196
|
+
(thread_history_projection_state 上有 DELETE 触发器,会连带清 thread_realtime_items)"""
|
|
197
|
+
db_path = os.path.join(CODEX_HOME, "thread_history_1.sqlite")
|
|
198
|
+
if not (thread_id and os.path.exists(db_path)):
|
|
199
|
+
return False
|
|
200
|
+
db = sqlite3.connect(db_path)
|
|
201
|
+
try:
|
|
202
|
+
has = lambda t: db.execute(
|
|
203
|
+
"SELECT 1 FROM sqlite_master WHERE type='table' AND name=?", (t,)).fetchone()
|
|
204
|
+
for t in ("thread_items", "thread_turns", "thread_history_projection_state"):
|
|
205
|
+
if has(t):
|
|
206
|
+
db.execute(f"DELETE FROM {t} WHERE thread_id=?", (thread_id,))
|
|
207
|
+
db.commit()
|
|
208
|
+
return True
|
|
209
|
+
finally:
|
|
210
|
+
db.close()
|
|
211
|
+
|
|
156
212
|
# ---------- 命令 ----------
|
|
157
213
|
def cmd_use(which):
|
|
158
214
|
if which not in ("deepseek", "gpt"): err("用法: cx use deepseek|gpt")
|
|
@@ -348,8 +404,14 @@ def cmd_fix_all():
|
|
|
348
404
|
if rp and os.path.exists(rp):
|
|
349
405
|
bakj = rp + f".bak.cx-fixall-{ts}"
|
|
350
406
|
if not os.path.exists(bakj): shutil.copy2(rp, bakj)
|
|
407
|
+
old_ords = read_ordinals(rp) # 改写前快照(仅用于诊断是否有缺口)
|
|
351
408
|
if needs_model: rewrite_rollout(rp, model, provider)
|
|
352
409
|
if provider == "openai": sanitize_rollout(rp)
|
|
410
|
+
# 关键:删行会产生 ordinal 缺口 + 重排会移动字节偏移;必须重编号消除缺口,
|
|
411
|
+
# 并清投影缓存让 App 从 rollout 重建,否则重开 App 后该会话内容会"消失"
|
|
412
|
+
fixed = renumber_ordinals(rp)
|
|
413
|
+
reset_app_projection(tid)
|
|
414
|
+
if fixed: print(f" · {tid[:8]} 重编号 {fixed} 行并重置 App 投影")
|
|
353
415
|
if needs_model:
|
|
354
416
|
db.execute("UPDATE threads SET model=?, model_provider=? WHERE id=?", (model, provider, tid))
|
|
355
417
|
n += 1
|
package/package.json
CHANGED