@khanglvm/relay 0.13.2 → 0.13.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanglvm/relay",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "description": "Question boards with rich blocks (markdown, charts, mermaid, tables, code, diffs, video, sandboxed HTML), clickable local file-links, and element-level annotations for AI coding agents (Claude Code, Codex, …): ask users structured questions, present interactive visuals, collect inline comments, read answers as JSON — in a local browser board OR rendered INLINE inside the Claude & Codex apps as an MCP App (SEP-1865).",
5
5
  "keywords": [
6
6
  "ai-agents",
package/src/server.js CHANGED
@@ -694,13 +694,22 @@ export async function runBoard({ id, port = 0, open = true, timeoutSec = 1800, q
694
694
  });
695
695
 
696
696
  // Bind the requested port (reopen/rescue reuse the board's last port so a
697
- // still-open tab reconnects). If that port was grabbed by another process in
698
- // the meantime, fall back to a random free one rather than failing to boot.
697
+ // still-open tab reconnects). A board just stopped on that port holds its
698
+ // listening socket through a short close grace, so a stop-then-reopen on the
699
+ // same port can briefly hit EADDRINUSE — retry for ~2s to ride that out before
700
+ // giving up. Only then fall back to a random free port rather than failing.
699
701
  await new Promise((resolve, reject) => {
702
+ const RETRY_MS = 200;
703
+ const MAX_RETRIES = 10; // ~2s — covers a prior server's ~600ms close grace
704
+ let retries = 0;
700
705
  const bind = (p, allowFallback) => {
701
706
  const onErr = (e) => {
702
707
  if (allowFallback && e && e.code === 'EADDRINUSE' && p !== 0) {
703
- bind(0, false); // desired port busy → random free one
708
+ if (retries++ < MAX_RETRIES) {
709
+ setTimeout(() => bind(p, true), RETRY_MS); // port freeing up — retry it
710
+ } else {
711
+ bind(0, false); // still busy after retries → random free port
712
+ }
704
713
  } else {
705
714
  reject(e);
706
715
  }
package/src/ui/blocks.js CHANGED
@@ -453,13 +453,22 @@
453
453
  const rows = [];
454
454
  let oldNo = 0;
455
455
  let newNo = 0;
456
+ // Diff content (+/-/context) only has meaning INSIDE a hunk. Lines before the
457
+ // first @@ are either recognized headers (handled below) or the commit
458
+ // header/message of `git show`/`git log -p` output — skip the latter so it
459
+ // isn't rendered as bogus context rows (which split view duplicates on both
460
+ // sides as long unwrapped lines, shoving the new side off-screen).
461
+ let inHunk = false;
456
462
  for (const line of lines) {
457
463
  if (/^@@/.test(line)) {
458
464
  const m = line.match(/@@\s*-(\d+)(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s*@@/);
459
465
  if (m) { oldNo = Number(m[1]) - 1; newNo = Number(m[2]) - 1; }
466
+ inHunk = true;
460
467
  rows.push({ kind: 'hunk', text: line });
461
468
  } else if (/^(diff |index |--- |\+\+\+ |new file|deleted file|old mode|new mode|similarity|rename |copy )/.test(line)) {
462
469
  rows.push({ kind: 'meta', text: line });
470
+ } else if (!inHunk) {
471
+ continue; // commit header/message preamble before the first hunk — drop it
463
472
  } else if (line[0] === '+') {
464
473
  rows.push({ kind: 'add', text: line.slice(1), newNo: newNo++ });
465
474
  } else if (line[0] === '-') {