termdock 1.4.371 → 1.4.372

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.
@@ -2921,7 +2921,9 @@ function getTmuxBinary() {
2921
2921
  return 'tmux'; // fallback to PATH
2922
2922
  }
2923
2923
  async function runTmux(args, options) {
2924
- const { stdout } = await execFileAsync(getTmuxBinary(), args, {
2924
+ // Non-UTF-8 clients on newer tmux sanitize control delimiters to underscores.
2925
+ // Services launched without a locale must preserve machine-readable output.
2926
+ const { stdout } = await execFileAsync(getTmuxBinary(), ['-u', ...args], {
2925
2927
  timeout: 5000,
2926
2928
  maxBuffer: options?.maxBuffer ?? 2 * 1024 * 1024,
2927
2929
  env: buildInteractiveColorEnvironment(process.env),
@@ -2932,7 +2934,7 @@ async function runTmux(args, options) {
2932
2934
  * content to `load-buffer -`. Kept separate from runTmux so the many callers
2933
2935
  * that never pipe anything are untouched. */
2934
2936
  async function runTmuxStdin(args, input) {
2935
- const child = execFile(getTmuxBinary(), args, {
2937
+ const child = execFile(getTmuxBinary(), ['-u', ...args], {
2936
2938
  timeout: 5000,
2937
2939
  maxBuffer: 2 * 1024 * 1024,
2938
2940
  env: buildInteractiveColorEnvironment(process.env),
@@ -3368,10 +3370,17 @@ async function listLiveTmuxInventorySessions() {
3368
3370
  const raw = await runTmux(['list-sessions', '-F', format]);
3369
3371
  return raw
3370
3372
  .split('\n')
3371
- .map((line) => line.trim())
3373
+ .map((line) => line.replace(/\r$/, ''))
3372
3374
  .filter(Boolean)
3373
- .map((line) => parseDelimitedRow(line, 15))
3374
- .filter((row) => row !== null)
3375
+ .map((line) => {
3376
+ const row = parseDelimitedRow(line, 15);
3377
+ // A partial or malformed scan is unknown, never proof of session loss.
3378
+ // Reject the entire scan so recovery/reconcile cannot delete records.
3379
+ if (!row || !/^\d+$/.test(row[1]) || !/^\d+$/.test(row[2])) {
3380
+ throw new Error('Invalid tmux session inventory row');
3381
+ }
3382
+ return row;
3383
+ })
3375
3384
  .map(([name, windowsRaw, attachedRaw, friendlyName, program, cwd, label, clientCountRaw, host, pidRaw, version, createdAtRaw, lastActiveAtRaw, guiDetachedAtRaw, sourceFrontendSessionId,]) => ({
3376
3385
  name,
3377
3386
  windows: Number.parseInt(windowsRaw || '0', 10) || 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termdock",
3
- "version": "1.4.371",
3
+ "version": "1.4.372",
4
4
  "description": "A complete web-based terminal application with modern UI",
5
5
  "type": "module",
6
6
  "main": ".desktop-dist/main.js",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "packageName": "termdock",
4
- "version": "1.4.371",
4
+ "version": "1.4.372",
5
5
  "runtimeProtocolVersion": 1,
6
6
  "minimumDesktopVersion": "1.4.46",
7
7
  "nodeMajor": 22,
8
8
  "dependencyHash": "sha256-Y8lMrpp3Lu4r/I8Zx3R59DZsC3RtYVYC7b/kH84ZMeY=",
9
- "serverBundleHash": "sha256-yBB1I/3vFzMaEpzWpMGS1zYuYqyP8E099AOdnd6R/Zw=",
9
+ "serverBundleHash": "sha256-ab8otV2I41nS5TQW/BmOO4tGi54enuEG7WS53HbJccE=",
10
10
  "clientBundleHash": "sha256-62DpReFWG6al4v41Zsl0vt+TUdtlqzXUlAWDw6qXX6o=",
11
11
  "entrypoint": "dist/server/cli.js",
12
12
  "clientEntrypoint": "dist/client/index.html"