labgate 0.5.42 → 0.5.43
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/bin/postinstall.js +40 -0
- package/dist/cli.js +47 -10
- package/dist/cli.js.map +1 -1
- package/dist/lib/cli-update-notice.d.ts +13 -0
- package/dist/lib/cli-update-notice.js +21 -0
- package/dist/lib/cli-update-notice.js.map +1 -0
- package/dist/lib/startup-stage-lock.js +0 -1
- package/dist/lib/startup-stage-lock.js.map +1 -1
- package/dist/lib/ui.js +36 -107
- package/dist/lib/ui.js.map +1 -1
- package/dist/lib/update-check.d.ts +33 -0
- package/dist/lib/update-check.js +203 -0
- package/dist/lib/update-check.js.map +1 -0
- package/package.json +4 -3
package/dist/lib/ui.js
CHANGED
|
@@ -63,6 +63,7 @@ const explorer_eval_js_1 = require("./explorer-eval.js");
|
|
|
63
63
|
const explorer_store_js_1 = require("./explorer-store.js");
|
|
64
64
|
const feedback_js_1 = require("./feedback.js");
|
|
65
65
|
const automation_engine_js_1 = require("./automation-engine.js");
|
|
66
|
+
const update_check_js_1 = require("./update-check.js");
|
|
66
67
|
const log = __importStar(require("./log.js"));
|
|
67
68
|
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
68
69
|
const HTML_PATH = (0, path_1.resolve)(__dirname, '..', 'lib', 'ui.html');
|
|
@@ -86,7 +87,6 @@ const PODMAN_SETUP_MAX_BUFFER = 16 * 1024 * 1024;
|
|
|
86
87
|
const EXPLORER_TSP_TEMPLATE_DIR = (0, path_1.resolve)(__dirname, '..', '..', 'templates', 'tsp-lab');
|
|
87
88
|
const EXPLORER_TSP_TEMPLATE_SOURCE_REPO = (0, path_1.join)((0, config_js_1.getExplorerRootDir)(), 'templates', 'tsp-lab-source');
|
|
88
89
|
const EXPLORER_ARTIFACT_READ_MAX_BYTES = 2 * 1024 * 1024;
|
|
89
|
-
const UI_VERSION_NPM_PACKAGE = 'labgate';
|
|
90
90
|
const UI_VERSION_CHECK_TIMEOUT_MS = 8_000;
|
|
91
91
|
const UI_VERSION_CHECK_MAX_BUFFER = 256 * 1024;
|
|
92
92
|
const UI_VERSION_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
@@ -261,29 +261,6 @@ function readPackageVersion() {
|
|
|
261
261
|
return '0.0.0';
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
|
-
function stripVersionPrefix(raw) {
|
|
265
|
-
return String(raw || '').trim().replace(/^v/i, '');
|
|
266
|
-
}
|
|
267
|
-
function parseSemverTriplet(version) {
|
|
268
|
-
const normalized = stripVersionPrefix(version).split('-', 1)[0];
|
|
269
|
-
const match = normalized.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
270
|
-
if (!match)
|
|
271
|
-
return null;
|
|
272
|
-
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
273
|
-
}
|
|
274
|
-
function compareSemverStrings(a, b) {
|
|
275
|
-
const left = parseSemverTriplet(a);
|
|
276
|
-
const right = parseSemverTriplet(b);
|
|
277
|
-
if (!left || !right)
|
|
278
|
-
return null;
|
|
279
|
-
for (let i = 0; i < 3; i += 1) {
|
|
280
|
-
if (left[i] > right[i])
|
|
281
|
-
return 1;
|
|
282
|
-
if (left[i] < right[i])
|
|
283
|
-
return -1;
|
|
284
|
-
}
|
|
285
|
-
return 0;
|
|
286
|
-
}
|
|
287
264
|
function getUiBuildId() {
|
|
288
265
|
try {
|
|
289
266
|
const st = (0, fs_1.statSync)(HTML_PATH);
|
|
@@ -293,77 +270,11 @@ function getUiBuildId() {
|
|
|
293
270
|
return `${LABGATE_UI_VERSION}:unknown`;
|
|
294
271
|
}
|
|
295
272
|
}
|
|
296
|
-
function normalizeNpmVersionValue(raw) {
|
|
297
|
-
if (typeof raw === 'string') {
|
|
298
|
-
const cleaned = stripVersionPrefix(raw).trim();
|
|
299
|
-
return cleaned || null;
|
|
300
|
-
}
|
|
301
|
-
if (Array.isArray(raw)) {
|
|
302
|
-
const versions = raw
|
|
303
|
-
.map((entry) => normalizeNpmVersionValue(entry))
|
|
304
|
-
.filter((entry) => !!entry);
|
|
305
|
-
if (versions.length === 0)
|
|
306
|
-
return null;
|
|
307
|
-
const sorted = [...versions].sort((a, b) => {
|
|
308
|
-
const cmp = compareSemverStrings(a, b);
|
|
309
|
-
if (cmp !== null)
|
|
310
|
-
return cmp;
|
|
311
|
-
return a.localeCompare(b);
|
|
312
|
-
});
|
|
313
|
-
return sorted[sorted.length - 1] || null;
|
|
314
|
-
}
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
function parseNpmVersionOutput(rawOutput) {
|
|
318
|
-
const text = String(rawOutput || '').trim();
|
|
319
|
-
if (!text)
|
|
320
|
-
return null;
|
|
321
|
-
try {
|
|
322
|
-
return normalizeNpmVersionValue(JSON.parse(text));
|
|
323
|
-
}
|
|
324
|
-
catch {
|
|
325
|
-
const cleaned = stripVersionPrefix(text.replace(/^"+|"+$/g, '').trim());
|
|
326
|
-
return cleaned || null;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
function summarizeCommandError(err) {
|
|
330
|
-
const detail = commandErrorDetail(err);
|
|
331
|
-
const firstLine = detail
|
|
332
|
-
.split('\n')
|
|
333
|
-
.map((line) => line.trim())
|
|
334
|
-
.find((line) => line.length > 0);
|
|
335
|
-
if (!firstLine)
|
|
336
|
-
return 'Could not reach npm registry.';
|
|
337
|
-
return firstLine.length > 180 ? `${firstLine.slice(0, 177)}...` : firstLine;
|
|
338
|
-
}
|
|
339
273
|
async function fetchPublishedUiVersion() {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
maxBuffer: UI_VERSION_CHECK_MAX_BUFFER,
|
|
345
|
-
});
|
|
346
|
-
const latestVersion = parseNpmVersionOutput(String(result?.stdout || ''));
|
|
347
|
-
if (!latestVersion) {
|
|
348
|
-
return {
|
|
349
|
-
latestVersion: null,
|
|
350
|
-
checkedAt,
|
|
351
|
-
error: 'npm returned an unreadable version.',
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
return {
|
|
355
|
-
latestVersion,
|
|
356
|
-
checkedAt,
|
|
357
|
-
error: null,
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
catch (err) {
|
|
361
|
-
return {
|
|
362
|
-
latestVersion: null,
|
|
363
|
-
checkedAt,
|
|
364
|
-
error: summarizeCommandError(err),
|
|
365
|
-
};
|
|
366
|
-
}
|
|
274
|
+
return (0, update_check_js_1.fetchPublishedNpmVersion)(update_check_js_1.LABGATE_NPM_PACKAGE, {
|
|
275
|
+
timeoutMs: UI_VERSION_CHECK_TIMEOUT_MS,
|
|
276
|
+
maxBuffer: UI_VERSION_CHECK_MAX_BUFFER,
|
|
277
|
+
});
|
|
367
278
|
}
|
|
368
279
|
async function getPublishedUiVersionCached(force = false) {
|
|
369
280
|
const now = Date.now();
|
|
@@ -467,13 +378,13 @@ function runUiSelfUpdate() {
|
|
|
467
378
|
status: 'running',
|
|
468
379
|
startedAt,
|
|
469
380
|
finishedAt: null,
|
|
470
|
-
message: `Installing ${
|
|
381
|
+
message: `Installing ${update_check_js_1.LABGATE_NPM_PACKAGE}@latest...`,
|
|
471
382
|
error: null,
|
|
472
383
|
latestVersion: null,
|
|
473
384
|
};
|
|
474
385
|
uiSelfUpdatePromise = (async () => {
|
|
475
386
|
try {
|
|
476
|
-
await execFileAsync('npm', ['install', '-g', `${
|
|
387
|
+
await execFileAsync('npm', ['install', '-g', `${update_check_js_1.LABGATE_NPM_PACKAGE}@latest`], {
|
|
477
388
|
timeout: UI_SELF_UPDATE_TIMEOUT_MS,
|
|
478
389
|
maxBuffer: UI_SELF_UPDATE_MAX_BUFFER,
|
|
479
390
|
});
|
|
@@ -493,7 +404,7 @@ function runUiSelfUpdate() {
|
|
|
493
404
|
startedAt,
|
|
494
405
|
finishedAt: new Date().toISOString(),
|
|
495
406
|
message: 'Update failed.',
|
|
496
|
-
error: summarizeCommandError(err),
|
|
407
|
+
error: (0, update_check_js_1.summarizeCommandError)(err),
|
|
497
408
|
latestVersion: null,
|
|
498
409
|
};
|
|
499
410
|
}
|
|
@@ -1959,6 +1870,18 @@ async function ensureWebTerminalBridge(record) {
|
|
|
1959
1870
|
bridge.stopRequested = false;
|
|
1960
1871
|
bridge.pty = ptyProcess;
|
|
1961
1872
|
webTerminalBridges.set(record.id, bridge);
|
|
1873
|
+
if (!existing && bridge.history.length === 0) {
|
|
1874
|
+
try {
|
|
1875
|
+
const { stdout } = await execFileAsync(tmuxBin, ['capture-pane', '-p', '-S', WEB_TERMINAL_STARTUP_CAPTURE_LINES, '-t', record.tmuxSession], { timeout: 2_000, maxBuffer: WEB_TERMINAL_STARTUP_READY_BUFFER_LIMIT });
|
|
1876
|
+
const snapshot = String(stdout || '');
|
|
1877
|
+
if (snapshot) {
|
|
1878
|
+
appendWebTerminalBuffer(bridge, snapshot);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
catch {
|
|
1882
|
+
// Best effort only; live bridge output continues to stream after attach.
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1962
1885
|
ptyProcess.onData((data) => {
|
|
1963
1886
|
const appended = appendWebTerminalBuffer(bridge, data);
|
|
1964
1887
|
for (const chunk of appended) {
|
|
@@ -2648,13 +2571,7 @@ async function handleGetUiVersion(reqUrl, res) {
|
|
|
2648
2571
|
const published = await getPublishedUiVersionCached(forceRefresh);
|
|
2649
2572
|
const runningVersion = LABGATE_UI_VERSION;
|
|
2650
2573
|
const latestVersion = published.latestVersion;
|
|
2651
|
-
|
|
2652
|
-
if (latestVersion) {
|
|
2653
|
-
const cmp = compareSemverStrings(latestVersion, runningVersion);
|
|
2654
|
-
updateAvailable = cmp === null
|
|
2655
|
-
? stripVersionPrefix(latestVersion) !== stripVersionPrefix(runningVersion)
|
|
2656
|
-
: cmp > 0;
|
|
2657
|
-
}
|
|
2574
|
+
const updateAvailable = (0, update_check_js_1.isVersionNewer)(latestVersion, runningVersion);
|
|
2658
2575
|
json(res, {
|
|
2659
2576
|
ok: true,
|
|
2660
2577
|
runningVersion,
|
|
@@ -2662,7 +2579,7 @@ async function handleGetUiVersion(reqUrl, res) {
|
|
|
2662
2579
|
latestVersion,
|
|
2663
2580
|
latestCheckedAt: published.checkedAt,
|
|
2664
2581
|
updateAvailable,
|
|
2665
|
-
updateCommand:
|
|
2582
|
+
updateCommand: (0, update_check_js_1.getUpdateCommand)(update_check_js_1.LABGATE_NPM_PACKAGE),
|
|
2666
2583
|
restartCommand: 'labgate ui',
|
|
2667
2584
|
checkError: published.error,
|
|
2668
2585
|
});
|
|
@@ -5821,12 +5738,24 @@ async function handleGetWebTerminalHistory(reqUrl, res) {
|
|
|
5821
5738
|
limit = Math.max(1, Math.min(WEB_TERMINAL_HISTORY_PAGE_MAX, Math.floor(parsedLimit)));
|
|
5822
5739
|
}
|
|
5823
5740
|
const bridge = await ensureWebTerminalBridge(record);
|
|
5741
|
+
const currentCommand = await getTmuxSessionForegroundCommand(record.tmuxSession);
|
|
5824
5742
|
if (!bridge) {
|
|
5825
|
-
json(res, {
|
|
5743
|
+
json(res, {
|
|
5744
|
+
ok: true,
|
|
5745
|
+
id: record.id,
|
|
5746
|
+
currentCommand: currentCommand || null,
|
|
5747
|
+
history: {
|
|
5748
|
+
chunks: [],
|
|
5749
|
+
hasMore: false,
|
|
5750
|
+
nextBefore: null,
|
|
5751
|
+
oldestSeq: null,
|
|
5752
|
+
latestSeq: null,
|
|
5753
|
+
limit,
|
|
5754
|
+
},
|
|
5755
|
+
});
|
|
5826
5756
|
return;
|
|
5827
5757
|
}
|
|
5828
5758
|
const page = getWebTerminalHistoryPage(bridge, { beforeSeq, limit });
|
|
5829
|
-
const currentCommand = await getTmuxSessionForegroundCommand(record.tmuxSession);
|
|
5830
5759
|
json(res, {
|
|
5831
5760
|
ok: true,
|
|
5832
5761
|
id: record.id,
|