Skip to content

[PR4/5] fix(upstream): v1 split pane 起動時のサイジング修正(ターミナル Session Readiness 機構)(#3416)#162

Merged
MocA-Love merged 1 commit intomainfrom
upstream-merge/pr4-terminal-session-readiness
Apr 14, 2026
Merged

[PR4/5] fix(upstream): v1 split pane 起動時のサイジング修正(ターミナル Session Readiness 機構)(#3416)#162
MocA-Love merged 1 commit intomainfrom
upstream-merge/pr4-terminal-session-readiness

Conversation

@MocA-Love
Copy link
Copy Markdown
Owner

@MocA-Love MocA-Love commented Apr 14, 2026

Upstream Merge PR#4 - Terminal Session Readiness

upstream superset-sh#3416 を cherry-pick し、v1 split pane での preset コマンド実行バグを修正します。

取り込むコミット

Commit Upstream PR 内容
`31fcf191f` superset-sh#3416 [codex] fix v1 split pane startup sizing

改善内容の詳細

何が問題だったか

v1 split pane でプリセットコマンドが正しく実行されない:

  1. ユーザーが workspace で「水平分割」や「垂直分割」を実行
  2. 新しいペインができるが、その pane の DOM マウントとターミナルセッションの attach は非同期
  3. ところが、preset コマンドの実行はこれらを待たずに即座に走っていた
  4. 結果:
    • ターミナルがまだ正しいサイズになる前に `echo hello` が書き込まれ、改行やサイジングが崩れる
    • ひどいケースでは、attach 完了前にコマンドが送られ、完全にスキップされる

背景タブで pane を作る場合は「helper-side attach」経由なので影響なし。フォアグラウンドの split 操作でのみ 発生する race condition でした。

どう直したか

新しい "Session Readiness" 機構を導入:

新規ファイル `lib/terminal/session-readiness.ts`

```typescript
// paneId ごとに「準備完了フラグ」と「待機中の Promise」を管理する module-level state

export function waitForTerminalSessionReady(paneId: string): Promise
// paneId がまだ ready でなければ Promise を返して待つ
// ready なら即座に resolve

export function markTerminalSessionReady(paneId: string): void
// paneId を ready 状態に、待機中の Promise を全て resolve

export function rejectTerminalSessionReady(paneId: string, error: Error): void
// 待機中の Promise を全て reject(attach 失敗時や pane close 時)

export function clearTerminalSessionReady(paneId: string): void
// ready 状態をクリア(再 attach 時)
```

`launch-command.ts` に `waitForMountedSession` オプション追加

```typescript
interface LaunchCommandInPaneOptions {
// ... 既存の項目 ...
/**

  • アクティブタブに即座にマウントされる pane 用。
  • バックグラウンドタブは helper-side attach 経由にすること。
    */
    waitForMountedSession?: boolean;
    }

async function launchCommandInPane(options) {
if (options.waitForMountedSession) {
// session が ready になるまで待機
await waitForTerminalSessionReady(paneId);
await writeCommandInPane({ paneId, command, write, noExecute });
return;
}
// 従来のパス(helper-side attach)
// ...
}
```

`useTerminalLifecycle.ts` で readiness シグナルを発火

Terminal の attach ライフサイクルの適切なタイミングでシグナルを送る:

  1. attach 開始時 → `clearTerminalSessionReady(paneId)`
  2. attach 成功時(`v1TerminalCache.setStreamReady()` 直後)→ `markTerminalSessionReady(paneId)`
  3. attach 失敗時(`TERMINAL_SESSION_KILLED` or その他エラー)→ `rejectTerminalSessionReady(paneId, error)`

`useTabsWithPresets.ts` で split 操作時に `waitForMountedSession: true` を渡す

```typescript
// split 操作時の preset launch
launchPresetCommands(launches, { waitForMountedSession: true });
```

`launchPresetCommand()`, `launchPresetCommands()`, `launchFirstPresetInPane()`, `launchFirstPresetInFocusedPane()` に `options?: { waitForMountedSession?: boolean }` パラメータを追加。

`terminal-cleanup.ts` でクリーンアップ

```typescript
export const killTerminalForPane = (paneId: string): void => {
// pane が close されたときに、まだ待機中の Promise を reject
rejectTerminalSessionReady(
paneId,
new Error("Terminal pane was closed before the session became ready"),
);
electronTrpcClient.terminal.kill.mutate({ paneId }).catch(...);
};
```

これで、ユーザーが session ready 前に pane を close しても、待機中の Promise がリークせず適切に reject されます。

変更ファイル

ファイル 種別 概要
`lib/terminal/session-readiness.ts` 新規 上記の readiness 機構本体
`lib/terminal/launch-command.ts` 変更 `waitForMountedSession` オプション追加
`lib/terminal/launch-command.test.ts` 変更 新規テスト2件追加(mounted-session ready / failure の2パターン)
`Terminal/hooks/useTerminalLifecycle.ts` 変更 3箇所で readiness シグナル発火
`stores/tabs/useTabsWithPresets.ts` 変更 split 系メソッドに `{ waitForMountedSession }` オプション伝播
`stores/tabs/utils/terminal-cleanup.ts` 変更 `killTerminalForPane` で reject 呼び出し

コンフリクト解決

ファイル 解決方針
`launch-command.ts` import を両方統合:`isTerminalAttachCanceledMessage`(フォーク)+ `waitForTerminalSessionReady`(upstream)
`launch-command.test.ts` フォーク独自の "retries once when helper attach is canceled" テストを保持し、upstream の新規テスト2件をその後に追加
`useTerminalLifecycle.ts` auto-merge で3箇所の readiness シグナルがフォークの attach lifecycle 周りに正しく挿入された
`useTabsWithPresets.ts` auto-merge 成功
`terminal-cleanup.ts` auto-merge 成功

フォーク固有機能の保持

  • フォークの `isTerminalAttachCanceledMessage` リトライパス: 引き続き `launchCommandInPane` で使用されている
  • `v1TerminalCache.setStreamReady()`: フォーク独自のストリーム状態管理、維持
  • `TERMINAL_SESSION_KILLED` エラーハンドリング: フォーク独自、維持
  • `markAttachInFlight` / `clearAttachInFlight`: フォーク独自の attach 状態追跡、維持
  • Quit lifecycle(`QuitMode`, `cleanupMainWindowResources`): 影響なし。session readiness のクリーンアップは quit 処理と直交的

ユーザーへのメリット

  1. v1 workspace での split 操作が確実に動作

    • 水平分割・垂直分割で preset コマンドが正しいタイミングで実行される
    • ターミナルサイジングが崩れない
  2. リソースリーク防止

    • pane を session ready 前に close しても、待機中の Promise が適切に reject され、メモリリークしない

テスト結果

  • ✅ `bun run typecheck` パス
  • ✅ `bun run lint` パス
  • ✅ `bun test launch-command.test.ts` - 10 pass, 0 fail(upstream 新規テスト2件を含む)

手動テスト計画

  • v1 workspace で preset コマンド付き pane を水平分割 → preset コマンドが正常に実行され、サイジング正常
  • v1 workspace で preset コマンド付き pane を垂直分割 → 同上
  • バックグラウンドタブで preset 実行(helper-side attach 経由)は影響なし
  • Session ready 前に pane を close → pending promise が適切に reject される(リークなし)
  • PR#1 で入ったターミナルクリップボード機能は引き続き動作

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 14, 2026

Warning

Rate limit exceeded

@MocA-Love has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 50 minutes and 36 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 50 minutes and 36 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: bf522f48-d6b7-4da1-8609-4c4e2b31f9a9

📥 Commits

Reviewing files that changed from the base of the PR and between e302ab1 and 2656d14.

📒 Files selected for processing (6)
  • apps/desktop/src/renderer/lib/terminal/launch-command.test.ts
  • apps/desktop/src/renderer/lib/terminal/launch-command.ts
  • apps/desktop/src/renderer/lib/terminal/session-readiness.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts
  • apps/desktop/src/renderer/stores/tabs/useTabsWithPresets.ts
  • apps/desktop/src/renderer/stores/tabs/utils/terminal-cleanup.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch upstream-merge/pr4-terminal-session-readiness

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.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f2486d5b26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

},
);
launchPresetCommands(launches);
launchPresetCommands(launches, { waitForMountedSession: true });
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Stop deferring preset launch for non-visible active tabs

