Skip to content

fix(services): expand banner box to prevent │ from corrupting public URL (cloudflared)#1419

Open
MauroDruwel wants to merge 6 commits intoNVIDIA:mainfrom
MauroDruwel:fix/cloudflare-url-box-overflow
Open

fix(services): expand banner box to prevent │ from corrupting public URL (cloudflared)#1419
MauroDruwel wants to merge 6 commits intoNVIDIA:mainfrom
MauroDruwel:fix/cloudflare-url-box-overflow

Conversation

@MauroDruwel
Copy link
Copy Markdown
Contributor

@MauroDruwel MauroDruwel commented Apr 3, 2026

Summary

When the cloudflare tunnel URL (~50 chars) is printed inside a fixed-width ASCII box using padEnd(40), no padding is added and the closing (U+2502) box character lands immediately after the URL. Terminals auto-detect the as part of the URL and Punycode-encode .com│.xn--com-hs4a, producing a broken, non-clickable link. This PR fixes the banner in both src/lib/services.ts and scripts/start-services.sh to expand the box width dynamically so there are always at least 2 trailing spaces before the closing border.

Screenshot of issue

image

Changes

  • src/lib/services.ts: replaced hardcoded padEnd(40) banner with a dynamic-width renderer that computes inner = max(53, urlPrefix.length + url.length + 2) and pads all box lines to match.
  • scripts/start-services.sh: same fix using printf %-*s with a dynamically computed field width.

Type of Change

  • Code change for a new feature, bug fix, or refactor.

Testing

  • npx prek run --all-files passes (or equivalently make check).
  • npm test passes.

Screenshot after

image

General

Code Changes

  • Formatters applied — npx prek run --all-files auto-fixes formatting (or make format for targeted runs).
  • Tests added or updated for new or changed behavior.
  • No secrets, API keys, or credentials committed.
  • Doc pages updated for any user-facing behavior changes.

Signed-off-by: Mauro Druwel <mauro.druwel@gmail.com>

Summary by CodeRabbit

  • Refactor
    • Startup and registration banners now dynamically resize to fit content, improving layout for longer entries.
    • Public URL and status lines are shown only when relevant, reducing clutter in console output.
    • Banner borders and padding are computed to keep text aligned and visually consistent across different environments.

claude added 2 commits April 3, 2026 14:17
When the cloudflare tunnel URL is longer than 40 chars (typical for
trycloudflare.com URLs like ~50 chars), padEnd(40) adds no padding, so
the closing │ box character is printed immediately after the URL. Terminals
auto-detect this as part of the URL and Punycode-encode the │ (U+2502),
turning `.com│` into `.xn--com-hs4a`, producing a broken non-clickable URL.

Fix by computing the box inner width dynamically: default 53 chars, but
expanded to fit `url + 2 trailing spaces` when the URL is longer. All box
lines are rendered with the computed width so borders stay aligned.

Same fix applied to scripts/start-services.sh (bash variant).

https://claude.ai/code/session_01VBztUR9CyS1QtWaDf5zCFp
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9d25f78a-bd06-442b-8c51-6b54e3c99388

📥 Commits

Reviewing files that changed from the base of the PR and between c2e7d8f and 77616bd.

📒 Files selected for processing (2)
  • nemoclaw/src/index.ts
  • scripts/start-services.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/start-services.sh

📝 Walkthrough

Walkthrough

Three banner renderings were refactored from fixed-width ASCII boxes to dynamically-sized boxes: scripts/start-services.sh, src/lib/services.ts, and nemoclaw/src/index.ts. Each now computes an inner width (with a minimum), builds matching borders, pads lines to that width, and conditionally renders the Public URL / Telegram rows when data is present.

Changes

