feat(chat): turn /btw into an isolated composer (#3398)

* feat(chat): turn /btw into an isolated composer

* fix(chat): preserve direct BTW sends and isolate pending preparation

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
ChangeHow
2026-09-07 23:13:07 +03:00
committed by GitHub
co-authored by Bohdan Triapitsyn
parent 7b206b1014
commit 02581d08c5
38 changed files with 1227 additions and 311 deletions
+18
View File
@@ -120,6 +120,11 @@ export type SyntheticContextPart = {
metadata?: ContextPartMetadata
}
type PendingBtwComposerRequest = {
parentSessionId: string
text: string
}
export type VSCodeActiveEditorFile = {
filePath: string
fileName: string
@@ -144,6 +149,7 @@ export type InputState = {
* narrow layouts); consumed by ChatInput, which owns the command-aware submit.
*/
pendingPresetSubmit: { text: string; type: "command" | "skill" } | null
pendingBtwComposerRequest: PendingBtwComposerRequest | null
attachedFiles: AttachedFile[]
activeEditorFile: VSCodeActiveEditorFile | null
@@ -151,6 +157,8 @@ export type InputState = {
consumePendingInputText: () => { text: string; mode: "replace" | "append" | "append-inline" } | null
requestPresetSubmit: (text: string, type: "command" | "skill") => void
consumePendingPresetSubmit: () => { text: string; type: "command" | "skill" } | null
requestBtwComposer: (request: PendingBtwComposerRequest) => void
consumePendingBtwComposerRequest: (parentSessionId: string | null) => PendingBtwComposerRequest | null
setPendingSyntheticParts: (parts: SyntheticContextPart[] | null) => void
consumePendingSyntheticParts: () => SyntheticContextPart[] | null
addAttachedFile: (file: File) => Promise<boolean>
@@ -176,6 +184,7 @@ export const useInputStore = create<InputState>()((set, get) => ({
pendingInputMode: "replace",
pendingSyntheticParts: null,
pendingPresetSubmit: null,
pendingBtwComposerRequest: null,
attachedFiles: [],
activeEditorFile: null,
@@ -198,6 +207,15 @@ export const useInputStore = create<InputState>()((set, get) => ({
return pendingPresetSubmit
},
requestBtwComposer: (request) => set({ pendingBtwComposerRequest: request }),
consumePendingBtwComposerRequest: (parentSessionId) => {
const request = get().pendingBtwComposerRequest
if (!request || request.parentSessionId !== parentSessionId) return null
set({ pendingBtwComposerRequest: null })
return request
},
setPendingSyntheticParts: (parts) => set({ pendingSyntheticParts: parts }),
consumePendingSyntheticParts: () => {