fix(desktop): busy state and reactivity

This commit is contained in:
Adam 2025-11-18 11:35:17 -06:00
parent 13f319b64f
commit 333b8e907b
No known key found for this signature in database
GPG key ID: 9CB48779AF150E75
6 changed files with 33 additions and 29 deletions

View file

@ -266,7 +266,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
if (!existing) {
const created = await sdk.client.session.create()
existing = created.data ?? undefined
if (existing) navigate(`${local.slug()}/session/${existing.id}`)
if (existing) navigate(existing.id)
}
if (!existing) return

View file

@ -11,6 +11,7 @@ import type {
Project,
FileDiff,
Todo,
SessionStatus,
} from "@opencode-ai/sdk"
import { createStore, produce, reconcile } from "solid-js/store"
import { Binary } from "@/utils/binary"
@ -25,6 +26,9 @@ type State = {
config: Config
path: Path
session: Session[]
session_status: {
[sessionID: string]: SessionStatus
}
session_diff: {
[sessionID: string]: FileDiff[]
}
@ -68,6 +72,7 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple
agent: [],
provider: [],
session: [],
session_status: {},
session_diff: {},
todo: {},
limit: 10,
@ -108,6 +113,10 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple
case "todo.updated":
setStore("todo", event.properties.sessionID, event.properties.todos)
break
case "session.status": {
setStore("session_status", event.properties.sessionID, event.properties.status)
break
}
case "message.updated": {
const messages = store.message[event.properties.info.sessionID]
if (!messages) {

View file

@ -58,16 +58,13 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex
if (!store.messageId) return lastUserMessage()
return userMessages()?.find((m) => m.id === store.messageId)
})
const working = createMemo(() => {
if (!params.id) return false
const last = lastUserMessage()
if (!last) return false
const assistantMessages = sync.data.message[params.id]?.filter(
(m) => m.role === "assistant" && m.parentID == last?.id,
) as AssistantMessage[]
const error = assistantMessages?.find((m) => m?.error)?.error
return !last?.summary?.body && !error
})
const status = createMemo(
() =>
sync.data.session_status[params.id] ?? {
type: "idle",
},
)
const working = createMemo(() => status()?.type !== "idle")
const cost = createMemo(() => {
const total = pipe(
@ -102,8 +99,11 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex
})
return {
id: params.id,
get id() {
return params.id
},
info,
status,
working,
diffs,
prompt: {

View file

@ -26,6 +26,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
.slice(0, store.limit)
setStore("session", sessions)
}),
status: () => sdk.client.session.status().then((x) => setStore("session_status", x.data!)),
config: () => sdk.client.config.get().then((x) => setStore("config", x.data!)),
changes: () => sdk.client.file.status().then((x) => setStore("changes", x.data!)),
node: () => sdk.client.file.list({ query: { path: "/" } }).then((x) => setStore("node", x.data!)),

View file

@ -14,12 +14,10 @@ export default function Layout(props: ParentProps) {
return sync.data.projects.find((x) => x.worktree === decoded)?.worktree ?? "/"
})
return (
<Show when={params.id || true} keyed>
<SDKProvider directory={directory()}>
<SyncProvider>
<LocalProvider>{props.children}</LocalProvider>
</SyncProvider>
</SDKProvider>
</Show>
<SDKProvider directory={directory()}>
<SyncProvider>
<LocalProvider>{props.children}</LocalProvider>
</SyncProvider>
</SDKProvider>
)
}

View file

@ -378,15 +378,9 @@ export default function Page() {
>
<For each={session.messages.user()}>
{(message) => {
const assistantMessages = createMemo(() => {
if (!session.id) return []
return sync.data.message[session.id]?.filter(
(m) => m.role === "assistant" && m.parentID == message.id,
) as AssistantMessageType[]
})
const error = createMemo(() => assistantMessages().find((m) => m?.error)?.error)
const working = createMemo(() => !message.summary?.body && !error())
const working = createMemo(
() => message.id === session.messages.last()?.id && session.working(),
)
const handleClick = () => session.messages.setActive(message.id)
return (
@ -473,7 +467,9 @@ export default function Page() {
?.flatMap((m) => sync.data.part[m.id])
.some((p) => p?.type === "tool"),
)
const working = createMemo(() => !message.summary?.body && !error())
const working = createMemo(
() => message.id === session.messages.last()?.id && session.working(),
)
// allowing time for the animations to finish
createEffect(() => {