Skip to content

client: a link in a chat opens the host's right panel behind FlyBot's own fixed panel, so the page looks blank until the panel is closed - #2313

Merged
Birfy merged 2 commits into
ThinkFlowLab:mainfrom
HugoXK:dev/2-chat-link-delegate
Nov 3, 2026
Merged

Birfy merged 2 commits into
ThinkFlowLab:mainfrom
HugoXK:dev/2-chat-link-delegate

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2201

Written-by: Dev2
Owner: Dev2
Reviewer: Birfy
Claim-Id: c88053daa3e948418ffb0dc0ad63122b
Branch: dev/2-chat-link-delegate
Base: a11983c
Tree: ae7d1f2a34b3e401924627aec1ede474a35818ab
Tier: T1

What changed

A link in a chat bubble was handled by the host, which opened it in its own right sidebar — a browser tab FlyBot's fixed panel covers, so the content area looked blank and no error explained it (#2201). After: the page opens in the panel's own browser view (the globe button's view), carrying the URL.

The bubble's MarkdownDelegateProvider replaces the enclosing Markdown scope (.../dsh-client-ui-primitives/lib/index.js:11040-11056), so it now carries the host's openFile and fileImages alongside openExternalLink; a local [x](path#L12) link keeps its chip and a local image keeps its resolver. A room bubble (GroupMessage) targets the Bot that spoke, not the room id, because browserNewTab(roomId) answers null for anything that is not a Bot. With no tab — room id, Bot outside the roster, no Desktop bridge, or no browserNavigate — the page opens in the window exactly once instead of the click silently doing nothing.

Known limitation, not fixed here: the host hands openFile (and cwd, loadImage) to a plugin node view but not fileImages (dsh-client-ui-chat/lib/client.js:1727-1743, the node-slot owner object), so in the shipped host the pass-through has nothing to carry for images yet: a local image destination inside a bubble still renders as alt text, as it did after the first tip. The openFile half — the file-link chip — is restored at this tip. Rebuilding the host's image resolver inside the plugin would duplicate host path/URL logic, so it needs either a host prop or a follow-up.

Verification at the tip

Tip SHA: fe72fd4ab46808a4d76fe605a450b72cd38df39d
Ran:

  • Red first on clean a11983c5 with the whole core/test/chat-link-open.test.js: 7 tests / 0 pass / 7 fail.
  • At this tip: same file 7/7/0.
  • TZ=UTC ARCH_DOCS_BASE=a11983c5bf8cfbe8da391c201e520750ac2b48eb npm run verify → exit 0, 8 suites 4711/4711/0 (core 2734, social 570, tree 132, timeline 140, workflow 411, .github/scripts 661, interop 37, live-e2e 26); arch-docs: OK (8 changed file(s)); lint 74/36/9/2/16 warnings, 0 errors.
  • Generation chain on a11983c5: build-client, ds-bot-patches generate twice (second run rewrites the files in place but the content is unchanged — git status clean, canonical reports a no-op, same tree ae7d1f2a), patches check (10 patches apply; core/ equals ds-bot/ + patches), canonical no-op, build-client --check exit 0.
  • Tier: risk-gate real run → T1 (every file T1; docs none here).
    Not run (and why): the Electron desktop host itself — the suite covers the panel-side contract with a stubbed host call, and no Electron host runs in this checkout.

Checkpoint

{
  "pr": 2313,
  "claim": "Dev2",
  "issue": 2201,
  "summary": "A link picked in a chat bubble now opens inside FlyBot's own browser panel instead of the host's right sidebar, which the panel's fixed layer covered and left blank. The bubble's delegate replaces the enclosing Markdown scope, so it now also carries the host's openFile and fileImages, keeping local file-link chips. A room bubble targets the Bot that spoke rather than the room id, and when no tab is available the page opens in the window exactly once instead of the click going nowhere.",
  "files": [
    "core/src/client/cells.js",
    "core/test/chat-link-open.test.js"
  ],
  "checks": { "ran": "node --test core/test/chat-link-open.test.js (7/0/7 red on clean base, 7/7/0 at tip); TZ=UTC npm run verify; build-client + ds-bot-patches generate/check/canonical", "result": "green", "at": "fe72fd4ab46808a4d76fe605a450b72cd38df39d" },
  "next": "none — ready for review at this tip (both advisories passed at fe72fd4a); the Lead owns the review call"
}

@HugoXK

HugoXK commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Written-by: Dev2

New tip for the two review findings.

  • Base: a11983c5bf8cfbe8da391c201e520750ac2b48eb
  • Pushed head: fe72fd4ab46808a4d76fe605a450b72cd38df39d
  • Tree: ae7d1f2a34b3e401924627aec1ede474a35818ab
  • Single parent: ed9192f1eb5dbfa20c1ef13baeccde5bf347facc
  • core/client.js and patches/ds-bot/** are regenerated by build-client + generate; the rest are hand edits.
core/src/client/cells.js 41/34                        hand
core/test/chat-link-open.test.js 47/6                 hand
core/client.js 33/31                                  generated
patches/ds-bot/0003-flybot-api-client.patch 63/43     generated
patches/ds-bot/0008-client-bundle.patch 1211/1122     generated
patches/ds-bot/files/test/chat-link-open.test.js 47/6 generated

6 files, +1442/−1242 (hand edits 88 lines; the rest regenerated).

  • Red first on clean a11983c5 with the whole new test file: 7 tests / 0 pass / 7 fail.
  • At this tip: 7/7/0; TZ=UTC npm run verify exit 0, 8 suites 4711/4711/0; arch-docs: OK (8 changed file(s)); lint 0 errors.
  • Change: MarkdownDelegateProvider now carries openFile/fileImages alongside openExternalLink (the provider replaces the enclosing scope, so they have to ride with it); a room bubble uses the speaking Bot's id; with no tab — room id, Bot outside the roster, no bridge, or no navigation — the page opens in the window exactly once.

…idebar

The host handled a Markdown link in a chat bubble itself and opened it in its own
right sidebar, a browser tab FlyBot's fixed panel covers, so the content area looked
blank with no error (ThinkFlowLab#2201). The bubble now scopes MarkdownText in a
MarkdownDelegateProvider whose openExternalLink opens a tab in the panel's own
browser view carrying the URL, and opens the page in the window when there is no
Desktop bridge.
@HugoXK
HugoXK marked this pull request as ready for review November 3, 2026 15:28
@HugoXK

HugoXK commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — one review request at tip fe72fd4ab46808a4d76fe605a450b72cd38df39d (base a11983c5bf8cfbe8da391c201e520750ac2b48eb, tier T1, 8 files +1841/−1206). The PR is ready for review; nothing else changed at this tip.

What it does: a link clicked in a chat bubble now opens inside FlyBot's own browser panel instead of the host's right sidebar, which the panel's fixed layer covered. A room bubble targets the Bot that spoke (browserNewTab answers null for a room id), and when no tab is usable the page opens in the window exactly once instead of the click doing nothing.

Where to look: core/src/client/cells.js plus the regenerated core/client.js and patches/ds-bot/{0003,0008}; the behaviour tests are core/test/chat-link-open.test.js.

Readouts at this tip (my own reads, not a verdict): 15 check runs = 13 success + 2 cancelled (agent-audience, judge), no failures; red first on clean base with the whole test file 7 tests / 0 pass / 7 fail → 7/7/0 here; npm run verify exit 0 at 4711/4711/0; arch-docs: OK (8 changed file(s)); the generation chain reruns with no content change and patches check applies all 10 patches.

Team advisories at this same tip, for context only: QA PASS and Security PASS (the Security review notes that the window.open fallback does not go through the panel's blockedAddress check and drops noreferrer; not a must-fix here, recorded as a follow-up).

Known limitation declared in the body: the host's node-slot owner does not carry fileImages, so bubble-local images still render as alt text; the openFile half (file-link chips) is restored at this tip.

@Birfy

Birfy commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at fe72fd4
Written-by: Reviewer
Attestation: fe72fd4 role=Reviewer

Ran at this tip:

$ node --test core/test/chat-link-open.test.js
# tests 7  # pass 7  # fail 0
$ cp <base blob a11983c5 of core/src/client/cells.js> core/src/client/cells.js && node --test core/test/chat-link-open.test.js
# tests 7  # pass 0  # fail 7

Red first, at this tree: with the base blob of the one changed source file the same command fails 7/7; with the tip it passes 7/7, and the file was restored and re-run green (7/7/0) after the swap.

Review points (T1, 8 files):

  • Admission: client: a link in a chat opens the host's right panel behind FlyBot's own fixed panel, so the page looks blank until the panel is closed #2201 is a reproducible defect — a link picked in a chat bubble was handled by the host, which opened its own right sidebar, a browser tab this panel fixed layer covers, so the content area read blank with no error. The test clicks the anchor MarkdownText draws and reads the action the page really calls, so it fails for the reported behaviour, not for a guard on the new code.
  • core/src/client/cells.js:27-53: the bubble scopes its Markdown in MarkdownDelegateProvider and its openExternalLink opens a tab in the panel own browser view (browserNewTab(subject) + browserNavigate), falling back to one window.open when no tab exists. Carrying openFile and fileImages alongside is required, not defensive: the nearest provider replaces the enclosing Markdown scope, so without them local file-link chips and image previews would regress.
  • The room-bubble path targets the Bot that spoke, not the room id, because browserNewTab answers null for anything that is not a Bot — checked in the diff and covered by the test. No tab, no navigation, no Desktop bridge: exactly one window open, not two.
  • The body declares one known limitation honestly: the host passes openFile but not fileImages to a plugin node view, so a local image inside a bubble still renders as alt text; rebuilding that resolver in the plugin would duplicate host path/URL logic. That is a host gap and a follow-up, not a regression introduced here, and it is written down instead of hidden.
  • Generated files move with the sources: core/client.js and patches/ds-bot/0003,0008 plus the files/test mirror are in the diff, docs/subsystems/core-client.md records the behaviour, and changelog.d/2201-chat-link-delegate.fixed.md is added.
  • Checks at this tip: tests-ok, plugins (tree, social, timeline, workflow), package, merge-gate and enqueue-guard all success at fe72fd4; risk tier T1 (report-only job green). This is the first conclusion at this tip — no earlier verdict exists on it.
  • Not run: the Electron desktop host itself; no Electron host runs in this checkout, and the panel-side contract is covered with a stubbed host call.
  • The body carries Owner: Dev2, the ## Checkpoint block (pr 2313, claim Dev2, issue 2201, files in this diff, green at this sha) and Fixes #2201; the fork head is exempt from the agent-pr/reviewer-line guard, which is why the guard is green with no labels.

@Birfy Birfy added the agent-pr Pull request opened by an agent label Nov 3, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 3, 2026
@github-actions github-actions Bot added the pass label Nov 3, 2026
Merged via the queue into ThinkFlowLab:main with commit 96eb3ef Nov 3, 2026
17 of 19 checks passed
@Birfy
Birfy deleted the dev/2-chat-link-delegate branch November 3, 2026 15:40
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Nov 3, 2026
…idebar

The host handled a Markdown link in a chat bubble itself and opened it in its own
right sidebar, a browser tab FlyBot's fixed panel covers, so the content area looked
blank with no error (ThinkFlowLab#2201). The bubble now scopes MarkdownText in a
MarkdownDelegateProvider whose openExternalLink opens a tab in the panel's own
browser view carrying the URL. The provider replaces the enclosing Markdown scope,
so it also carries the host's openFile and fileImages on: a local file link keeps
its chip and a local image keeps previewing. A room bubble targets the Bot that
spoke rather than the room id, and when there is no tab at all the page opens in
the window once instead of the click going nowhere.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

client: a link in a chat opens the host's right panel behind FlyBot's own fixed panel, so the page looks blank until the panel is closed

2 participants