fix(runtime): discover Python interpreters without fixed minor lists - #4482
huangruiteng merged 4 commits into
Conversation
|
Coordination readback: the current author head is The maintenance pass observed concurrent author updates and preserved them. A separate local candidate combining the earlier The previous CI failures were in change-window and chat-context tests; both focused cases pass on a clean |
Signed-off-by: song <liusongstep@gmail.com>
Signed-off-by: song <liusongstep@gmail.com>
Signed-off-by: song <liusongstep@gmail.com>
db58562 to
2164327
Compare
…pment-entrypoints Signed-off-by: song <liusongstep@gmail.com>
54044df to
5545d17
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
动机
解释器发现以前依赖人工维护的 minor 版本清单:POSIX 启动器里写着 python3.13/3.12/3.11,DSH 插件里冻结了 PYTHON_CANDIDATES = [python3, python3.14, 3.13, 3.12, 3.11]。这带来一种安静但会周期性复发的失败:当某台机器上可用的受支持解释器不是这几个名字(例如只有 python3.15,或者名字被改过),启动器会一路走到最后的 python3,而那个可能是 3.10 甚至更旧,于是表现为"环境明明有 Python 却起不来"。每加一个新 Python 版本都得同时改两处清单,属于典型的会把维护成本滚大的知识复制。
改动思路
作者把"名字清单"换成"发现 + 探测":两个 surface 各自枚举 python3.<minor> 形式的名字,但对每个候选都保留原有的兼容性探测(脚本里是 python_version_ok,插件侧是版本 + pip 探测),并且显式配置的优先级一点没动——LOOPX_PYTHON、.loopx-python 记录、PYTHON_BIN、仓库 .venv 仍然排在发现之前。脚本侧按 minor 数值降序排列(sort -t. -k2,2nr,避免 python3.14 在字典序上输给 python3.9),并用 case 过滤掉非纯数字后缀,python3.12-config、python3.12.1、同名目录都不会被当成解释器。插件侧同样过滤非目录项后按 minor 降序返回,但保留 python3 在最前。另外,之前集成测试里那份"另一份版本清单"被删除,改成直接复用插件自己的发现 owner,这是这次改动里最值得肯定的去重。
具体改动
scripts/loopx-python.sh:新增versioned_python_names(枚举 → 过滤 → 数值降序 → 去重),select_loopx_python的顺序变成"显式配置/记录/.venv → PATH 上的版本化名字 →python3→~/.local/bin、Homebrew、/usr/local/bin兜底目录",每个候选都要过python_version_ok。packages/dsh-loopx-plugin/src/managed-runtime.ts:删除PYTHON_CANDIDATES,pluginPythonCandidates改为"显式PYTHON_BIN优先;否则python3打头 + 按 minor 降序的发现结果",读取 PATH 不可用的目录直接跳过。- 测试:
tests/test_python_discovery.py(新增 7 项)、packages/dsh-loopx-plugin/tests/python-discovery.spec.ts(2 项),并把admission-closeout.integration.spec.ts改为复用插件发现 owner。 - 文档:
AGENTS.md新增 Source-Checkout Python Entry Points(建议uv run --extra test、检查sys.executable与loopx.__file__),以及 dashboard/personal-workspace 文档、scripts/dashboard-dev.sh与安装脚本 help 文本的相应措辞。
关键代码讲解
scripts/loopx-python.sh:24 versioned_python_names:核心过滤在case "${minor}" in ''|*[!0-9]*) continue,配合[ -x ] && [ ! -d ],确保只有可执行的纯python3.<数字>参与排序;sort -t. -k2,2nr | uniq完成数值降序与跨目录去重。scripts/loopx-python.sh:74起的select_loopx_python:显式来源之后先扫 PATH 目录(把 PATH 按:拆开、空段按.处理,与 PATH 语义一致),再退回python3,最后扫~/.local/bin、/opt/homebrew/bin、/usr/local/bin——旧代码里那些路径仍然在,只是从"硬编码名字"变成"发现名字"。packages/dsh-loopx-plugin/src/managed-runtime.ts:28 pluginPythonCandidates:/^python3\.(\d+)(?:\.exe)?$/i匹配、!entry.isDirectory()过滤、minorB - minorA || nameA.localeCompare(nameB)排序,返回['python3', ...发现结果];读取失败静默跳过,实际有效性仍由调用方的版本/pip 探测决定。- 去重证据:
admission-closeout.integration.spec.ts不再内嵌版本列表,而是调用插件的发现 owner;head 上grep只在新的单测期望里还能看到具体 minor。
对主干的风险
我把能跑的都跑了:pytest -q tests/test_python_discovery.py 7 项通过;插件侧 vitest run tests/python-discovery.spec.ts 2 项通过;admission-closeout.integration.spec.ts + init-command.spec.ts 33 项通过(46s)。行为面上,显式配置的优先级、3.11 下限、以及"每个候选必须探测"这三条约束都没被削弱,发现本身是只读的一次 glob/readdir,没有新增状态、协议字段或 CLI 选项,回滚也只是恢复两份清单。
一条非阻塞 P3:两个 surface 的发现顺序不一致。启动器现在是"先版本化名字、后 python3",插件是"先 python3、后版本化名字",PR 描述里也是分开说明的。在 python3 落在较旧(但受支持)minor 的机器上,两个 surface 可能选到不同解释器——都由 3.11 探测兜底,所以不会选出不可用环境,但一旦某个运行期问题只在其中一个解释器上复现,这个差异会让复现路径变模糊。建议在一处文档里写清两个 surface 各自的有意顺序,并在两个套件里补一条共同的顺序期望,而不是各自只断言自己那一侧。另外,我没有在"只暴露非常见受支持 minor 名"的真实机器上做过安装,这一项保持 unverified;集成与单测覆盖了代码路径。
我的整体评价
结论是 APPROVE。这是一次典型的"删掉知识复制而不是延长它"的改动:两处人工 minor 清单换成发现 + 原有探测,且在改动过程中把集成测试里的第三份清单也去掉了,净效果是以后新增 Python 版本不再需要同时改多处。优先级、下限与探测这些真正决定正确性的约束都原样保留,测试覆盖也随改动一起补齐并全部通过。唯一值得跟进的是两个 surface 的排序策略不同——它是有意的(插件要保持 python3 隐式优先以不改变既有安装行为),但目前只散落在 PR 描述与各自实现里,建议集中说明以免将来被当成 bug 修掉。没有发现阻塞项。
English verdict: APPROVE — exact head 5545d1747aa07e1e31b9481a0bd16745600c620a of #4482. The change replaces two hand-maintained minor-version lists with name discovery plus the existing probes, and it removes a third copy of the same knowledge from admission-closeout.integration.spec.ts by reusing the plugin's discovery owner. Explicit precedence is untouched on both surfaces (LOOPX_PYTHON, the .loopx-python record, the repository .venv, and PYTHON_BIN all stay ahead of discovery), the 3.11 floor and per-candidate probing are preserved, and the shell filter rejects python3.12-config/python3.12.1/directories while ordering by numeric minor so python3.14 is not lexically ranked behind python3.9. Validation at this head: tests/test_python_discovery.py 7 passed, packages/dsh-loopx-plugin/tests/python-discovery.spec.ts 2 passed, and admission-closeout.integration.spec.ts plus init-command.spec.ts 33 passed in 46s. One non-blocking P3: the launcher prefers versioned names before python3 while the plugin keeps python3 first, so the two surfaces can pick different (both supported) interpreters on the same machine — document that intended order in one place and add a shared ordering expectation to both suites. Unverified: no install was executed on a machine that exposes only an unusual supported minor name, since this environment has the usual names; the unit and integration suites cover the code paths. No protocol, state, quota or authority surface changes.
Summary
Installed Python discovery previously depended on hand-maintained minor-version lists. A supported interpreter exposed only under a name outside those lists could be missed. The POSIX launcher and DSH plugin now discover installed
python3.<minor>names and retain their existing compatibility probes and explicit-configuration precedence.Changes
LOOPX_PYTHON, the installer record, and the project environment ahead of discovery; discover versioned names on PATH and in existing user/Homebrew fallback directories, in descending numeric order.PYTHON_BINauthoritative and the implicitpython3first; discover the remaining names on the supplied PATH. Installation still validates Python >=3.11 and pip; reopening still validates the managed LoopX CLI.The discovery behavior now admits compatible installed names absent from the old list. POSIX selection and DSH installation still reject invalid explicit interpreters. Managed-runtime readback keeps its existing CLI fallback behavior. No Python downloads, automatic installation side effects, global Python mutation, or uv runtime dependency are added. CI versions, supported-version declarations, and concrete compatibility fixtures remain intentional.
Validation
edcddc7aa, the expanded Python set including Chat baseline tests passes 126 tests.The production entrypoints are the existing installation/development launcher and DSH managed-runtime resolver. No frontend view or settings field changes are needed; the affected command help and both runtime documents are updated. The bounded refactor removes repeated version lists while keeping each distribution's existing selection precedence. No model benchmark or release publication was performed.
Base-sync validation repair
The newly merged
test_a_channel_without_a_session_reads_as_unboundassumed the optional DSH runtime was installed. It failed both here and on unmodified mainedcddc7aain the same environment (dsh_runtime_unavailable). A separate test-only commit pins the existing runtime-availability probe to the test's declared ready-endpoint premise; the original assertions and production behavior are unchanged. This makes the unbound-session assertion independent of locally installed optional hosts.中文摘要
此前的开发命令调整没有覆盖运行时写死的小版本候选列表。本次将 POSIX 启动器和 DSH 插件改为发现已安装的版本化解释器,再执行原有兼容性校验;集成测试复用生产发现逻辑。显式配置优先级、最低 Python 要求及插件安装时的 pip 校验保留,不增加 uv 运行时依赖。60 项定向 Python 测试、187 项插件测试、类型检查、构建及真实打包入口探针通过。同步主干后扩展验证为 126 项 Python 测试通过;其中一个主干测试的环境依赖已用独立测试提交修复,未改生产逻辑。