mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-30 08:32:07 -04:00
fix(cookbook): only block model launch on real port collisions (#4760)
* Fix #4507: only block model launch on real port collisions Quick-run hardcoded port 8000 and never called _nextAvailablePort(), so every launch collided. Both pre-launch guards (serve panel + quick-run) were count-based and fired regardless of port. - quick-run now auto-assigns a free port (8080 for llama.cpp) - both guards parse the new port and only prompt on a real overlap, stopping only the colliding serve - dialog reports the actual port instead of a hardcoded 8000 * refactor(cookbook): share _taskPort for port parsing; auto-assign llama.cpp port Addresses review on #4760: - _taskPort regex now matches --port= as well as --port (space) - _nextAvailablePort and both launch guards reuse _taskPort instead of inline regex - quick-run llama.cpp no longer pins 8080, so two can run concurrently * fix(cookbook): _taskPort also parses -p; add port-parsing tests Addresses review on #4760: - _taskPort now matches -p <n> too, so it's the complete single reader (was missing the short flag that other readers already handle) - add tests/test_cookbook_port_parsing_js.py covering the port forms, shared-reader reuse, and llama.cpp auto-assign * test(cookbook): extract pure port helpers and test behavior Addresses review on #4760: the prior tests only asserted source strings. - extract portOf() and nextFreePort() into static/js/cookbookPorts.js - cookbookRunning.js imports them; _taskPort and _nextAvailablePort delegate - tests run the helpers via node and assert real behavior: all port forms (--port, --port=, -p, -p=), next-free-port skipping taken ports, and the same-port-clash / different-port-coexist outcome --------- Co-authored-by: samy <samy@odysseus.boukouro.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import uiModule from './ui.js';
|
||||
import { _diagnose, _showDiagnosis, _clearDiagnosis } from './cookbook-diagnosis.js';
|
||||
import { registerMenuDismiss } from './escMenuStack.js';
|
||||
import { computeProgressSignal } from './cookbookProgressSignal.js';
|
||||
import { portOf, nextFreePort } from './cookbookPorts.js';
|
||||
|
||||
// Human-friendly badge label for a task's internal status. Avoids surfacing
|
||||
// the word "error" in the sidebar — a server the user stopped or one that
|
||||
@@ -266,9 +267,7 @@ function _taskHostLabel(task) {
|
||||
}
|
||||
|
||||
function _taskPort(task) {
|
||||
const cmd = task?.payload?._cmd || '';
|
||||
const match = cmd.match(/--port\s+(\d+)/);
|
||||
return match ? match[1] : '';
|
||||
return portOf(task?.payload?._cmd || '');
|
||||
}
|
||||
|
||||
function _buildCrashReport(task, outputText) {
|
||||
@@ -455,16 +454,14 @@ function _nextAvailablePort() {
|
||||
const usedPorts = new Set();
|
||||
tasks.forEach(t => {
|
||||
if (t.type === 'serve' && (t.status === 'running' || t.status === 'queued')) {
|
||||
const m = t.payload?._cmd?.match(/--port\s+(\d+)/);
|
||||
if (m) usedPorts.add(parseInt(m[1]));
|
||||
const p = _taskPort(t);
|
||||
if (p) usedPorts.add(parseInt(p));
|
||||
}
|
||||
});
|
||||
presets.forEach(p => {
|
||||
if (p.port) usedPorts.add(parseInt(p.port));
|
||||
});
|
||||
let port = 8000;
|
||||
while (usedPorts.has(port)) port++;
|
||||
return String(port);
|
||||
return nextFreePort(usedPorts);
|
||||
}
|
||||
|
||||
// ── Endpoint cleanup ──
|
||||
@@ -3987,4 +3984,4 @@ export function initRunning(shared) {
|
||||
}
|
||||
|
||||
// Also export _retryDownload and _nextAvailablePort for use by other modules
|
||||
export { _retryDownload, _nextAvailablePort, _processQueue };
|
||||
export { _retryDownload, _nextAvailablePort, _processQueue, _taskPort };
|
||||
|
||||
Reference in New Issue
Block a user