tui: simplify optimistic prompt reconciliation
This commit is contained in:
parent
f5c770d65e
commit
ebaad55c8c
2 changed files with 30 additions and 27 deletions
|
|
@ -1187,25 +1187,18 @@ export function Prompt(props: PromptProps) {
|
||||||
},
|
},
|
||||||
...nonTextParts.map(assign),
|
...nonTextParts.map(assign),
|
||||||
]
|
]
|
||||||
sync.session.addOptimisticPrompt({
|
const request = {
|
||||||
sessionID,
|
sessionID,
|
||||||
messageID,
|
messageID,
|
||||||
agent: agent.name,
|
agent: agent.name,
|
||||||
model: selectedModel,
|
model: selectedModel,
|
||||||
variant,
|
variant,
|
||||||
parts,
|
parts,
|
||||||
})
|
}
|
||||||
|
sync.session.addOptimisticPrompt(request)
|
||||||
sdk.client.session
|
sdk.client.session
|
||||||
.prompt({
|
.prompt(request)
|
||||||
sessionID,
|
.catch(() => sync.session.removeOptimisticPrompt(request.sessionID, request.messageID))
|
||||||
...selectedModel,
|
|
||||||
messageID,
|
|
||||||
agent: agent.name,
|
|
||||||
model: selectedModel,
|
|
||||||
variant,
|
|
||||||
parts,
|
|
||||||
})
|
|
||||||
.catch(() => sync.session.removeOptimisticPrompt(sessionID, messageID))
|
|
||||||
if (editorParts.length > 0) editor.markSelectionSent()
|
if (editorParts.length > 0) editor.markSelectionSent()
|
||||||
}
|
}
|
||||||
history.append({
|
history.append({
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||||
const kv = useKV()
|
const kv = useKV()
|
||||||
|
|
||||||
const fullSyncedSessions = new Set<string>()
|
const fullSyncedSessions = new Set<string>()
|
||||||
|
const optimisticMessages = new Set<string>()
|
||||||
|
|
||||||
function sessionListQuery(): { scope?: "project"; path?: string } {
|
function sessionListQuery(): { scope?: "project"; path?: string } {
|
||||||
if (!kv.get("session_directory_filter_enabled", true)) return { scope: "project" }
|
if (!kv.get("session_directory_filter_enabled", true)) return { scope: "project" }
|
||||||
|
|
@ -257,6 +258,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||||
}
|
}
|
||||||
|
|
||||||
case "message.updated": {
|
case "message.updated": {
|
||||||
|
optimisticMessages.delete(event.properties.info.id)
|
||||||
const messages = store.message[event.properties.info.sessionID]
|
const messages = store.message[event.properties.info.sessionID]
|
||||||
if (!messages) {
|
if (!messages) {
|
||||||
setStore("message", event.properties.info.sessionID, [event.properties.info])
|
setStore("message", event.properties.info.sessionID, [event.properties.info])
|
||||||
|
|
@ -296,6 +298,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case "message.removed": {
|
case "message.removed": {
|
||||||
|
optimisticMessages.delete(event.properties.messageID)
|
||||||
const messages = store.message[event.properties.sessionID]
|
const messages = store.message[event.properties.sessionID]
|
||||||
const result = Binary.search(messages, event.properties.messageID, (m) => m.id)
|
const result = Binary.search(messages, event.properties.messageID, (m) => m.id)
|
||||||
if (result.found) {
|
if (result.found) {
|
||||||
|
|
@ -532,6 +535,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||||
variant?: string
|
variant?: string
|
||||||
parts: OptimisticPromptPart[]
|
parts: OptimisticPromptPart[]
|
||||||
}) {
|
}) {
|
||||||
|
optimisticMessages.add(input.messageID)
|
||||||
const messages = store.message[input.sessionID]
|
const messages = store.message[input.sessionID]
|
||||||
const match = messages ? Binary.search(messages, input.messageID, (m) => m.id) : undefined
|
const match = messages ? Binary.search(messages, input.messageID, (m) => m.id) : undefined
|
||||||
const info: Message = {
|
const info: Message = {
|
||||||
|
|
@ -552,14 +556,13 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
messageID: input.messageID,
|
messageID: input.messageID,
|
||||||
}
|
}
|
||||||
if (withIDs.type !== "text") return withIDs
|
if (withIDs.type === "file") {
|
||||||
return {
|
return {
|
||||||
...withIDs,
|
...withIDs,
|
||||||
metadata: {
|
url: "",
|
||||||
...withIDs.metadata,
|
}
|
||||||
optimistic: true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
return withIDs
|
||||||
})
|
})
|
||||||
|
|
||||||
batch(() => {
|
batch(() => {
|
||||||
|
|
@ -570,7 +573,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||||
"message",
|
"message",
|
||||||
input.sessionID,
|
input.sessionID,
|
||||||
produce((draft) => {
|
produce((draft) => {
|
||||||
draft.splice(match?.index ?? draft.length, 0, info)
|
Binary.insert(draft, info, (message) => message.id)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -578,12 +581,11 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
removeOptimisticPrompt(sessionID: string, messageID: string) {
|
removeOptimisticPrompt(sessionID: string, messageID: string) {
|
||||||
if (!store.part[messageID]?.some((part) => part.type === "text" && part.metadata?.optimistic === true)) return
|
if (!optimisticMessages.delete(messageID)) return
|
||||||
const messages = store.message[sessionID]
|
const messages = store.message[sessionID]
|
||||||
if (!messages) return
|
const match = messages ? Binary.search(messages, messageID, (m) => m.id) : undefined
|
||||||
const match = Binary.search(messages, messageID, (m) => m.id)
|
|
||||||
batch(() => {
|
batch(() => {
|
||||||
if (match.found) {
|
if (match?.found) {
|
||||||
setStore(
|
setStore(
|
||||||
"message",
|
"message",
|
||||||
sessionID,
|
sessionID,
|
||||||
|
|
@ -611,12 +613,20 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||||
setStore(
|
setStore(
|
||||||
produce((draft) => {
|
produce((draft) => {
|
||||||
const match = Binary.search(draft.session, sessionID, (s) => s.id)
|
const match = Binary.search(draft.session, sessionID, (s) => s.id)
|
||||||
|
const fetched = messages.data!
|
||||||
|
const fetchedIDs = new Set(fetched.map((message) => message.info.id))
|
||||||
|
const optimistic = (draft.message[sessionID] ?? []).filter(
|
||||||
|
(message) => optimisticMessages.has(message.id) && !fetchedIDs.has(message.id),
|
||||||
|
)
|
||||||
if (match.found) draft.session[match.index] = session.data!
|
if (match.found) draft.session[match.index] = session.data!
|
||||||
if (!match.found) draft.session.splice(match.index, 0, session.data!)
|
if (!match.found) draft.session.splice(match.index, 0, session.data!)
|
||||||
draft.todo[sessionID] = todo.data ?? []
|
draft.todo[sessionID] = todo.data ?? []
|
||||||
const infos: (typeof draft.message)[string] = []
|
const infos: (typeof draft.message)[string] = fetched.map((message) => message.info)
|
||||||
for (const message of messages.data ?? []) {
|
for (const message of optimistic) {
|
||||||
infos.push(message.info)
|
Binary.insert(infos, message, (item) => item.id)
|
||||||
|
}
|
||||||
|
for (const message of fetched) {
|
||||||
|
optimisticMessages.delete(message.info.id)
|
||||||
draft.part[message.info.id] = message.parts
|
draft.part[message.info.id] = message.parts
|
||||||
}
|
}
|
||||||
draft.message[sessionID] = infos
|
draft.message[sessionID] = infos
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue