fix(chat): pin existing-session sends to captured target (#2424)

* fix(chat): pin sends to captured session

* fix(chat): handle runtime cancellation consistently
This commit is contained in:
Wsyjq
2026-08-07 00:46:21 +03:00
committed by GitHub
parent 834d2edb87
commit 70226149ce
10 changed files with 222 additions and 31 deletions
+23 -4
View File
@@ -122,6 +122,7 @@ export function expandSlashCommandGoalObjective(content: string, commands: GoalC
// ---------------------------------------------------------------------------
export function routeMessage(params: {
runtimeKey?: string
sessionId: string
directory?: string | null
content: string
@@ -138,6 +139,7 @@ export function routeMessage(params: {
const requestDirectory = params.directory ?? undefined
if (params.inputMode === "shell") {
return opencodeClient.shellSession({
runtimeKey: params.runtimeKey,
sessionId: params.sessionId,
directory: requestDirectory,
agent: params.agent ?? "",
@@ -166,6 +168,7 @@ export function routeMessage(params: {
if (isCommand) {
return optimisticSend({
runtimeKey: params.runtimeKey,
sessionId: params.sessionId,
content: params.content,
providerID: params.providerID,
@@ -174,6 +177,7 @@ export function routeMessage(params: {
directory: requestDirectory,
files: params.files,
send: (messageID) => opencodeClient.sendCommand({
runtimeKey: params.runtimeKey,
id: params.sessionId,
providerID: params.providerID,
modelID: params.modelID,
@@ -191,6 +195,7 @@ export function routeMessage(params: {
// Normal prompt — optimistic insert so message appears instantly
return optimisticSend({
runtimeKey: params.runtimeKey,
sessionId: params.sessionId,
content: params.content,
providerID: params.providerID,
@@ -199,6 +204,7 @@ export function routeMessage(params: {
directory: requestDirectory,
files: params.files,
send: (messageID) => opencodeClient.sendMessage({
runtimeKey: params.runtimeKey,
id: params.sessionId,
providerID: params.providerID,
modelID: params.modelID,
@@ -215,7 +221,14 @@ export function routeMessage(params: {
})
}
type CapturedSendTarget = {
runtimeKey: string
sessionId: string
directory: string
}
type SendMessageOptions = {
target?: CapturedSendTarget
sessionId?: string
directory?: string
delivery?: 'steer'
@@ -1198,8 +1211,13 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
inputMode?: "normal" | "shell",
options?: SendMessageOptions,
) => {
const capturedTarget = options?.target
if (capturedTarget && capturedTarget.runtimeKey !== getRuntimeKey()) {
throw new Error("Message was not sent because the runtime changed.")
}
// Clear non-Git changed-files bar on new user message for current session
const sid = options?.sessionId ?? get().currentSessionId;
const sid = capturedTarget?.sessionId ?? options?.sessionId ?? get().currentSessionId;
if (sid) {
const map = new Map(get().pendingChangesBarDismissed);
map.delete(sid);
@@ -1258,7 +1276,7 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
}
// ---- New session from draft ----
if (!options?.sessionId && draft?.open) {
if (!capturedTarget && !options?.sessionId && draft?.open) {
const createdDraftSession = await materializeOpenDraftSession({
providerID,
modelID,
@@ -1310,7 +1328,7 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
}
// ---- Existing session ----
const targetSessionId = options?.sessionId ?? get().currentSessionId
const targetSessionId = capturedTarget?.sessionId ?? options?.sessionId ?? get().currentSessionId
const sessionAgentSelection = targetSessionId
? useSelectionStore.getState().getSessionAgentSelection(targetSessionId)
: null
@@ -1345,7 +1363,7 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
}
const currentSessionDirectory = targetSessionId
? normalizePath(options?.directory ?? get().getDirectoryForSession(targetSessionId))
? normalizePath(capturedTarget?.directory ?? options?.directory ?? get().getDirectoryForSession(targetSessionId))
: null
if (targetSessionId) {
notifyMessageSent(targetSessionId)
@@ -1366,6 +1384,7 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
await applyArmedGoal(targetSessionId, currentSessionDirectory)
}
await routeMessage({
runtimeKey: capturedTarget?.runtimeKey,
sessionId: targetSessionId || "",
directory: currentSessionDirectory,
content,