|
@@ -1,7 +1,8 @@
|
|
|
import { createOpencodeClient, type Event } from "@opencode-ai/sdk"
|
|
import { createOpencodeClient, type Event } from "@opencode-ai/sdk"
|
|
|
import { createSimpleContext } from "./helper"
|
|
import { createSimpleContext } from "./helper"
|
|
|
import { createGlobalEmitter } from "@solid-primitives/event-bus"
|
|
import { createGlobalEmitter } from "@solid-primitives/event-bus"
|
|
|
-import { batch, onCleanup } from "solid-js"
|
|
|
|
|
|
|
+import { batch, onCleanup, onMount } from "solid-js"
|
|
|
|
|
+import { iife } from "@/util/iife"
|
|
|
|
|
|
|
|
export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|
export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|
|
name: "SDK",
|
|
name: "SDK",
|
|
@@ -16,43 +17,49 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|
|
[key in Event["type"]]: Extract<Event, { type: key }>
|
|
[key in Event["type"]]: Extract<Event, { type: key }>
|
|
|
}>()
|
|
}>()
|
|
|
|
|
|
|
|
- sdk.event.subscribe().then(async (events) => {
|
|
|
|
|
- let queue: Event[] = []
|
|
|
|
|
- let timer: Timer | undefined
|
|
|
|
|
- let last = 0
|
|
|
|
|
-
|
|
|
|
|
- const flush = () => {
|
|
|
|
|
- if (queue.length === 0) return
|
|
|
|
|
- const events = queue
|
|
|
|
|
- queue = []
|
|
|
|
|
- timer = undefined
|
|
|
|
|
- last = Date.now()
|
|
|
|
|
- // Batch all event emissions so all store updates result in a single render
|
|
|
|
|
- batch(() => {
|
|
|
|
|
- for (const event of events) {
|
|
|
|
|
- emitter.emit(event.type, event)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ onMount(async () => {
|
|
|
|
|
+ while (true) {
|
|
|
|
|
+ if (abort.signal.aborted) break
|
|
|
|
|
+ const events = await sdk.event.subscribe({
|
|
|
|
|
+ signal: abort.signal,
|
|
|
})
|
|
})
|
|
|
- }
|
|
|
|
|
|
|
+ let queue: Event[] = []
|
|
|
|
|
+ let timer: Timer | undefined
|
|
|
|
|
+ let last = 0
|
|
|
|
|
+
|
|
|
|
|
+ const flush = () => {
|
|
|
|
|
+ if (queue.length === 0) return
|
|
|
|
|
+ const events = queue
|
|
|
|
|
+ queue = []
|
|
|
|
|
+ timer = undefined
|
|
|
|
|
+ last = Date.now()
|
|
|
|
|
+ // Batch all event emissions so all store updates result in a single render
|
|
|
|
|
+ batch(() => {
|
|
|
|
|
+ for (const event of events) {
|
|
|
|
|
+ emitter.emit(event.type, event)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- for await (const event of events.stream) {
|
|
|
|
|
- queue.push(event)
|
|
|
|
|
- const elapsed = Date.now() - last
|
|
|
|
|
|
|
+ for await (const event of events.stream) {
|
|
|
|
|
+ queue.push(event)
|
|
|
|
|
+ const elapsed = Date.now() - last
|
|
|
|
|
|
|
|
- if (timer) continue
|
|
|
|
|
- // If we just flushed recently (within 16ms), batch this with future events
|
|
|
|
|
- // Otherwise, process immediately to avoid latency
|
|
|
|
|
- if (elapsed < 16) {
|
|
|
|
|
- timer = setTimeout(flush, 16)
|
|
|
|
|
- continue
|
|
|
|
|
|
|
+ if (timer) continue
|
|
|
|
|
+ // If we just flushed recently (within 16ms), batch this with future events
|
|
|
|
|
+ // Otherwise, process immediately to avoid latency
|
|
|
|
|
+ if (elapsed < 16) {
|
|
|
|
|
+ timer = setTimeout(flush, 16)
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ flush()
|
|
|
}
|
|
}
|
|
|
- flush()
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- // Flush any remaining events
|
|
|
|
|
- if (timer) clearTimeout(timer)
|
|
|
|
|
- if (queue.length > 0) {
|
|
|
|
|
- flush()
|
|
|
|
|
|
|
+ // Flush any remaining events
|
|
|
|
|
+ if (timer) clearTimeout(timer)
|
|
|
|
|
+ if (queue.length > 0) {
|
|
|
|
|
+ flush()
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|