فهرست منبع

fix(app): sync session selection before prompts

Brendan Allan 6 روز پیش
والد
کامیت
d06546b7ea

+ 35 - 2
packages/app/src/components/prompt-input/submit.test.ts

@@ -31,6 +31,12 @@ const promotedDrafts: Array<{ draftID: string; server: string; sessionId: string
 const sentPrompts: string[] = []
 const promptInputs: unknown[] = []
 const sentCommands: unknown[] = []
+const switchedAgents: Array<{ sessionID: string; agent: string }> = []
+const switchedModels: Array<{
+  sessionID: string
+  model: { id: string; providerID: string; variant?: string }
+}> = []
+const sessionRequestOrder: string[] = []
 const commands: Array<{ name: string }> = []
 let serverSessionSyncs = 0
 
@@ -93,10 +99,22 @@ const clientFor = (directory: string) => {
           }
         },
         prompt: async (input: unknown) => {
+          sessionRequestOrder.push("prompt")
           sentPrompts.push(directory)
           promptInputs.push(input)
           return { data: undefined }
         },
+        switchAgent: async (input: { sessionID: string; agent: string }) => {
+          sessionRequestOrder.push("agent")
+          switchedAgents.push(input)
+        },
+        switchModel: async (input: {
+          sessionID: string
+          model: { id: string; providerID: string; variant?: string }
+        }) => {
+          sessionRequestOrder.push("model")
+          switchedModels.push(input)
+        },
         command: async (input: unknown) => {
           sentCommands.push(input)
         },
@@ -279,6 +297,9 @@ beforeEach(() => {
   sentPrompts.length = 0
   promptInputs.length = 0
   sentCommands.length = 0
+  switchedAgents.length = 0
+  switchedModels.length = 0
+  sessionRequestOrder.length = 0
   commands.length = 0
   promptValue = [{ type: "text", content: "ls", start: 0, end: 2 }]
   params = {}
@@ -436,13 +457,17 @@ describe("prompt submit worktree selection", () => {
     expect(promotedDrafts).toEqual([{ draftID: "draft-1", server: "project-server", sessionId: "session-1" }])
   })
 
-  test("includes the selected variant on optimistic prompts", async () => {
+  test("switches the selected agent and model before prompting", async () => {
     params = { id: "session-1" }
     variant = "high"
 
     const submit = createPromptSubmit({
       prompt,
-      info: () => ({ id: "session-1" }),
+      info: () => ({
+        id: "session-1",
+        agent: "old-agent",
+        model: { id: "old-model", providerID: "old-provider" },
+      }),
       imageAttachments: () => [],
       commentCount: () => 0,
       autoAccept: () => false,
@@ -471,6 +496,14 @@ describe("prompt submit worktree selection", () => {
       },
     })
     expect(sentPrompts).toEqual(["/repo/main"])
+    expect(switchedAgents).toEqual([{ sessionID: "session-1", agent: "agent" }])
+    expect(switchedModels).toEqual([
+      {
+        sessionID: "session-1",
+        model: { id: "model", providerID: "provider", variant: "high" },
+      },
+    ])
+    expect(sessionRequestOrder).toEqual(["agent", "model", "prompt"])
     expect(promptInputs[0]).toMatchObject({
       sessionID: "session-1",
       text: "ls",

+ 24 - 1
packages/app/src/components/prompt-input/submit.ts

@@ -45,6 +45,7 @@ type FollowupSendInput = {
   api: DirectorySDK["api"]["session"]
   serverSync: ServerSync
   sync: DirectorySync
+  session: Accessor<{ agent?: string; model?: { id: string; providerID: string; variant?: string } } | undefined>
   draft: FollowupDraft
   messageID?: string
   optimisticBusy?: boolean
@@ -157,6 +158,25 @@ export async function sendFollowupDraft(input: FollowupSendInput) {
       return false
     }
 
+    const session = input.session()
+    if (session?.agent !== input.draft.agent) {
+      await input.api.switchAgent({ sessionID: input.draft.sessionID, agent: input.draft.agent })
+    }
+    if (
+      session?.model?.providerID !== input.draft.model.providerID ||
+      session.model.id !== input.draft.model.modelID ||
+      (session.model.variant ?? "default") !== (input.draft.variant ?? "default")
+    ) {
+      await input.api.switchModel({
+        sessionID: input.draft.sessionID,
+        model: {
+          id: input.draft.model.modelID,
+          providerID: input.draft.model.providerID,
+          variant: input.draft.variant,
+        },
+      })
+    }
+
     await input.api.prompt({
       sessionID: input.draft.sessionID,
       id: messageID,
@@ -197,7 +217,9 @@ export async function sendFollowupDraft(input: FollowupSendInput) {
 
 type PromptSubmitInput = {
   prompt: ReturnType<typeof usePrompt>
-  info: Accessor<{ id: string } | undefined>
+  info: Accessor<
+    { id: string; agent?: string; model?: { id: string; providerID: string; variant?: string } } | undefined
+  >
   imageAttachments: Accessor<ImageAttachmentPart[]>
   commentCount: Accessor<number>
   autoAccept: Accessor<boolean>
@@ -595,6 +617,7 @@ export function createPromptSubmit(input: PromptSubmitInput) {
       api: sdk().api.session,
       sync: sync(),
       serverSync: serverSync(),
+      session: () => input.info() ?? session,
       draft,
       messageID,
       optimisticBusy: sessionDirectory === projectDirectory,

+ 1 - 0
packages/app/src/pages/session.tsx

@@ -1721,6 +1721,7 @@ export default function Page() {
         api: sdk().api.session,
         sync: sync(),
         serverSync: serverSync(),
+        session: () => sync().session.get(input.sessionID),
         draft: item,
         optimisticBusy: item.sessionDirectory === sdk().directory,
       }).catch((err) => {