Cohort / File(s) Summary
Start script banner
scripts/start-services.sh
Replaced hardcoded ASCII box with dynamic width computation (min inner width, expands for tunnel URL), builds horizontal border, uses printf with computed padding, and conditionally prints Public URL line.
Service start banner
src/lib/services.ts
Refactored startAll() console banner to compute inner width, generate hBar, pad lines (titleText, telegramText, footerText), and conditionally include tunnelUrl (Public URL) within the resized box.
Nemoclaw registration banner
nemoclaw/src/index.ts
Converted fixed-width registration box to a dynamically-sized box by computing inner width from endpoint/provider/model lengths, generating a horizontal border, and padding banner lines to align with computed width.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 a hop, a nibble, a hop again
Boxes stretched from tip to tail,
Lines now fit each growing trail,
URLs whisper, padding sings,
I celebrate with fluffed-up wings! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: implementing dynamic banner box expansion to fix URL corruption caused by fixed-width formatting when Cloudflared tunnel URLs exceed the hardcoded padding width.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/start-services.sh (1)

199-210: Reduce magic-number width math in banner rows.

The width offsets (19, 15, 29, 37, 50) are easy to desync during text edits. Consider deriving them from string lengths so the box stays correct if labels change.

Suggested refactor (length-derived widths)
-  printf "  │  NemoClaw Services%-*s│\n" $(( inner - 19 )) ""
+  local title_text="  NemoClaw Services"
+  local url_prefix="  Public URL:  "
+  local telegram_running_text="  Telegram:    bridge running"
+  local telegram_stopped_text="  Telegram:    not started (no token)"
+  local footer_text="  Run 'openshell term' to monitor egress approvals"
+
+  printf "  │%s%-*s│\n" "$title_text" $(( inner - ${`#title_text`} )) ""
   printf "  │%-*s│\n" "$inner" ""
   if [ -n "$tunnel_url" ]; then
-    printf "  │  Public URL:  %-*s│\n" $(( inner - 15 )) "$tunnel_url"
+    printf "  │%s%-*s│\n" "$url_prefix" $(( inner - ${`#url_prefix`} )) "$tunnel_url"
   fi
   if is_running telegram-bridge; then
-    printf "  │  Telegram:    bridge running%-*s│\n" $(( inner - 29 )) ""
+    printf "  │%s%-*s│\n" "$telegram_running_text" $(( inner - ${`#telegram_running_text`} )) ""
   else
-    printf "  │  Telegram:    not started (no token)%-*s│\n" $(( inner - 37 )) ""
+    printf "  │%s%-*s│\n" "$telegram_stopped_text" $(( inner - ${`#telegram_stopped_text`} )) ""
   fi
   printf "  │%-*s│\n" "$inner" ""
-  printf "  │  Run 'openshell term' to monitor egress approvals%-*s│\n" $(( inner - 50 )) ""
+  printf "  │%s%-*s│\n" "$footer_text" $(( inner - ${`#footer_text`} )) ""
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/start-services.sh` around lines 199 - 210, Replace the hardcoded
magic-number width offsets by computing pad widths from the actual text lengths
before each printf; for each banner line (the printf calls that use "inner" and
constants) build the text portion (e.g., the labels like "NemoClaw Services",
"Public URL:  $tunnel_url", "Telegram:    bridge running" or "Telegram:    not
started (no token)"), compute pad = inner - ${`#text`} (or use expr/parameter
expansion) and then pass that pad to printf. Update the printf lines in
scripts/start-services.sh that reference inner and numeric offsets so they use
the computed pad variable and the text variable instead of the hardcoded
numbers, and ensure the is_running branch constructs its text before measuring
length.
src/lib/services.ts (1)

354-359: Harden width calculation against future text edits.

pad() can throw if any row text grows past inner later. Consider deriving inner from all row candidates and clamping repeat count.

