mirror of
https://github.com/sst/opencode.git
synced 2025-12-23 10:11:41 +00:00
sync
This commit is contained in:
parent
256dead643
commit
7894c3834e
3 changed files with 69 additions and 1 deletions
|
|
@ -17,6 +17,13 @@ import { type AutocompleteRef, Autocomplete } from "./autocomplete"
|
|||
export type PromptProps = {
|
||||
sessionID?: string
|
||||
onSubmit?: () => void
|
||||
ref?: (ref: PromptRef) => void
|
||||
}
|
||||
|
||||
export type PromptRef = {
|
||||
focused: boolean
|
||||
set(prompt: PromptInfo): void
|
||||
reset(): void
|
||||
}
|
||||
|
||||
export function Prompt(props: PromptProps) {
|
||||
|
|
@ -43,6 +50,22 @@ export function Prompt(props: PromptProps) {
|
|||
if (dialog.stack.length > 0) input.blur()
|
||||
})
|
||||
|
||||
props.ref?.({
|
||||
get focused() {
|
||||
return input.focused
|
||||
},
|
||||
set(prompt) {
|
||||
setStore(prompt)
|
||||
input.cursorPosition = prompt.input.length
|
||||
},
|
||||
reset() {
|
||||
setStore({
|
||||
input: "",
|
||||
parts: [],
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Autocomplete
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
|||
|
||||
sdk.event.subscribe().then(async (events) => {
|
||||
for await (const event of events.stream) {
|
||||
console.log(event.type)
|
||||
switch (event.type) {
|
||||
case "todo.updated":
|
||||
setStore("todo", event.properties.sessionID, event.properties.todos)
|
||||
|
|
@ -76,6 +77,20 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
|||
)
|
||||
break
|
||||
}
|
||||
case "message.removed": {
|
||||
const messages = store.message[event.properties.sessionID]
|
||||
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 parts = store.part[event.properties.part.messageID]
|
||||
if (!parts) {
|
||||
|
|
@ -96,6 +111,20 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
|||
)
|
||||
break
|
||||
}
|
||||
|
||||
case "message.part.removed": {
|
||||
const parts = store.part[event.properties.messageID]
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { useSync } from "@tui/context/sync"
|
|||
import { SplitBorder } from "@tui/component/border"
|
||||
import { Theme } from "@tui/context/theme"
|
||||
import { BoxRenderable, ScrollBoxRenderable } from "@opentui/core"
|
||||
import { Prompt } from "@tui/component/prompt"
|
||||
import { Prompt, type PromptRef } from "@tui/component/prompt"
|
||||
import type { AssistantMessage, Part, ToolPart, UserMessage, TextPart, ReasoningPart } from "@opencode-ai/sdk"
|
||||
import { useLocal } from "@tui/context/local"
|
||||
import { Locale } from "@/util/locale"
|
||||
|
|
@ -31,6 +31,7 @@ import { Header } from "./header"
|
|||
import { parsePatch } from "diff"
|
||||
import { useDialog } from "../../ui/dialog"
|
||||
import { DialogMessage } from "./dialog-message"
|
||||
import type { PromptInfo } from "../../component/prompt/history"
|
||||
|
||||
export function Session() {
|
||||
const route = useRouteData("session")
|
||||
|
|
@ -44,9 +45,11 @@ export function Session() {
|
|||
const sdk = useSDK()
|
||||
|
||||
let scroll: ScrollBoxRenderable
|
||||
let prompt: PromptRef
|
||||
const keybind = useKeybind()
|
||||
|
||||
useKeyboard((evt) => {
|
||||
if (!prompt.focused) return
|
||||
if (keybind.match("messages_page_up", evt)) scroll.scrollBy(-scroll.height / 2)
|
||||
if (keybind.match("messages_page_down", evt)) scroll.scrollBy(scroll.height / 2)
|
||||
})
|
||||
|
|
@ -132,6 +135,17 @@ export function Session() {
|
|||
messageID: message.id,
|
||||
},
|
||||
})
|
||||
const parts = sync.data.part[message.id]
|
||||
prompt.set(
|
||||
parts.reduce(
|
||||
(agg, part) => {
|
||||
if (part.type === "text") agg.input += part.text
|
||||
if (part.type === "file") agg.parts.push(part)
|
||||
return agg
|
||||
},
|
||||
{ input: "", parts: [] as PromptInfo["parts"] },
|
||||
),
|
||||
)
|
||||
dialog.clear()
|
||||
},
|
||||
},
|
||||
|
|
@ -150,6 +164,7 @@ export function Session() {
|
|||
id: route.sessionID,
|
||||
},
|
||||
})
|
||||
prompt.set({ input: "", parts: [] })
|
||||
return
|
||||
}
|
||||
sdk.session.revert({
|
||||
|
|
@ -288,6 +303,7 @@ export function Session() {
|
|||
</Show>
|
||||
<box flexShrink={0}>
|
||||
<Prompt
|
||||
ref={(r) => (prompt = r)}
|
||||
onSubmit={() => {
|
||||
toBottom()
|
||||
}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue