summaryrefslogtreecommitdiffhomepage
path: root/packages/desktop/src
diff options
context:
space:
mode:
authorAdam <[email protected]>2025-10-31 10:08:24 -0500
committerAdam <[email protected]>2025-10-31 10:08:24 -0500
commita8bf1ad40f9aa48c8207d92ce3fee794f9d38279 (patch)
treeb5ff27faa0610af0e74b48b20ce84ab1615ba9da /packages/desktop/src
parent0ac943de909fb5a685a608d7894248cdd3a9e129 (diff)
downloadopencode-a8bf1ad40f9aa48c8207d92ce3fee794f9d38279.tar.gz
opencode-a8bf1ad40f9aa48c8207d92ce3fee794f9d38279.zip
wip: desktop work
Diffstat (limited to 'packages/desktop/src')
-rw-r--r--packages/desktop/src/context/sync.tsx5
-rw-r--r--packages/desktop/src/pages/index.tsx58
2 files changed, 34 insertions, 29 deletions
diff --git a/packages/desktop/src/context/sync.tsx b/packages/desktop/src/context/sync.tsx
index ce2fa1ea4..c60206b0b 100644
--- a/packages/desktop/src/context/sync.tsx
+++ b/packages/desktop/src/context/sync.tsx
@@ -124,7 +124,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/")
const sanitizePart = (part: Part) => {
if (part.type === "tool") {
- if (part.state.status === "completed") {
+ if (part.state.status === "completed" || part.state.status === "error") {
for (const key in part.state.metadata) {
if (typeof part.state.metadata[key] === "string") {
part.state.metadata[key] = sanitize(part.state.metadata[key] as string)
@@ -135,6 +135,9 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
part.state.input[key] = sanitize(part.state.input[key] as string)
}
}
+ if ("error" in part.state) {
+ part.state.error = sanitize(part.state.error as string)
+ }
}
}
return part
diff --git a/packages/desktop/src/pages/index.tsx b/packages/desktop/src/pages/index.tsx
index 01fe4b508..5b2f4ecc1 100644
--- a/packages/desktop/src/pages/index.tsx
+++ b/packages/desktop/src/pages/index.tsx
@@ -53,10 +53,11 @@ export default function Page() {
const [activeItem, setActiveItem] = createSignal<string | undefined>(undefined)
createEffect(() => {
- if (!local.session.activeMessage()) return
- if (!messageScrollElement) return
- const element = messageScrollElement.querySelector(`[data-message="${local.session.activeMessage()?.id}"]`)
- element?.scrollIntoView({ block: "start", behavior: "instant" })
+ // Set first message as active if none selected
+ const userMessages = local.session.userMessages()
+ if (userMessages.length > 0 && !local.session.activeMessage()) {
+ local.session.setActiveMessage(userMessages[0].id)
+ }
})
const MOD = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) ? "Meta" : "Control"
@@ -567,28 +568,29 @@ export default function Page() {
</ul>
</Show>
<div ref={messageScrollElement} class="grow min-w-0 h-full overflow-y-auto no-scrollbar">
- <div class="flex flex-col items-start gap-50 pb-50">
- <For each={local.session.userMessages()}>
- {(message) => {
- const [initialized, setInitialized] = createSignal(!!message.summary?.title)
- const [expanded, setExpanded] = createSignal(false)
- const parts = createMemo(() => sync.data.part[message.id])
- const title = createMemo(() => message.summary?.title)
- const summary = createMemo(() => message.summary?.body)
- const assistantMessages = createMemo(() => {
- return sync.data.message[activeSession().id]?.filter(
- (m) => m.role === "assistant" && m.parentID == message.id,
- ) as AssistantMessageType[]
- })
- const working = createMemo(() => !summary())
- createEffect(() => {
- setTimeout(() => setInitialized(!!title()), 10_000)
- })
-
- return (
+ <For each={local.session.userMessages()}>
+ {(message) => {
+ const isActive = createMemo(() => local.session.activeMessage()?.id === message.id)
+ const [initialized, setInitialized] = createSignal(!!message.summary?.title)
+ const [expanded, setExpanded] = createSignal(false)
+ const parts = createMemo(() => sync.data.part[message.id])
+ const title = createMemo(() => message.summary?.title)
+ const summary = createMemo(() => message.summary?.body)
+ const assistantMessages = createMemo(() => {
+ return sync.data.message[activeSession().id]?.filter(
+ (m) => m.role === "assistant" && m.parentID == message.id,
+ ) as AssistantMessageType[]
+ })
+ const working = createMemo(() => !summary())
+ createEffect(() => {
+ setTimeout(() => setInitialized(!!title()), 10_000)
+ })
+
+ return (
+ <Show when={isActive()}>
<div
data-message={message.id}
- class="flex flex-col items-start self-stretch gap-8 min-h-screen"
+ class="flex flex-col items-start self-stretch gap-8 pb-50"
>
{/* Title */}
<div class="py-2 flex flex-col items-start gap-2 self-stretch sticky top-0 bg-background-stronger z-10">
@@ -774,10 +776,10 @@ export default function Page() {
</Switch>
</div>
</div>
- )
- }}
- </For>
- </div>
+ </Show>
+ )
+ }}
+ </For>
</div>
</div>
</div>