Suggested hardening
-  const minInner = 53;
-  const inner = tunnelUrl ? Math.max(minInner, urlPrefix.length + tunnelUrl.length + 2) : minInner;
-
-  const pad = (s: string) => s + " ".repeat(inner - s.length);
+  const minInner = 53;
+  const rows = [
+    titleText,
+    telegramText,
+    footerText,
+    tunnelUrl ? `${urlPrefix}${tunnelUrl}` : "",
+  ];
+  const inner = Math.max(minInner, ...rows.map((s) => s.length + 2));
+
+  const pad = (s: string) => s + " ".repeat(Math.max(0, inner - s.length));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/services.ts` around lines 354 - 359, The current width logic
(minInner, inner, pad, hBar) can break if any future row grows beyond inner;
update the calculation to compute inner from the lengths of all candidate row
strings (e.g., urlPrefix, tunnelUrl and any other lines you render) taking the
maximum length plus your extra padding, then clamp inner with Math.max(minInner,
computedMax) and ensure pad uses Math.max(0, inner - s.length) when repeating
spaces and hBar uses "─".repeat(Math.max(0, inner)) so no negative repeat
occurs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/start-services.sh`:
- Around line 199-210: Replace the hardcoded magic-number width offsets by
computing pad widths from the actual text lengths before each printf; for each
banner line (the printf calls that use "inner" and constants) build the text
portion (e.g., the labels like "NemoClaw Services", "Public URL:  $tunnel_url",
"Telegram:    bridge running" or "Telegram:    not started (no token)"), compute
pad = inner - ${`#text`} (or use expr/parameter expansion) and then pass that pad
to printf. Update the printf lines in scripts/start-services.sh that reference
inner and numeric offsets so they use the computed pad variable and the text
variable instead of the hardcoded numbers, and ensure the is_running branch
constructs its text before measuring length.

In `@src/lib/services.ts`:
- Around line 354-359: The current width logic (minInner, inner, pad, hBar) can
break if any future row grows beyond inner; update the calculation to compute
inner from the lengths of all candidate row strings (e.g., urlPrefix, tunnelUrl
and any other lines you render) taking the maximum length plus your extra
padding, then clamp inner with Math.max(minInner, computedMax) and ensure pad
uses Math.max(0, inner - s.length) when repeating spaces and hBar uses
"─".repeat(Math.max(0, inner)) so no negative repeat occurs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8e6127af-2e21-4524-ae91-cb29eaffed83

📥 Commits

Reviewing files that changed from the base of the PR and between 494ecde and c2e7d8f.

📒 Files selected for processing (2)
  • scripts/start-services.sh
  • src/lib/services.ts

@MauroDruwel MauroDruwel marked this pull request as draft April 3, 2026 15:05
MauroDruwel and others added 4 commits April 3, 2026 17:17
Apply the same dynamic inner-width logic used in src/lib/services.ts to
the NemoClaw registered banner in nemoclaw/src/index.ts. The old code
used hardcoded .padEnd(40) which would push the closing │ beyond the
fixed 53-char horizontal bars whenever an endpoint, provider, or model
string exceeded 40 characters, making all lines different lengths.

Now inner width = max(53, longestValue + prefix(13) + 2 trailing spaces),
so all lines are always the same length regardless of value lengths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tr is a byte-level tool — 'tr " " "─"' only emits the first byte
(\xe2) of the 3-byte UTF-8 sequence for ─ (U+2500), producing invalid
UTF-8 that renders as garbled characters in the terminal.

Replace with a bash += loop which correctly appends the full multi-byte
character on each iteration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MauroDruwel MauroDruwel marked this pull request as ready for review April 3, 2026 15:32
@wscurran wscurran added bug Something isn't working priority: medium Issue that should be addressed in upcoming releases NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). observability Use this label to improve NemoClaw logging, metrics, and tracing. labels Apr 3, 2026
@wscurran
Copy link
Copy Markdown
Contributor

wscurran commented Apr 3, 2026

✨ Thanks for submitting this pull request, which proposes a way to fix a display issue in the CLI banner where the cloudflare tunnel URL gets corrupted by a box-drawing character. This could improve observability by ensuring URLs remain clickable and correctly rendered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). observability Use this label to improve NemoClaw logging, metrics, and tracing. priority: medium Issue that should be addressed in upcoming releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants