Skip to content

fix: preserve per-session input drafts when switching sessions#14267

Open
uriva wants to merge 2 commits intoanomalyco:devfrom
uriva:fix/per-session-input-state
Open

fix: preserve per-session input drafts when switching sessions#14267
uriva wants to merge 2 commits intoanomalyco:devfrom
uriva:fix/per-session-input-state

Conversation

@uriva
Copy link

@uriva uriva commented Feb 19, 2026

Issue for this PR

Closes #14263

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Switching sessions lost or leaked draft input text. This stores drafts in a per-session Map so each session keeps its own input state independently.

Three touch points save/restore drafts: the reactive effect in Prompt when sessionID changes, the "new session" command in app.tsx, and the session list dialog. Drafts are cleared on submit and on session deletion.

How did you verify your code works?

Typecheck passes. Manually tested: type text in session A, switch to session B (text gone, fresh input), switch back to A (text restored), submit (draft cleared). Also verified new session, child session cycling, and session deletion all behave correctly.

Screenshots / recordings

N/A — behavior change only, no visual changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Store each session's draft input in a module-level Map so that
switching between sessions restores the text the user was typing.
Previously, switching sessions either lost the draft or carried it
to the new session.

Closes anomalyco#14263
Copilot AI review requested due to automatic review settings February 19, 2026 10:29
@github-actions github-actions bot added the needs:compliance This means the issue will auto-close after 2 hours. label Feb 19, 2026
@github-actions
Copy link
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search, I found one potentially related PR that may have addressed a similar concern:

Related PR:

This PR (14267) appears to be the primary/only PR specifically focused on preserving per-session input drafts when switching between sessions. The related PR above handles a narrower case (new session creation), while your PR takes a broader approach by storing drafts in a Map for all session switches.

No other duplicate PRs found for the specific feature of preserving input drafts across session switches.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds per-session draft preservation for the TUI prompt so that switching between sessions (and navigating via dialogs/commands) no longer loses or leaks the input buffer between sessions.

Changes:

  • Introduces a module-level drafts: Map<string, PromptInfo> to persist drafts keyed by session ID.
  • Saves the current session’s draft on session switch / navigation, and restores the target session’s draft (or clears the prompt if none exists).
  • Clears the stored draft for a session on submit to avoid resurrecting already-sent prompts.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx Adds the per-session drafts map and session-change effect to save/restore prompt drafts; clears draft on submit.
packages/opencode/src/cli/cmd/tui/app.tsx Updates the “New session” command to save the current session draft into drafts instead of passing it to the home route.
packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx Saves the current session draft before navigating to the selected session from the session list dialog.
Comments suppressed due to low confidence (1)

packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx:171

  • The session-switch effect is deferred, so it won’t run on initial mount. This means drafts saved in drafts won’t be restored when (re)entering a session via route navigation that remounts Prompt (e.g., session -> home -> session), and the draft will appear lost. Consider running this logic on mount as well (e.g., remove defer: true and use the prev value provided by on() to only save when prevSessionID is defined, while always restoring for nextSessionID).
  let previousSessionID: string | undefined = props.sessionID
  createEffect(
    on(
      () => props.sessionID,
      (nextSessionID) => {
        // Save current draft for the previous session
        if (previousSessionID && store.prompt.input) {
          drafts.set(previousSessionID, { input: store.prompt.input, parts: [...store.prompt.parts] })
        } else if (previousSessionID) {
          drafts.delete(previousSessionID)
        }

        // Restore draft for the new session or clear
        const draft = nextSessionID ? drafts.get(nextSessionID) : undefined
        if (draft) {
          input.setText(draft.input)
          setStore("prompt", { input: draft.input, parts: draft.parts })
          restoreExtmarksFromParts(draft.parts)
          input.gotoBufferEnd()
        } else {
          input.clear()
          input.extmarks.clear()
          setStore("prompt", { input: "", parts: [] })
          setStore("extmarkToPartIndex", new Map())
        }

        previousSessionID = nextSessionID
        setStore("placeholder", Math.floor(Math.random() * PLACEHOLDERS.length))
      },
      { defer: true },
    ),

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

setStore("prompt", { input: "", parts: [] })
setStore("extmarkToPartIndex", new Map())
}

Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

On session switch, store.mode is not reset/restored. If the user is in shell mode in one session and switches sessions, the new session can inherit shell mode and submit the restored/empty input via sdk.client.session.shell(...) unexpectedly. Consider resetting mode to normal when changing sessions (or persisting/restoring mode per session along with the draft).

Suggested change
// Reset mode on session change to avoid inheriting modes like "shell"
setStore("mode", "normal")

Copilot uses AI. Check for mistakes.
const currentPrompt = current?.current?.input ? current.current : undefined
// Save draft for the current session instead of carrying it to home
if (current?.current?.input && route.data.type === "session") {
drafts.set(route.data.sessionID, { input: current.current.input, parts: [...current.current.parts] })
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

When navigating to home via “New session”, this only drafts.set(...) when there is input, but never clears an existing draft when the prompt was emptied. If the user cleared the input and then triggers “New session”, the stale draft for that session will remain in drafts and be restored later. Mirror the session-switch behavior by drafts.delete(route.data.sessionID) when there’s no input (and only when route.data.type === "session").

Suggested change
drafts.set(route.data.sessionID, { input: current.current.input, parts: [...current.current.parts] })
drafts.set(route.data.sessionID, { input: current.current.input, parts: [...current.current.parts] })
} else if (route.data.type === "session") {
// Clear any stale draft when there is no current input
drafts.delete(route.data.sessionID)

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +15
import { usePromptRef } from "../context/prompt"
import { drafts } from "./prompt"
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

With drafts now imported/used here, session deletion in this dialog (the delete keybind handler below) should also clear any saved draft for the deleted session. Otherwise drafts for deleted sessions can accumulate and potentially be restored later if the ID is referenced again.

Copilot uses AI. Check for mistakes.
- Reset mode to normal on session switch to prevent shell mode leaking
- Delete stale drafts when input is empty in 'New session' handler
- Clear draft when a session is deleted from session list dialog
- Remove defer:true and use on() prev arg so drafts restore on remount
@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Feb 19, 2026
@github-actions
Copy link
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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.

Input text should be per-session: switching sessions should not carry over or lose draft text

1 participant

Comments