session-mechanism:修 preferred_model 取数判据——改用人开一次性会话判断会取错(P0-80 二次),现复用 _scan_mains 的主会话候选判据(本区+非worker+非退役角色+按最近活动)

This commit is contained in:
admin committed 2026-10-12 02:35:06 +08:00
1 parent d81f75f173
commit cd5fcf1d30
1 file changed
+38 -19
+38 -19
View File
@@ -3758,11 +3758,22 @@ def local_user_id() -> str:
return "" return ""
# 🔴🔴 **机制另建会话时,模型该跟谁一致**(2026-10-05 用户点破 P0-80) # 🔴🔴 **机制另建会话时,模型该跟谁一致**(2026-10-05 用户点破 P0-80;2026-10-12 修严判据)
# 症状:常驻新建的 `[执行]`/`[检查]` 会话全是模型 `space-bunny`,而**主会话是 `deepseek-v4.1-flash`** # 症状:常驻新建的 `[执行]`/`[检查]` 会话全是模型 `space-bunny`,而**主会话是 `deepseek-v4.1-flash`**
# ⇒ 同一件活在两种模型上跑(能力档、思考开关全不一致)。 # ⇒ 同一件活在两种模型上跑(能力档、思考开关全不一致)。
# 真因:`create_check_schedule()` 的 INSERT 里**字面写死** `"space-bunny"`(把一次实测当成了永恒)。 # 真因(10-05 那次):`create_check_schedule()` 的 INSERT 里**字面写死** `"space-bunny"`。
# ✅ 正解:**跟本区最近一条「人开的」会话取同一档** —— 模型 + 思考档一起继承。 # 🔴🔴 真因(2026-10-12 第二次实测):改成"跟本区最近一条**人开的**会话"后**仍然取错** ——
# 取到的是 `hy4-preview-f`,而真主会话是 `deepseek-v4.1-flash`。
# 病根=**「人开的」(`is_background_automation <> 1`)不等于「主会话」**:
# 本区「人开的」有两条 —— `c9ba8796`「部署 TRENDRADAR 到 Docker」(10-09,`hy4-preview-f`)
# 与 `184c4986`「规划整合营销平台」(10-08,`deepseek-v4.1-flash` = 真主会话)。
# 按 `created_at desc` 取最近 ⇒ 取到那条**人开的一次性会话** ⇒ 照抄了它的模型。
# ⚠️ 而 `is_background_automation` 这个判据机制**自己早就注明不可用**
# (见 `_scan_mains()` 文档:接续会话本身就是自动化起的,连主会话都可能是 `bg=1`)。
# ✅ 正解(10-12 改):**复用机制自己的「主会话候选」判据**(与 `_scan_mains()` 同源)——
# 本区 + `parse_session_name(标题).role` 不是 `worker` + 不是退役角色标题,
# 按 **`last_activity_at desc`** 取第一条有 model 的。
# ⇒ 判据只有一份(`_scan_mains()` 怎么认主会话,这里就怎么认),⛔ 不再另立一套。
# ⚠️ 两条建会话的路必须**同源**:常驻直连 SQLite(本函数所服务的路径)/会话侧走 `automation_update`。 # ⚠️ 两条建会话的路必须**同源**:常驻直连 SQLite(本函数所服务的路径)/会话侧走 `automation_update`。
# ⛔ 取不到时**必须打日志**(⛔ 不许静默回落 —— 否则又是"看着改了其实没生效")。 # ⛔ 取不到时**必须打日志**(⛔ 不许静默回落 —— 否则又是"看着改了其实没生效")。
FALLBACK_MODEL = "space-bunny" # 兜底常量:仅当**取不到**主会话模型时才用 FALLBACK_MODEL = "space-bunny" # 兜底常量:仅当**取不到**主会话模型时才用
@@ -3772,33 +3783,41 @@ FALLBACK_THINKING = 0
def preferred_model(cwd: str = "") -> tuple: def preferred_model(cwd: str = "") -> tuple:
"""**本区主会话用的(模型, 是否开思考)** —— 机制另建会话时照抄这个。 """**本区主会话用的(模型, 是否开思考)** —— 机制另建会话时照抄这个。
取数:`sessions` 里**人开的**(`is_background_automation <> 1`)、**本区**、**最近一条**。 取数:**复用「主会话候选」判据**(与 `_scan_mains()` 同源)——
⚠️ 排除 `bg=1` 是必须的 —— 否则会取到「机制自己上次建的那条」⇒ **自我强化**, 本区 + 标题解析出的角色不是 `worker` + 不是退役角色标题,按 `last_activity_at desc` 取第一条有 model 的。
永远锁死在历史值上(同 P0-77 那类"错值自我强化")。 ⚠️ **⛔ 不按 `is_background_automation` 筛**(10-12 实测栽过):**「人开的」≠「主会话」** ——
人开的一次性会话会把真主会话挤掉;而接续会话本来就是自动化起的,按 bg 排会连真主会话一起排掉。
⚠️ **⛔ 不按 `created_at` 排**:主会话可能创建得最早却一直在用 ⇒ 按创建时间会取到别的会话。
⚠️ `thought_level`:`disabled`/空 ⇒ 0,其余(`high`/`low`/…) ⇒ 1。 ⚠️ `thought_level`:`disabled`/空 ⇒ 0,其余(`high`/`low`/…) ⇒ 1。
""" """
ws = (str(cwd or WS or os.getcwd())).replace("\\", "/").rstrip("/") ws = (str(cwd or WS or os.getcwd())).replace("\\", "/").rstrip("/")
try: try:
c = _ro_conn() c = _ro_conn()
r = c.execute( rows = c.execute(
"select model, thought_level from sessions " "select id, cwd, coalesce(custom_title, title, ''), model, thought_level from sessions "
"where (is_background_automation is null or is_background_automation <> 1) " "where deleted_at is null order by last_activity_at desc limit 50").fetchall()
" and model is not null and model <> '' "
" and replace(cwd,'\\\\','/') like ? "
"order by created_at desc limit 1", ("%" + ws + "%",)).fetchone()
c.close() c.close()
except Exception as e: except Exception as e:
log("⚠️ preferred_model 取数失败(回落 %s):%s" % (FALLBACK_MODEL, e)) log("⚠️ preferred_model 取数失败(回落 %s):%s" % (FALLBACK_MODEL, e))
return FALLBACK_MODEL, FALLBACK_THINKING return FALLBACK_MODEL, FALLBACK_THINKING
if not r or not (r[0] or "").strip(): for _sid, _cwd, _title, _model, _thought in (rows or []):
log("⚠️ preferred_model 取不到本区主会话模型(cwd=%s)⇒ 回落 %s" _t = str(_title or "")
% (ws, FALLBACK_MODEL)) _role = str(parse_session_name(_t).get("role") or "")
return FALLBACK_MODEL, FALLBACK_THINKING # 🔴 判据与 `_scan_mains()` 逐字同源:本区 + 非 worker + 非退役角色标题
m = str(r[0]).strip() if not _same_ws(str(_cwd or "")):
tl = str(r[1] or "").strip().lower() continue
if _role in ("worker",) or is_retired_role_title(_t):
continue
m = str(_model or "").strip()
if not m:
continue # 候选里取第一条**有模型**的
tl = str(_thought or "").strip().lower()
th = 0 if tl in ("", "disabled", "off", "none", "0") else 1 th = 0 if tl in ("", "disabled", "off", "none", "0") else 1
log("preferred_model:本区主会话 model=%s thought=%s ⇒ 机制照抄这个(P0-80)" % (m, tl or "-")) log("preferred_model:本区主会话 %s「%s」model=%s thought=%s ⇒ 机制照抄这个(P0-80)"
% (str(_sid)[:8], _t[:24], m, tl or "-"))
return m, th return m, th
log("⚠️ preferred_model 取不到本区主会话模型(cwd=%s)⇒ 回落 %s" % (ws, FALLBACK_MODEL))
return FALLBACK_MODEL, FALLBACK_THINKING
def active_schedule_exists(name: str) -> bool: def active_schedule_exists(name: str) -> bool: