Skip to content

upstream/2026-04-26 PR4: remote ports 大物 (port-scanner 切り出し + v2 サイドバー統合)#438

Merged
MocA-Love merged 2 commits intomainfrom
upstream/batch-2026-04-26-pr-d
Apr 26, 2026
Merged

upstream/2026-04-26 PR4: remote ports 大物 (port-scanner 切り出し + v2 サイドバー統合)#438
MocA-Love merged 2 commits intomainfrom
upstream/batch-2026-04-26-pr-d

Conversation

@MocA-Love
Copy link
Copy Markdown
Owner

Summary

upstream (superset-sh/superset) からの 9 commits 取り込みバッチの PR4(最後・最大)。7c0d22b77 (superset-sh#3676) は 78 files / +4234 -1088 の大物で、新規 packages/port-scanner/ パッケージを切り出し、host-service の v2 リモートポートをサイドバーに統合する。9 件の conflict を fork の v1 PortsList 機能(detected/static 二段表示、isPending loader、navigation)を保持しつつ統合。

取り込み内容

Commit upstream PR 概要
7c0d22b77 superset-sh#3676 packages/port-scanner/ 新規パッケージ抽出(PortManager + scanner + procfs + static-ports)。host-service の ports.getAll で workspace ごとの ports.json ラベルを解決。renderer の usePortsData が remote v2 host を 5 秒間隔で polling して merge。EnrichedPort.hostUrl を導入し、kill を hostUrl-based でルーティング。

加えて 19af7282c で fork 固有依存(browser-automation / browser-mcp-bridge)を新パッケージへ移行。

Fork 側のコンフリクト解決(9 ファイル)

shared/types/ports.ts

  • fork の EnrichedPort 拡張(detected, pid, processName, terminalId, detectedAt, address)を保持しつつ、upstream の hostUrl: string | null(local Electron port なら null、remote host-service URL でルーティング)を統合。
  • v1 PortsList 互換のため paneIdterminalId にリネーム(upstream の port-scanner は DetectedPort.terminalId を使うため、もはや paneId と呼ぶ意味がない)。

apps/desktop/src/lib/trpc/routers/ports/ports.ts

  • fork の buildLabelCache / getLabelsForPath (detected + static port を返す 2 段アプローチ) を保持。
  • getAll で各 EnrichedPortterminalId (was paneId) と hostUrl: null を補完。
  • upstream の getLabelsForWorkspace (label-cache.ts) は fork のキャッシュ構造と被るので使わず、invalidatePortLabelCache re-export だけ残す(projects.ts / db-helpers.ts が消費)。

packages/host-service/src/trpc/router/workspace/workspace.ts

  • import 競合: fork の createSimpleGitWithEnv と upstream の invalidateLabelCache を併存。

apps/desktop/src/main/lib/host-service-coordinator.ts

  • conflict なし(PR3 で先に解消済み、auto-merge 成立)。

v2 worktree 関連

  • TerminalPane.tsx: ターミナル OSC リンク open を openUrlInV2Workspace({store, target: "current-tab", url}) ヘルパー経由に統一(upstream 方針)。
  • openUrlInV2Workspace.ts: fork の BrowserPaneData.mode が必須なので data: { url, mode: "generic" } satisfies BrowserPaneData で補完(FORK NOTE)。
  • v2-workspace/$workspaceId/page.tsx: fork の useCollections / rightSidebarOpenViewWidth / setShowPresetsBar 系と upstream の useConsumeOpenUrlRequest両方併記

v1 PortsList 関連

  • useKillPort.ts: paneId → terminalId にリネーム + workspaceId を kill mutation に追加(新スキーマ {workspaceId, terminalId, port} 対応)。upstream の usePortKillActions ヘルパーは v2 用なので使わず、v1 のインライン toast.error 実装を保持(FORK NOTE)。
  • MergedPortBadge.tsx (4 ブロック):
    • isDetected 分岐(fork 仕様: detected = primary 色、!detected = muted 色 + "Not detected" 表示、static label 列挙用)を保持。
    • upstream の isPending ベース LuLoaderCircle spinning loader を採用。
    • port.terminalId baseline で canJumpToTerminal 判定。
  • WorkspacePortGroup.tsx: handleCloseAllif (isPending) return; void killPorts(detectedPorts) に統合(fork の "detected ports のみ kill" + upstream の pending ガード)。

19af7282c 統合 fix

  • packages/port-scanner/src/index.ts: getProcessCommand, getProcessName追加 re-export(fork 専用 browser-automation ルーターと browser-mcp-bridge/pane-resolver が消費)。
  • apps/desktop/src/lib/trpc/routers/browser-automation/index.ts, apps/desktop/src/main/lib/browser-mcp-bridge/pane-resolver.ts: main/lib/terminal/port-scanner@superset/port-scanner への import path 移行。
  • biome formatter による整形 (shared/types/ports.ts, browser-automation/index.ts)。

Fork 固有機能ヘルスチェック

  • 19 tRPC procedure: 全件健在
  • ansi_up / @vscode/ripgrep / @xyflow/react 健在
  • TERMINAL_OPTIONS / SUPERSET_WORKSPACE_NAME / moonshot-ai.kimi-code / MainWindowEffects / INCEPTION_AUTH_PROVIDER_ID / v1MigrationState / TiptapPromptEditor 健在
  • desktop 1.5.10、drizzle idx (db=0035 / local-db=0072) 維持
  • v1 PortsList の static port 表示 + detected/!detected 分岐: 維持
  • v2 サイドバーに新規 DashboardSidebarPortsList (新 v2 用) が追加され、v1 PortsList と併存

検証

  • bun install: ✅ (5757 packages, 46s)
  • bun run typecheck: ✅ (28/28 successful, fork 統合 fix 後)
  • bun run lint: ✅ (Biome: 4368 files, no fixes applied; format fix は cherry-pick 直後に取り込み済み)
  • bun run --filter @superset/desktop compile:app: ✅ (electron-vite build, 3m 48s, exit 0)

上流バッチ取り込み完了

このマージで behind upstream/main = 0 に到達(PR1〜PR4 で 9 commits 全件取り込み)。

Test plan

  • v1 サイドバー: detected port (primary 色) と未 detected static port (muted 色 + "Not detected") の両方が表示される
  • v1 サイドバー: detected port の close ボタンで LuLoaderCircle が回り、kill が成功すると消える
  • v1 サイドバー: workspace の close-all で detectedPorts のみ kill される (static label は残る)
  • v2 サイドバー: 新規 DashboardSidebarPortsList で local + remote ports が混在表示
  • v2 サイドバー: remote v2 host (host-service) のポートも 5 秒ポーリングで merge される
  • v2 ターミナル: OSC リンククリックで browser pane が open する(mode: "generic" デフォルト)
  • browser-automation: pane resolver が新 @superset/port-scanner 経由で getProcessTree/getProcessName/getProcessCommand を呼べる

Kitenite and others added 2 commits April 26, 2026 08:57
…et-sh#3676)

* feat(ports): extract port scanner to shared package for v2 remote hosts

Move port detection and PortManager into @superset/port-scanner so the
host-service can surface remote workspace ports over tRPC subscriptions
without duplicating scan logic. Desktop and host-service each wire their
own kill strategy via a constructor-injected killFn.

Also fixes two blockers found during extraction:
- PortManager.scanAbort was nulled on stop() and never re-allocated,
  leaving subsequent scans without an AbortSignal.
- The desktop ports router hit SQLite on every enrichment; now cached
  per workspace and invalidatable.

* feat(ports): merge remote host-service ports into the sidebar list

usePortsData now polls ports.getAll on every online remote v2 host every
5s (via tanstack useQueries) and merges the results with the local
Electron port stream. Each EnrichedPort carries a hostUrl so useKillPort
can route kills to the owning host-service instead of always hitting
Electron.

Polling rather than SSE-subscribing keeps the existing httpBatchLink
client intact — the host-service already debounces scans behind hints,
so ports.getAll is a cheap in-memory read.

* feat(ports): resolve ports.json labels on remote host-services

Host-service's ports.getAll now returns EnrichedPort[] by reading each
workspace's .superset/ports.json and attaching a per-port label. The
lookup is memoized per workspaceId so the 5s renderer poll doesn't
retrigger fs+sqlite reads.

Parse errors are silent here (unlike desktop's loader, which surfaces
them): this endpoint is a best-effort hint feeding a sidebar list, not a
config validator.

* fix(ports): drop label cache entries when workspaces are deleted

Previously the label cache held a workspaceId → labels map for the life
of the process. After a workspace was deleted, the next lookup would
still return cached labels (or the cached "null" sentinel), both of
which are stale.

Desktop: split the cache out of the ports router so workspace-delete
paths can invalidate without creating a ports ↔ workspaces import cycle,
then call it from `deleteWorkspace` and the project-cascade delete.

Host-service: call `invalidateLabelCache` from `workspace.delete` and
`workspace-cleanup` after the sqlite row is removed.

Rollback-on-create paths are intentionally skipped — the workspace never
had a cache entry to begin with.

* perf(port-scanner): read /proc directly on Linux instead of spawning lsof

On Linux we now resolve listening sockets by reading /proc/net/tcp,
/proc/net/tcp6, and /proc/<pid>/fd/* in process. This is the same
approach VS Code uses for its remote tunnel port detection (see
src/vs/workbench/contrib/remoteTunnel). macOS keeps the lsof path;
Windows keeps netstat.

The switch matters for remote v2 host-services running on Linux: the
old lsof fork happened on every scan tick (2.5s periodic + hint-driven
bursts) and dominated cost on hosts with many terminal daemons. Two
file reads + one directory walk is roughly 10× cheaper and avoids
child-process lifecycle (timeouts, aborts, partial stdout).

Parsers are pure and exported so we test them on canned /proc lines
rather than requiring a real /proc mount in CI.

* fix(ports): wire v2 sidebar port list

* fix(ports): address review cleanups

* Fix v2 port sidebar interactions

* Add host port events for v2 sidebar

* Patch v2 port cache from host events

* Fix port sidebar event and kill contracts

* Refactor dashboard port data transforms
…traction

- Re-export getProcessCommand/getProcessName from @superset/port-scanner index
  (used by fork-only browser-automation router and browser-mcp-bridge).
- Update browser-automation/index.ts and pane-resolver.ts imports from the
  removed main/lib/terminal/port-scanner to @superset/port-scanner.
- Biome formatter polish on shared/types/ports.ts and browser-automation
  imports after the rename.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

Warning

Rate limit exceeded

@MocA-Love has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 25 minutes and 40 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 25 minutes and 40 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 05c0a866-1da9-4895-8801-495767b4e844

📥 Commits

Reviewing files that changed from the base of the PR and between 4089462 and 19af728.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (79)
  • apps/desktop/package.json
  • apps/desktop/plans/20260108-2251-static-ports-json.md
  • apps/desktop/src/lib/trpc/routers/browser-automation/index.ts
  • apps/desktop/src/lib/trpc/routers/ports/label-cache.ts
  • apps/desktop/src/lib/trpc/routers/ports/ports.ts
  • apps/desktop/src/lib/trpc/routers/projects/projects.ts
  • apps/desktop/src/lib/trpc/routers/workspaces/utils/db-helpers.ts
  • apps/desktop/src/main/lib/browser-mcp-bridge/pane-resolver.ts
  • apps/desktop/src/main/lib/static-ports/loader.test.ts
  • apps/desktop/src/main/lib/static-ports/loader.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.test.ts
  • apps/desktop/src/main/lib/terminal/daemon/daemon-manager.ts
  • apps/desktop/src/main/lib/terminal/port-manager.test.ts
  • apps/desktop/src/main/lib/terminal/port-manager.ts
  • apps/desktop/src/renderer/globals.css
  • apps/desktop/src/renderer/hooks/host-service/useWorkspaceEvent/useWorkspaceEvent.ts
  • apps/desktop/src/renderer/hooks/ports/usePortKillActions/index.ts
  • apps/desktop/src/renderer/hooks/ports/usePortKillActions/killPortTarget.test.ts
  • apps/desktop/src/renderer/hooks/ports/usePortKillActions/killPortTarget.ts
  • apps/desktop/src/renderer/hooks/ports/usePortKillActions/usePortKillActions.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/DashboardSidebar.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/DashboardSidebarPortsList.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/components/DashboardSidebarPortBadge/DashboardSidebarPortBadge.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/components/DashboardSidebarPortBadge/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/components/DashboardSidebarPortGroup/DashboardSidebarPortGroup.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/components/DashboardSidebarPortGroup/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/hooks/useDashboardSidebarPortKill/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/hooks/useDashboardSidebarPortKill/useDashboardSidebarPortKill.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/hooks/useDashboardSidebarPortsData/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/hooks/useDashboardSidebarPortsData/useDashboardSidebarPortsData.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/hooks/useDashboardSidebarPortsData/useDashboardSidebarPortsData.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/hooks/useDashboardSidebarPortsData/useDashboardSidebarPortsData.utils.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarPortsList/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/utils/workspace-navigation.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeOpenUrlRequest/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeOpenUrlRequest/useConsumeOpenUrlRequest.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/useConsumeOpenUrlRequest/useConsumeOpenUrlRequest.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/TerminalPane/TerminalPane.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/getSidebarClickIntent/getSidebarClickIntent.test.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/getSidebarClickIntent/getSidebarClickIntent.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/getSidebarClickIntent/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/openUrlInV2Workspace/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/utils/openUrlInV2Workspace/openUrlInV2Workspace.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/components/MergedPortBadge/MergedPortBadge.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/components/WorkspacePortGroup/WorkspacePortGroup.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/hooks/useKillPort.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/hooks/usePortsData.ts
  • apps/desktop/src/shared/types/ports.ts
  • apps/docs/content/docs/ports.mdx
  • packages/host-service/package.json
  • packages/host-service/src/events/event-bus.test.ts
  • packages/host-service/src/events/event-bus.ts
  • packages/host-service/src/events/index.ts
  • packages/host-service/src/events/types.ts
  • packages/host-service/src/ports/port-manager.ts
  • packages/host-service/src/ports/static-ports.ts
  • packages/host-service/src/ports/tree-kill.ts
  • packages/host-service/src/terminal/terminal.ts
  • packages/host-service/src/trpc/router/ports/index.ts
  • packages/host-service/src/trpc/router/ports/ports.ts
  • packages/host-service/src/trpc/router/router.ts
  • packages/host-service/src/trpc/router/workspace-cleanup/workspace-cleanup.ts
  • packages/host-service/src/trpc/router/workspace/workspace.ts
  • packages/port-scanner/package.json
  • packages/port-scanner/src/index.ts
  • packages/port-scanner/src/port-manager.test.ts
  • packages/port-scanner/src/port-manager.ts
  • packages/port-scanner/src/procfs.test.ts
  • packages/port-scanner/src/procfs.ts
  • packages/port-scanner/src/scanner.test.ts
  • packages/port-scanner/src/scanner.ts
  • packages/port-scanner/src/static-ports.ts
  • packages/port-scanner/src/types.ts
  • packages/port-scanner/tsconfig.json
  • packages/workspace-client/src/index.ts
  • packages/workspace-client/src/lib/eventBus.ts
  • plans/20260422-v2-remote-ports.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch upstream/batch-2026-04-26-pr-d

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 26, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

@MocA-Love MocA-Love merged commit 3b8f827 into main Apr 26, 2026
12 of 13 checks passed
MocA-Love added a commit that referenced this pull request Apr 26, 2026
PR1〜PR5 (#435 #436 #437 #438 #440) で 13 commits 全件 cherry-pick + 手動 conflict 解消で取り込み済み。
本コミットは git 履歴上 behind=0 とするための ours マージ記録。

取り込み済み 13 commits:
- 1f55c62 Fix host service restart adoption (superset-sh#3732)
- 0fe65d2 test(desktop): remove host-service-coordinator test (superset-sh#3734)
- 3012b5a Add optimistic Electric collection updates (superset-sh#3722)
- c272a51 fix(desktop): drop branch row from v2 sidebar workspace item (superset-sh#3733)
- c2f3fdc feat(desktop): add fade-edge mask utilities (superset-sh#3735)
- 682d07c fix v2 terminal osc links (superset-sh#3736)
- 7c0d22b feat(ports): surface remote host-service ports in the sidebar (superset-sh#3676)
- 6a3be2d [codex] Stabilize v2 terminal resize (superset-sh#3739)
- 8928ac6 [codex] Improve v2 pane header responsiveness (superset-sh#3737)
- 5fe3d22 refactor(desktop): tidy v2 terminal session dropdown (superset-sh#3743)
- 66c23d6 Fix automation timezone scheduling (superset-sh#3738)
- 16e270c [codex] Add terminal session titles (superset-sh#3740)
- 583fa5d fix(desktop): refit v2 terminal after font settle (superset-sh#3742)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants