@@ -4,10 +4,6 @@ import type {
44 Provider ,
55 Session ,
66 Part ,
7- TextPartInput ,
8- FilePartInput ,
9- AgentPartInput ,
10- SubtaskPartInput ,
117 Config ,
128 Todo ,
139 Command ,
@@ -36,8 +32,7 @@ import * as Log from "@opencode-ai/core/util/log"
3632import { emptyConsoleState , type ConsoleState } from "@/config/console-state"
3733import path from "path"
3834import { useKV } from "./kv"
39-
40- type OptimisticPromptPart = ( TextPartInput | FilePartInput | AgentPartInput | SubtaskPartInput ) & { id : string }
35+ import { mergeFetchedMessages , optimisticParts , type OptimisticPromptPart } from "./sync-optimistic"
4136
4237export const { use : useSync , provider : SyncProvider } = createSimpleContext ( {
4338 name : "Sync" ,
@@ -226,6 +221,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
226221 break
227222
228223 case "session.deleted" : {
224+ for ( const message of store . message [ event . properties . info . id ] ?? [ ] ) optimisticMessages . delete ( message . id )
229225 const result = Binary . search ( store . session , event . properties . info . id , ( s ) => s . id )
230226 if ( result . found ) {
231227 setStore (
@@ -258,7 +254,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
258254 }
259255
260256 case "message.updated" : {
261- optimisticMessages . delete ( event . properties . info . id )
262257 const messages = store . message [ event . properties . info . sessionID ]
263258 if ( ! messages ) {
264259 setStore ( "message" , event . properties . info . sessionID , [ event . properties . info ] )
@@ -313,6 +308,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
313308 break
314309 }
315310 case "message.part.updated" : {
311+ optimisticMessages . delete ( event . properties . part . messageID )
316312 const parts = store . part [ event . properties . part . messageID ]
317313 if ( ! parts ) {
318314 setStore ( "part" , event . properties . part . messageID , [ event . properties . part ] )
@@ -386,6 +382,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
386382 const workspace = project . workspace . current ( )
387383 if ( workspace !== syncedWorkspace ) {
388384 fullSyncedSessions . clear ( )
385+ optimisticMessages . clear ( )
389386 syncedWorkspace = workspace
390387 }
391388 const projectPromise = project . sync ( )
@@ -544,21 +541,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
544541 ...( input . variant ? { variant : input . variant } : { } ) ,
545542 } ,
546543 }
547- const parts = input . parts . map ( ( part ) : Part => {
548- const withIDs = {
549- ...part ,
550- sessionID : input . sessionID ,
551- messageID : input . messageID ,
552- }
553- if ( withIDs . type === "file" ) {
554- return {
555- ...withIDs ,
556- url : "" ,
557- }
558- }
559- return withIDs
560- } )
561-
562544 batch ( ( ) => {
563545 if ( ! messages ) {
564546 setStore ( "message" , input . sessionID , [ info ] )
@@ -571,7 +553,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
571553 } ) ,
572554 )
573555 }
574- setStore ( "part" , input . messageID , reconcile ( parts ) )
556+ setStore ( "part" , input . messageID , reconcile ( optimisticParts ( input ) ) )
575557 } )
576558 } ,
577559 removeOptimisticPrompt ( sessionID : string , messageID : string ) {
@@ -607,21 +589,21 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
607589 setStore (
608590 produce ( ( draft ) => {
609591 const match = Binary . search ( draft . session , sessionID , ( s ) => s . id )
610- const fetched = messages . data !
611- const fetchedIDs = new Set ( fetched . map ( ( message ) => message . info . id ) )
612- const optimistic = ( draft . message [ sessionID ] ?? [ ] ) . filter (
613- ( message ) => optimisticMessages . has ( message . id ) && ! fetchedIDs . has ( message . id ) ,
614- )
592+ const merged = mergeFetchedMessages ( {
593+ currentMessages : draft . message [ sessionID ] ?? [ ] ,
594+ currentParts : draft . part ,
595+ fetched : messages . data ! ,
596+ optimisticMessages,
597+ } )
615598 if ( match . found ) draft . session [ match . index ] = session . data !
616599 if ( ! match . found ) draft . session . splice ( match . index , 0 , session . data ! )
617600 draft . todo [ sessionID ] = todo . data ?? [ ]
618- draft . message [ sessionID ] = fetched . map ( ( x ) => x . info )
619- for ( const message of optimistic ) {
620- Binary . insert ( draft . message [ sessionID ] , message , ( item ) => item . id )
601+ draft . message [ sessionID ] = merged . messages
602+ for ( const messageID of merged . resolved ) {
603+ optimisticMessages . delete ( messageID )
621604 }
622- for ( const message of fetched ) {
623- optimisticMessages . delete ( message . info . id )
624- draft . part [ message . info . id ] = message . parts
605+ for ( const [ messageID , parts ] of merged . parts ) {
606+ draft . part [ messageID ] = parts
625607 }
626608 draft . session_diff [ sessionID ] = diff . data ?? [ ]
627609 } ) ,
0 commit comments