mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 02:29:33 +01:00
fix(custom-model): keep the in-use picker honest about down endpoints and exited panes
Review round on PR #757. The route turns EVERY upstream failure into isLlamaSwap: false, so the old line silently promised an unreachable endpoint was merely mute, and the live-session check missed a null pid (the PTY exited, the same test keep-warm applies). - Require pid !== null in _getCustomModelInUseBySession, pinned by a 'process exited' case in the marks-nothing table - Reword #customModelPickUnknown to claim only that nothing was reported, true for a down endpoint too; drop the 'stays quiet for a failed probe' promise from changeset, docs and comments - architecture-invariants: add the In-use tier, both pin fences (customModel not displayModel; stopped/null-pid/paneExit never count) and the unknown-line rule - Mirror the wording through i18n (key + zh-CN), index.html fixture, styles.css comment, and the run-menu tests
This commit is contained in:
1 parent
4623ee0d12
commit
4aeab0d9ce
8 files changed
+62
-40
No files matched your search
@@ -629,8 +629,8 @@
|
||||
'Currently loaded': '当前已加载',
|
||||
'In use by a session': '会话正在使用',
|
||||
'Last used': '上次使用',
|
||||
'Nothing is marked: this endpoint cannot report which model it has loaded, and no running session uses one. Pick the model to launch, or start a session on this endpoint first.':
|
||||
'未标记任何模型:此端点无法报告它当前加载了哪个模型,并且没有运行中的会话正在使用它。请选择要启动的模型,或先在该端点上启动一个会话。',
|
||||
'Nothing is marked: this endpoint did not report which model it has loaded, and none of your running sessions uses one. Pick the model to launch.':
|
||||
'未标记任何模型:此端点没有报告它已加载了哪个模型,你运行中的会话也没有在使用它。请选择要启动的模型。',
|
||||
'That endpoint no longer exists': '该端点已不存在',
|
||||
'No models discovered for this endpoint yet': '此端点尚未发现任何模型',
|
||||
// Model picker search box (index.html placeholder/aria-label and the no-matches line)
|
||||
|
||||
@@ -1045,7 +1045,7 @@
|
||||
answered that it is not llama-swap (see _openCustomModelPickModal): it says out
|
||||
loud WHY nothing is marked, in the user's language, rather than leaving an
|
||||
alphabetical wall that looks like the question was ignored. -->
|
||||
<p class="form-hint custom-model-pick-unknown" id="customModelPickUnknown" role="status" hidden>Nothing is marked: this endpoint cannot report which model it has loaded, and no running session uses one. Pick the model to launch, or start a session on this endpoint first.</p>
|
||||
<p class="form-hint custom-model-pick-unknown" id="customModelPickUnknown" role="status" hidden>Nothing is marked: this endpoint did not report which model it has loaded, and none of your running sessions uses one. Pick the model to launch.</p>
|
||||
<div id="customModelPickList" class="run-mode-custom-models"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1011,10 +1011,13 @@ Object.assign(CodemanApp.prototype, {
|
||||
* `_watchLlamaSwapLoading`'s own check.
|
||||
*
|
||||
* Resolves the raw route payload rather than a model id so the caller can tell the
|
||||
* three answers apart: llama-swap naming a model, an endpoint that positively cannot
|
||||
* say (safe to explain in the UI), and no answer at all (timeout/unreachable, which
|
||||
* resolves `null` and must NEVER be described as "cannot report", since the endpoint
|
||||
* may well have been asleep rather than mute). Never throws: a failed probe should
|
||||
* three answers apart: llama-swap naming a model; `isLlamaSwap: false`, which is what
|
||||
* the route answers for EVERY failure it catches (a server without a `/running`
|
||||
* route, a refused or unresolvable endpoint, a 401 from a wrong key) — safe to
|
||||
* explain in the UI as long as the wording also fits an endpoint that is down; and
|
||||
* `null`, only when Codeman's own request to the route failed or the client-side
|
||||
* bound below won the race, which stays silent, since the endpoint may merely have
|
||||
* been asleep. Never throws: a failed probe should
|
||||
* just skip promotion, not break the picker.
|
||||
*
|
||||
* ⚠️ Client-side bounded to ~800ms via Promise.race, on top of (never instead of) the
|
||||
@@ -1061,10 +1064,12 @@ Object.assign(CodemanApp.prototype, {
|
||||
* is display text scraped off a CLI's footer or statusline for a session header (pane
|
||||
* derived, `source: 'screen'`), and promoting a row because a terminal printed a
|
||||
* similar string is worse than showing nothing.
|
||||
* ⚠️ Requires a live pane: `status: 'stopped'` or a recorded `paneExit` means nothing
|
||||
* is on the endpoint any more, and a dead session's stale pin is exactly what an "in
|
||||
* use" claim must not resurrect. `session:updated` keeps it current, so a session
|
||||
* cleared back to the CLI's own backend or moved to another endpoint stops counting.
|
||||
* ⚠️ Requires a live pane: `status: 'stopped'`, a null `pid` (the PTY exited; the
|
||||
* same live-pane test keep-warm applies, `src/prompt-cache-keepwarm.ts`) or a recorded
|
||||
* `paneExit` means nothing is on the endpoint any more, and a dead session's stale pin
|
||||
* is exactly what an "in use" claim must not resurrect. `session:updated` keeps it
|
||||
* current, so a session cleared back to the CLI's own backend or moved to another
|
||||
* endpoint stops counting.
|
||||
* ⚠️ A since-deleted endpoint simply matches no host, so no extra liveness check is
|
||||
* needed here.
|
||||
*/
|
||||
@@ -1073,7 +1078,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
if (models.length === 0) return null;
|
||||
let newest = null;
|
||||
for (const [, session] of this.sessions || []) {
|
||||
if (!session || session.status === 'stopped' || session.paneExit) continue;
|
||||
if (!session || session.status === 'stopped' || session.pid === null || session.paneExit) continue;
|
||||
const pinned = session.customModel;
|
||||
if (!pinned || pinned.endpointId !== host.id) continue;
|
||||
if (!models.includes(pinned.modelId)) continue; // undiscovered since: no row to promote
|
||||
@@ -1129,10 +1134,13 @@ Object.assign(CodemanApp.prototype, {
|
||||
`${cliLabel} → ${host.label} — ${(host.models || []).length} models discovered.`;
|
||||
// A plain static line (its markup lives in index.html), shown when NOTHING is known
|
||||
// about any row: 40 alphabetical rows with no mark on any of them otherwise read as
|
||||
// the app ignoring the question. It only asserts what the probe actually answered:
|
||||
// `isLlamaSwap: false` is a real "I cannot tell you", where a probe that timed out or
|
||||
// failed (`runningStatus === null`) is not, the box may merely be asleep, so an
|
||||
// unreachable endpoint stays silent instead of explaining something it does not know.
|
||||
// the app ignoring the question. `isLlamaSwap: false` is what the route answers for
|
||||
// every failure it catches: a server that cannot report AND a down or refused one
|
||||
// alike (`getLlamaSwapStatus`, custom-model-routes.ts), so the line's wording
|
||||
// promises only that nothing was reported, which stays true either way. A probe
|
||||
// that never got an answer at all (`runningStatus === null`: Codeman's own request
|
||||
// failed or the 800ms bound won) keeps the line hidden, the box may merely be
|
||||
// asleep.
|
||||
// A remembered id that has since vanished from host.models is no promotion: count
|
||||
// only a promoted id that is actually a row, or a stale "last used" would both skip
|
||||
// tagging any row and hide this line, leaving 40 unmarked rows with no explanation.
|
||||
|
||||
@@ -7824,9 +7824,9 @@ html[data-skin="og"] .welcome-primary:hover {
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
/* "This endpoint cannot report which model it has loaded": the same `.form-hint`
|
||||
`display: block` beats `[hidden]` trap the two rules below fix for the no-matches
|
||||
line and the filtered rows, so the attribute needs the same re-assertion. */
|
||||
/* "Nothing is marked: this endpoint did not report which model it has loaded": the same
|
||||
`.form-hint` `display: block` beats `[hidden]` trap the two rules below fix for the
|
||||
no-matches line and the filtered rows, so the attribute needs the same re-assertion. */
|
||||
#customModelPickModal .custom-model-pick-unknown {
|
||||
padding-bottom: 0.15rem;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user