summaryrefslogtreecommitdiffhomepage
path: root/packages/desktop/src/context
diff options
context:
space:
mode:
authorAdam <[email protected]>2025-12-15 09:34:00 -0600
committerAdam <[email protected]>2025-12-15 10:22:04 -0600
commit5cf6a1343c6ca088bd2b586197faf7fe58961290 (patch)
treed8001631005d2f4791bfe3a0dd3a0b21003a2516 /packages/desktop/src/context
parent44d6c5780d41616bf29a749020c9d7f98895407f (diff)
downloadopencode-5cf6a1343c6ca088bd2b586197faf7fe58961290.tar.gz
opencode-5cf6a1343c6ca088bd2b586197faf7fe58961290.zip
wip(desktop): progress
Diffstat (limited to 'packages/desktop/src/context')
-rw-r--r--packages/desktop/src/context/global-sync.tsx40
-rw-r--r--packages/desktop/src/context/local.tsx2
-rw-r--r--packages/desktop/src/context/prompt.tsx14
3 files changed, 52 insertions, 4 deletions
diff --git a/packages/desktop/src/context/global-sync.tsx b/packages/desktop/src/context/global-sync.tsx
index b90dde34f..bebce64d7 100644
--- a/packages/desktop/src/context/global-sync.tsx
+++ b/packages/desktop/src/context/global-sync.tsx
@@ -100,11 +100,17 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple
async function loadSessions(directory: string) {
globalSDK.client.session.list({ directory }).then((x) => {
- const sessions = (x.data ?? [])
+ const oneHourAgo = Date.now() - 60 * 60 * 1000
+ const nonArchived = (x.data ?? [])
.slice()
.filter((s) => !s.time.archived)
.sort((a, b) => a.id.localeCompare(b.id))
- .slice(0, 5)
+ // Include at least 5 sessions, plus any updated in the last hour
+ const sessions = nonArchived.filter((s, i) => {
+ if (i < 5) return true
+ const updated = new Date(s.time.updated).getTime()
+ return updated > oneHourAgo
+ })
const [, setStore] = child(directory)
setStore("session", sessions)
})
@@ -220,6 +226,21 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple
)
break
}
+ case "message.removed": {
+ const messages = store.message[event.properties.sessionID]
+ if (!messages) break
+ const result = Binary.search(messages, event.properties.messageID, (m) => m.id)
+ if (result.found) {
+ setStore(
+ "message",
+ event.properties.sessionID,
+ produce((draft) => {
+ draft.splice(result.index, 1)
+ }),
+ )
+ }
+ break
+ }
case "message.part.updated": {
const part = event.properties.part
const parts = store.part[part.messageID]
@@ -241,6 +262,21 @@ export const { use: useGlobalSync, provider: GlobalSyncProvider } = createSimple
)
break
}
+ case "message.part.removed": {
+ const parts = store.part[event.properties.messageID]
+ if (!parts) break
+ const result = Binary.search(parts, event.properties.partID, (p) => p.id)
+ if (result.found) {
+ setStore(
+ "part",
+ event.properties.messageID,
+ produce((draft) => {
+ draft.splice(result.index, 1)
+ }),
+ )
+ }
+ break
+ }
}
})
diff --git a/packages/desktop/src/context/local.tsx b/packages/desktop/src/context/local.tsx
index 6ec9778cc..b12679210 100644
--- a/packages/desktop/src/context/local.tsx
+++ b/packages/desktop/src/context/local.tsx
@@ -406,7 +406,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
case "file.watcher.updated":
const relativePath = relative(event.properties.file)
if (relativePath.startsWith(".git/")) return
- load(relativePath)
+ if (store.node[relativePath]) load(relativePath)
break
}
})
diff --git a/packages/desktop/src/context/prompt.tsx b/packages/desktop/src/context/prompt.tsx
index c3b3bbace..2da0a08d5 100644
--- a/packages/desktop/src/context/prompt.tsx
+++ b/packages/desktop/src/context/prompt.tsx
@@ -21,7 +21,15 @@ export interface FileAttachmentPart extends PartBase {
selection?: TextSelection
}
-export type ContentPart = TextPart | FileAttachmentPart
+export interface ImageAttachmentPart {
+ type: "image"
+ id: string
+ filename: string
+ mime: string
+ dataUrl: string
+}
+
+export type ContentPart = TextPart | FileAttachmentPart | ImageAttachmentPart
export type Prompt = ContentPart[]
export const DEFAULT_PROMPT: Prompt = [{ type: "text", content: "", start: 0, end: 0 }]
@@ -38,6 +46,9 @@ export function isPromptEqual(promptA: Prompt, promptB: Prompt): boolean {
if (partA.type === "file" && partA.path !== (partB as FileAttachmentPart).path) {
return false
}
+ if (partA.type === "image" && partA.id !== (partB as ImageAttachmentPart).id) {
+ return false
+ }
}
return true
}
@@ -49,6 +60,7 @@ function cloneSelection(selection?: TextSelection) {
function clonePart(part: ContentPart): ContentPart {
if (part.type === "text") return { ...part }
+ if (part.type === "image") return { ...part }
return {
...part,
selection: cloneSelection(part.selection),