| author | |
| committer | |
| log | 5c0429b1578cff3307c35c51a305e2749a6dcb6e |
| tree | 349553ce589d70d4ceadf843bf4142914404dafb |
| parent | 5bf19d12b0fd54fc9999579869bcf264bc555874 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>7 files changed, 36 insertions(+), 6 deletions(-)
apps/web/src/components/ChatView.tsx+14-1| ... | ... | @@ -8511,6 +8511,11 @@ export default function ChatView(props: ChatViewProps) { |
| 8511 | 8511 | setComposerDraftThreadContexts(composerDraftTarget, [...records]), |
| 8512 | 8512 | resetCursor: (options) => composerRef.current?.resetCursorState(options), |
| 8513 | 8513 | }); |
| 8514 | } else if ( | |
| 8515 | submissionIntent === "background" && | |
| 8516 | currentRouteThreadKeyRef.current === routeThreadKey | |
| 8517 | ) { | |
| 8518 | handleNewThreadInActiveProject(); | |
| 8514 | 8519 | } |
| 8515 | 8520 | return; |
| 8516 | 8521 | } |
| ... | ... | @@ -8743,7 +8748,9 @@ export default function ChatView(props: ChatViewProps) { |
| 8743 | 8748 | } |
| 8744 | 8749 | beginLocalDispatch({ |
| 8745 | 8750 | preparingWorktree: multipleModelSelections !== null || Boolean(baseBranchForWorktree), |
| 8746 | submissionIntent, | |
| 8751 | // Only a draft has a background submission to hide behind its hero. | |
| 8752 | submissionIntent: | |
| 8753 | submissionIntent === "background" && !isLocalDraftThread ? "foreground" : submissionIntent, | |
| 8747 | 8754 | }); |
| 8748 | 8755 | setWorktreeSetupRef( |
| 8749 | 8756 | multipleModelSelections === null && baseBranchForWorktree |
| ... | ... | @@ -9316,6 +9323,12 @@ export default function ChatView(props: ChatViewProps) { |
| 9316 | 9323 | }), |
| 9317 | 9324 | ); |
| 9318 | 9325 | } |
| 9326 | } else if ( | |
| 9327 | submissionIntent === "background" && | |
| 9328 | currentRouteThreadKeyRef.current === routeThreadKey | |
| 9329 | ) { | |
| 9330 | // An existing thread keeps running; open a fresh composer like a draft does. | |
| 9331 | handleNewThreadInActiveProject(); | |
| 9319 | 9332 | } |
| 9320 | 9333 | } |
| 9321 | 9334 | } |
apps/web/src/components/settings/KeybindingsSettings.logic.ts+1| ... | ... | @@ -314,6 +314,7 @@ export function buildKeybindingCommandOptions( |
| 314 | 314 | export function commandLabel(command: KeybindingCommand): string { |
| 315 | 315 | if (command === "composer.sendAlternate") return "Composer: Opposite Queue or Steer Action"; |
| 316 | 316 | if (command === "composer.sendBackground") return "Composer: Start in Background"; |
| 317 | if (command === "composer.sendAndNewThread") return "Composer: Send and Start New Thread"; | |
| 317 | 318 | if (command === "thread.steerQueuedMessage") return "Queue: Send First Queued Message as Steer"; |
| 318 | 319 | if (command === "thread.editQueuedMessage") return "Queue: Edit Last Queued Message"; |
| 319 | 320 | if (command === "thread.copyReference") return "Pull Request: Copy Link or Thread ID"; |
apps/web/src/composer-logic.test.ts+8| ... | ... | @@ -124,6 +124,14 @@ describe("composerSubmissionIntentForKey", () => { |
| 124 | 124 | event: { ...modEnter, altKey: true }, |
| 125 | 125 | }), |
| 126 | 126 | ).toBe("background"); |
| 127 | expect( | |
| 128 | composerSubmissionIntentForKey({ | |
| 129 | ...input, | |
| 130 | platform, | |
| 131 | sendShortcut, | |
| 132 | event: { ...modEnter, altKey: true }, | |
| 133 | }), | |
| 134 | ).toBe("background"); | |
| 127 | 135 | expect( |
| 128 | 136 | composerSubmissionIntentForKey({ |
| 129 | 137 | ...input, |
apps/web/src/composer-logic.ts+1| ... | ... | @@ -59,6 +59,7 @@ export function composerSubmissionIntentForKey(input: { |
| 59 | 59 | }); |
| 60 | 60 | if (command === "composer.sendAlternate" && input.isRunning) return "alternate"; |
| 61 | 61 | if (command === "composer.sendBackground" && input.isDraftThread) return "background"; |
| 62 | if (command === "composer.sendAndNewThread" && !input.isDraftThread) return "background"; | |
| 62 | 63 | if (command !== null || event.key !== "Enter" || event.shiftKey || event.altKey) return null; |
| 63 | 64 | if ( |
| 64 | 65 | composerRequiresModifier(input.sendShortcut, input.prompt ?? "") && |
docs/user/keybindings.md+6-5| ... | ... | @@ -11,11 +11,12 @@ inserts a new line. This applies to the web and desktop composer at desktop widt |
| 11 | 11 | |
| 12 | 12 | **Follow-up behavior** chooses Queue or Steer while the agent runs. Use |
| 13 | 13 | `mod+Enter` to do the opposite for one message, even when the send shortcut |
| 14 | requires a modifier. In a new thread, `mod+Alt+Enter` starts the thread in the | |
| 15 | background and opens a fresh composer. Change either shortcut in | |
| 16 | **Settings → Keybindings** under **Composer: Opposite Queue or Steer Action** or | |
| 17 | **Composer: Start in Background**. These bindings take priority over the send | |
| 18 | shortcut. Click the send button to use the configured follow-up behavior. | |
| 14 | requires a modifier. `mod+Alt+Enter` sends, keeps that thread running in the | |
| 15 | background, and opens a fresh new-thread composer. Change these | |
| 16 | shortcuts in **Settings → Keybindings** under **Composer: Opposite Queue or | |
| 17 | Steer Action**, **Composer: Start in Background**, or **Composer: Send and Start | |
| 18 | New Thread**. These bindings take priority over the send shortcut. Click the | |
| 19 | send button to use the configured follow-up behavior. | |
| 19 | 20 | |
| 20 | 21 | When an active turn has queued messages, `mod+Shift+Enter` sends the first as a |
| 21 | 22 | steer. Change it under **Queue: Send First Queued Message as Steer** in Keybindings. |
packages/contracts/src/keybindings.ts+1| ... | ... | @@ -87,6 +87,7 @@ export const STATIC_KEYBINDING_COMMANDS = [ |
| 87 | 87 | "composer.stash", |
| 88 | 88 | "composer.sendAlternate", |
| 89 | 89 | "composer.sendBackground", |
| 90 | "composer.sendAndNewThread", | |
| 90 | 91 | "composer.host", |
| 91 | 92 | "composer.effort", |
| 92 | 93 | "composer.mode", |
packages/shared/src/keybindings.ts+5| ... | ... | @@ -53,6 +53,11 @@ export const DEFAULT_KEYBINDINGS: ReadonlyArray<KeybindingRule> = [ |
| 53 | 53 | command: "composer.sendBackground", |
| 54 | 54 | when: "composerFocus && draftThreadRoute", |
| 55 | 55 | }, |
| 56 | { | |
| 57 | key: "mod+alt+enter", | |
| 58 | command: "composer.sendAndNewThread", | |
| 59 | when: "composerFocus && !draftThreadRoute", | |
| 60 | }, | |
| 56 | 61 | { key: "mod+n", command: "chat.new", when: "!terminalFocus" }, |
| 57 | 62 | { key: "mod+shift+o", command: "chat.new", when: "!terminalFocus" }, |
| 58 | 63 | { key: "mod+shift+n", command: "chat.newLocal", when: "!terminalFocus" }, |