Browse Source

feat(desktop): optimistic prompt submit

Adam 2 months ago
parent
commit
b4209582fb

+ 20 - 5
packages/desktop/src/components/prompt-input.tsx

@@ -709,13 +709,28 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
       }
     }
 
+    const model = {
+      modelID: local.model.current()!.id,
+      providerID: local.model.current()!.provider.id,
+    }
+    const agent = local.agent.current()!.name
+
+    sync.session.addOptimisticMessage({
+      sessionID: existing.id,
+      text,
+      parts: [
+        { type: "text", text } as import("@opencode-ai/sdk/v2/client").Part,
+        ...(fileAttachmentParts as import("@opencode-ai/sdk/v2/client").Part[]),
+        ...(imageAttachmentParts as import("@opencode-ai/sdk/v2/client").Part[]),
+      ],
+      agent,
+      model,
+    })
+
     sdk.client.session.prompt({
       sessionID: existing.id,
-      agent: local.agent.current()!.name,
-      model: {
-        modelID: local.model.current()!.id,
-        providerID: local.model.current()!.provider.id,
-      },
+      agent,
+      model,
       parts: [
         {
           type: "text",

+ 35 - 0
packages/desktop/src/context/sync.tsx

@@ -4,6 +4,7 @@ import { Binary } from "@opencode-ai/util/binary"
 import { createSimpleContext } from "@opencode-ai/ui/context"
 import { useGlobalSync } from "./global-sync"
 import { useSDK } from "./sdk"
+import type { Message, Part } from "@opencode-ai/sdk/v2/client"
 
 export const { use: useSync, provider: SyncProvider } = createSimpleContext({
   name: "Sync",
@@ -30,6 +31,40 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
           if (match.found) return store.session[match.index]
           return undefined
         },
+        addOptimisticMessage(input: {
+          sessionID: string
+          text: string
+          parts: Part[]
+          agent: string
+          model: { providerID: string; modelID: string }
+        }) {
+          const messageID = crypto.randomUUID()
+          const message: Message = {
+            id: messageID,
+            sessionID: input.sessionID,
+            role: "user",
+            time: { created: Date.now() },
+            agent: input.agent,
+            model: input.model,
+          }
+          setStore(
+            produce((draft) => {
+              const messages = draft.message[input.sessionID]
+              if (!messages) {
+                draft.message[input.sessionID] = [message]
+              } else {
+                const result = Binary.search(messages, messageID, (m) => m.id)
+                messages.splice(result.index, 0, message)
+              }
+              draft.part[messageID] = input.parts.map((part, i) => ({
+                ...part,
+                id: `${messageID}-${i}`,
+                sessionID: input.sessionID,
+                messageID,
+              }))
+            }),
+          )
+        },
         async sync(sessionID: string, _isRetry = false) {
           const [session, messages, todo, diff] = await Promise.all([
             sdk.client.session.get({ sessionID }, { throwOnError: true }),