Passing waitForMountedSession: true here makes launchCommandInPane skip createOrAttach and wait for markTerminalSessionReady, which is only emitted by useTerminalLifecycle after the pane is mounted. That works for the currently rendered tab, but openPreset(..., { target: "active-tab" }) is also invoked from background setup flows (e.g. workspace init), where the workspace tab can exist without being mounted; in that case the promise never resolves and the preset command is never sent. Please keep helper-side attach for these active-tab preset paths unless visibility/mount is guaranteed.

Useful? React with 👍 / 👎.

@MocA-Love MocA-Love changed the title fix(upstream): v1 split pane startup sizing via terminal session readiness (#3416) fix(upstream): v1 split pane 起動時のサイジング修正(ターミナル Session Readiness 機構)(#3416) Apr 14, 2026
@MocA-Love MocA-Love changed the title fix(upstream): v1 split pane 起動時のサイジング修正(ターミナル Session Readiness 機構)(#3416) [PR4/5] fix(upstream): v1 split pane 起動時のサイジング修正(ターミナル Session Readiness 機構)(#3416) Apr 14, 2026
* fix v1 split pane startup sizing

* Handle background
@MocA-Love MocA-Love force-pushed the upstream-merge/pr4-terminal-session-readiness branch from f2486d5 to 2656d14 Compare April 14, 2026 17:44
@MocA-Love MocA-Love merged commit c4cdc8b into main Apr 14, 2026
6 checks passed
MocA-Love pushed a commit that referenced this pull request Apr 14, 2026
All 9 upstream commits have been individually cherry-picked via PR#159~#163:

| Upstream | Our PR | Description |
|---|---|---|
| d656b7e (superset-sh#3415) | #159 (PR#1) | terminal clipboard handling |
| 31fcf19 (superset-sh#3416) | #162 (PR#4) | v1 split pane startup sizing fix |
| 039edf2 (superset-sh#3403) | #161 (PR#3) | Cmd+Alt+Arrow spatial pane focus |
| b18a00c (superset-sh#3421) | #159 (PR#1) | v2 right sidebar toggle reactive |
| 3dd1de2 (superset-sh#3420) | #161 (PR#3) | v2 diff viewer + tab title resolution |
| b42a114 (superset-sh#3418) | #159 (PR#1) | CodeMirror hotkey enablement |
| c925f4d (superset-sh#3422) | #160 (PR#2) | unbound defaults + restore prev/next tab/workspace |
| bb12c09 (superset-sh#3419) | #163 (PR#5) | version bump 1.5.3 |
| 47efa73 (superset-sh#3432) | #159 (PR#1) | pending/update-required error selectable |

Fork-specific features preserved:
- auto-updater (IS_FORK, GitHub Releases API)
- QuitMode/cleanupMainWindowResources lifecycle
- GitHubSyncService, SpreadsheetViewer
- BROWSER_RELOAD / BROWSER_HARD_RELOAD / SEARCH_IN_FILES hotkeys
- HotkeyCategory "Browser"
- v1 deep-link navigation (useSearch/WorkspaceSearchParams)
- v1 tRPC-based PREV/NEXT_WORKSPACE handlers
- v1 CLOSE_TERMINAL/CLOSE_TAB hotkey handlers
- v2 extra state (rightSidebarOpenViewWidth, showPresetsBar)
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