fix(git): materialize draft session for generate (#1761)

* fix(git): materialize draft session for generate

* fix(sync): remove redundant draft session side effects

---------

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
This commit is contained in:
bashrusakh
2026-06-26 11:52:39 +03:00
committed by GitHub
co-authored by Leonid Skorobogatyy
parent b0e476ab7c
commit 03e6f789a4
2 changed files with 149 additions and 70 deletions
+83 -51
View File
@@ -30,6 +30,7 @@ import { markPendingUserSendAnimation } from "@/lib/userSendAnimation"
import { flattenAssistantTextParts } from "@/lib/messages/messageText"
import { composeForkSessionMessage } from "@/lib/messages/executionMeta"
import { waitForPendingDraftWorktreeRequest } from "@/lib/worktrees/pendingDraftWorktree"
import { waitForWorktreeBootstrap } from "@/lib/worktrees/worktreeBootstrap"
import { resolveProjectForSessionDirectory } from "@/lib/projectResolution"
import {
getSyncSessions,
@@ -408,6 +409,75 @@ const writeRuntimeSessionMemory = (key: string, patch: Partial<RuntimeSessionMem
})
}
type MaterializedDraftSession = {
sessionId: string
directory: string | null
agent?: string
syntheticParts?: SyntheticContextPart[]
}
export async function materializeOpenDraftSession(selection: {
providerID: string
modelID: string
agent?: string
variant?: string
}): Promise<MaterializedDraftSession | null> {
const store = useSessionUIStore.getState()
const draft = store.newSessionDraft
if (!draft?.open) return null
const trimmedAgent = typeof selection.agent === "string" && selection.agent.trim().length > 0
? selection.agent.trim()
: undefined
let draftDirectoryOverride = draft.bootstrapPendingDirectory ?? draft.directoryOverride ?? null
const draftProjectId = draft.selectedProjectId ?? null
if (draft.pendingWorktreeRequestId) {
draftDirectoryOverride = await waitForPendingDraftWorktreeRequest(draft.pendingWorktreeRequestId)
store.resolvePendingDraftWorktreeTarget(draft.pendingWorktreeRequestId, draftDirectoryOverride)
}
if (draftDirectoryOverride) {
await waitForWorktreeBootstrap(draftDirectoryOverride)
}
const created = await store.createSession(draft.title, draftDirectoryOverride, draft.parentID ?? null)
if (!created?.id) throw new Error("Failed to create session")
persistDraftTarget({
projectId: draftProjectId,
directory: normalizePath(draftDirectoryOverride ?? created.directory ?? null),
})
const draftSyntheticParts = draft.syntheticParts
const createdDirectory = normalizePath(draftDirectoryOverride ?? created.directory ?? null)
const configState = useConfigStore.getState()
void activateConfigForDirectory(createdDirectory).catch((error) => {
console.warn("Failed to activate directory after creating session:", error)
})
const effectiveDraftAgent = trimmedAgent ?? configState.currentAgentName
useSelectionStore.getState().saveSessionModelSelection(created.id, selection.providerID, selection.modelID)
if (effectiveDraftAgent) {
useSelectionStore.getState().saveSessionAgentSelection(created.id, effectiveDraftAgent)
useSelectionStore.getState().saveAgentModelForSession(created.id, effectiveDraftAgent, selection.providerID, selection.modelID)
useSelectionStore.getState().saveAgentModelVariantForSession(created.id, effectiveDraftAgent, selection.providerID, selection.modelID, selection.variant)
}
store.initializeNewOpenChamberSession(created.id, configState.agents ?? [])
store.setCurrentSession(created.id, createdDirectory)
return {
sessionId: created.id,
directory: createdDirectory,
agent: effectiveDraftAgent,
syntheticParts: draftSyntheticParts,
}
}
// ---------------------------------------------------------------------------
// Store
// ---------------------------------------------------------------------------
@@ -919,59 +989,21 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
// ---- New session from draft ----
if (!options?.sessionId && draft?.open) {
const draftTargetFolderId = draft.targetFolderId
let draftDirectoryOverride = draft.bootstrapPendingDirectory ?? draft.directoryOverride ?? null
const draftProjectId = draft.selectedProjectId ?? null
if (draft.pendingWorktreeRequestId) {
draftDirectoryOverride = await waitForPendingDraftWorktreeRequest(draft.pendingWorktreeRequestId)
get().resolvePendingDraftWorktreeTarget(draft.pendingWorktreeRequestId, draftDirectoryOverride)
}
const created = await get().createSession(draft.title, draftDirectoryOverride, draft.parentID ?? null)
if (!created?.id) throw new Error("Failed to create session")
persistDraftTarget({
projectId: draftProjectId,
directory: normalizePath(draftDirectoryOverride ?? created.directory ?? null),
const createdDraftSession = await materializeOpenDraftSession({
providerID,
modelID,
agent: trimmedAgent,
variant,
})
if (!createdDraftSession) throw new Error("Failed to create session")
const draftSyntheticParts = draft.syntheticParts
const createdDirectory = normalizePath(draftDirectoryOverride ?? created.directory ?? null)
const configState = useConfigStore.getState()
void activateConfigForDirectory(createdDirectory).catch((error) => {
console.warn("Failed to activate directory after creating session:", error)
})
const effectiveDraftAgent = trimmedAgent ?? configState.currentAgentName
useSelectionStore.getState().saveSessionModelSelection(created.id, providerID, modelID)
if (effectiveDraftAgent) {
useSelectionStore.getState().saveSessionAgentSelection(created.id, effectiveDraftAgent)
useSelectionStore.getState().saveAgentModelForSession(created.id, effectiveDraftAgent, providerID, modelID)
useSelectionStore.getState().saveAgentModelVariantForSession(created.id, effectiveDraftAgent, providerID, modelID, variant)
}
get().initializeNewOpenChamberSession(created.id, configState.agents ?? [])
get().closeNewSessionDraft()
get().setCurrentSession(created.id, createdDirectory)
if (draftTargetFolderId) {
const scopeKey = draftDirectoryOverride || created.directory || null
if (scopeKey) {
useSessionFoldersStore.getState().addSessionToFolder(scopeKey, draftTargetFolderId, created.id)
}
}
const mergedAdditionalParts = draftSyntheticParts?.length
? [...(additionalParts || []), ...draftSyntheticParts]
const mergedAdditionalParts = createdDraftSession.syntheticParts?.length
? [...(additionalParts || []), ...createdDraftSession.syntheticParts]
: additionalParts
notifyMessageSent(created.id)
notifyMessageSent(createdDraftSession.sessionId)
markPendingUserSendAnimation(created.id)
markPendingUserSendAnimation(createdDraftSession.sessionId)
const files = attachments?.map((a) => ({
type: "file" as const,
@@ -981,12 +1013,12 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
}))
await routeMessage({
sessionId: created.id,
directory: createdDirectory,
sessionId: createdDraftSession.sessionId,
directory: createdDraftSession.directory,
content,
providerID,
modelID,
agent: effectiveDraftAgent,
agent: createdDraftSession.agent,
agentMentionName,
variant,
inputMode,