cleanup
This commit is contained in:
parent
cf3df010ce
commit
32d542d1c6
5 changed files with 246 additions and 254 deletions
|
|
@ -310,9 +310,9 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const hasUserPrompt = createMemo(() => {
|
const hasUserPrompt = createMemo(() => {
|
||||||
const id = params.id
|
const sessionID = params.id
|
||||||
if (!id) return false
|
if (!sessionID) return false
|
||||||
const messages = sync.data.message[id]
|
const messages = sync.data.message[sessionID]
|
||||||
if (!messages) return false
|
if (!messages) return false
|
||||||
return messages.some((m) => m.role === "user")
|
return messages.some((m) => m.role === "user")
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1620,7 +1620,6 @@ export default function Page() {
|
||||||
|
|
||||||
const { clearMessageHash, scrollToMessage } = useSessionHashScroll({
|
const { clearMessageHash, scrollToMessage } = useSessionHashScroll({
|
||||||
sessionKey,
|
sessionKey,
|
||||||
sessionID: () => params.id,
|
|
||||||
messagesReady,
|
messagesReady,
|
||||||
visibleUserMessages,
|
visibleUserMessages,
|
||||||
turnStart: historyWindow.turnStart,
|
turnStart: historyWindow.turnStart,
|
||||||
|
|
@ -1694,8 +1693,10 @@ export default function Page() {
|
||||||
<div class="flex-1 min-h-0 overflow-hidden">
|
<div class="flex-1 min-h-0 overflow-hidden">
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={params.id}>
|
<Match when={params.id}>
|
||||||
|
{(sessionID) => (
|
||||||
<Show when={lastUserMessage()}>
|
<Show when={lastUserMessage()}>
|
||||||
<MessageTimeline
|
<MessageTimeline
|
||||||
|
sessionID={sessionID()}
|
||||||
mobileChanges={mobileChanges()}
|
mobileChanges={mobileChanges()}
|
||||||
mobileFallback={reviewContent({
|
mobileFallback={reviewContent({
|
||||||
diffStyle: "unified",
|
diffStyle: "unified",
|
||||||
|
|
@ -1736,6 +1737,7 @@ export default function Page() {
|
||||||
anchor={anchor}
|
anchor={anchor}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
|
)}
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={true}>
|
<Match when={true}>
|
||||||
<NewSessionView worktree={newSessionWorktree()} />
|
<NewSessionView worktree={newSessionWorktree()} />
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import { normalizeWheelDelta, shouldMarkBoundaryGesture } from "@/pages/session/
|
||||||
import { useSessionKey } from "@/pages/session/session-layout"
|
import { useSessionKey } from "@/pages/session/session-layout"
|
||||||
import { messageAgentColor } from "@/utils/agent"
|
import { messageAgentColor } from "@/utils/agent"
|
||||||
import { parseCommentNote, readCommentMetadata } from "@/utils/comment-note"
|
import { parseCommentNote, readCommentMetadata } from "@/utils/comment-note"
|
||||||
import { Optional } from "@/utils/optional"
|
|
||||||
|
|
||||||
type MessageComment = {
|
type MessageComment = {
|
||||||
path: string
|
path: string
|
||||||
|
|
@ -196,6 +195,7 @@ function createTimelineStaging(input: TimelineStageInput) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MessageTimeline(props: {
|
export function MessageTimeline(props: {
|
||||||
|
sessionID: string
|
||||||
mobileChanges: boolean
|
mobileChanges: boolean
|
||||||
mobileFallback: JSX.Element
|
mobileFallback: JSX.Element
|
||||||
actions?: UserActions
|
actions?: UserActions
|
||||||
|
|
@ -227,17 +227,17 @@ export function MessageTimeline(props: {
|
||||||
const settings = useSettings()
|
const settings = useSettings()
|
||||||
const dialog = useDialog()
|
const dialog = useDialog()
|
||||||
const language = useLanguage()
|
const language = useLanguage()
|
||||||
const { params, sessionKey } = useSessionKey()
|
const { sessionKey } = useSessionKey()
|
||||||
const platform = usePlatform()
|
const platform = usePlatform()
|
||||||
|
|
||||||
const rendered = createMemo(() => props.renderedUserMessages.map((message) => message.id))
|
const rendered = createMemo(() => props.renderedUserMessages.map((message) => message.id))
|
||||||
const sessionMessages = createMemo(() => Optional.map(params.id, (id) => sync.data.message[id]) ?? emptyMessages)
|
const sessionMessages = createMemo(() => sync.data.message[props.sessionID] ?? emptyMessages)
|
||||||
const pending = createMemo(() =>
|
const pending = createMemo(() =>
|
||||||
sessionMessages().findLast(
|
sessionMessages().findLast(
|
||||||
(item): item is AssistantMessage => item.role === "assistant" && typeof item.time.completed !== "number",
|
(item): item is AssistantMessage => item.role === "assistant" && typeof item.time.completed !== "number",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
const sessionStatus = createMemo(() => Optional.map(params.id, (id) => sync.data.session_status[id]) ?? idle)
|
const sessionStatus = createMemo(() => sync.data.session_status[props.sessionID] ?? idle)
|
||||||
const working = createMemo(() => !!pending() || sessionStatus().type !== "idle")
|
const working = createMemo(() => !!pending() || sessionStatus().type !== "idle")
|
||||||
const tint = createMemo(() => messageAgentColor(sessionMessages(), sync.data.agent))
|
const tint = createMemo(() => messageAgentColor(sessionMessages(), sync.data.agent))
|
||||||
|
|
||||||
|
|
@ -292,7 +292,7 @@ export function MessageTimeline(props: {
|
||||||
|
|
||||||
return undefined
|
return undefined
|
||||||
})
|
})
|
||||||
const info = createMemo(() => Optional.map(params.id, (id) => sync.session.get(id)))
|
const info = createMemo(() => sync.session.get(props.sessionID))
|
||||||
const titleValue = createMemo(() => info()?.title)
|
const titleValue = createMemo(() => info()?.title)
|
||||||
const shareUrl = createMemo(() => info()?.share?.url)
|
const shareUrl = createMemo(() => info()?.share?.url)
|
||||||
const shareEnabled = createMemo(() => sync.data.config.share !== "disabled")
|
const shareEnabled = createMemo(() => sync.data.config.share !== "disabled")
|
||||||
|
|
@ -326,12 +326,11 @@ export function MessageTimeline(props: {
|
||||||
const [req, setReq] = createStore({ share: false, unshare: false })
|
const [req, setReq] = createStore({ share: false, unshare: false })
|
||||||
|
|
||||||
const shareSession = () => {
|
const shareSession = () => {
|
||||||
const id = params.id
|
if (req.share) return
|
||||||
if (!id || req.share) return
|
|
||||||
if (!shareEnabled()) return
|
if (!shareEnabled()) return
|
||||||
setReq("share", true)
|
setReq("share", true)
|
||||||
globalSDK.client.session
|
globalSDK.client.session
|
||||||
.share({ sessionID: id, directory: sdk.directory })
|
.share({ sessionID: props.sessionID, directory: sdk.directory })
|
||||||
.catch((err: unknown) => {
|
.catch((err: unknown) => {
|
||||||
console.error("Failed to share session", err)
|
console.error("Failed to share session", err)
|
||||||
})
|
})
|
||||||
|
|
@ -341,12 +340,11 @@ export function MessageTimeline(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
const unshareSession = () => {
|
const unshareSession = () => {
|
||||||
const id = params.id
|
if (req.unshare) return
|
||||||
if (!id || req.unshare) return
|
|
||||||
if (!shareEnabled()) return
|
if (!shareEnabled()) return
|
||||||
setReq("unshare", true)
|
setReq("unshare", true)
|
||||||
globalSDK.client.session
|
globalSDK.client.session
|
||||||
.unshare({ sessionID: id, directory: sdk.directory })
|
.unshare({ sessionID: props.sessionID, directory: sdk.directory })
|
||||||
.catch((err: unknown) => {
|
.catch((err: unknown) => {
|
||||||
console.error("Failed to unshare session", err)
|
console.error("Failed to unshare session", err)
|
||||||
})
|
})
|
||||||
|
|
@ -387,7 +385,6 @@ export function MessageTimeline(props: {
|
||||||
)
|
)
|
||||||
|
|
||||||
const openTitleEditor = () => {
|
const openTitleEditor = () => {
|
||||||
if (!params.id) return
|
|
||||||
setTitle({ editing: true, draft: titleValue() ?? "" })
|
setTitle({ editing: true, draft: titleValue() ?? "" })
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
titleRef?.focus()
|
titleRef?.focus()
|
||||||
|
|
@ -401,8 +398,6 @@ export function MessageTimeline(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveTitleEditor = async () => {
|
const saveTitleEditor = async () => {
|
||||||
const id = params.id
|
|
||||||
if (!id) return
|
|
||||||
if (title.saving) return
|
if (title.saving) return
|
||||||
|
|
||||||
const next = title.draft.trim()
|
const next = title.draft.trim()
|
||||||
|
|
@ -413,11 +408,11 @@ export function MessageTimeline(props: {
|
||||||
|
|
||||||
setTitle("saving", true)
|
setTitle("saving", true)
|
||||||
await sdk.client.session
|
await sdk.client.session
|
||||||
.update({ sessionID: id, title: next })
|
.update({ sessionID: props.sessionID, title: next })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
sync.set(
|
sync.set(
|
||||||
produce((draft) => {
|
produce((draft) => {
|
||||||
const index = draft.session.findIndex((s) => s.id === id)
|
const index = draft.session.findIndex((s) => s.id === props.sessionID)
|
||||||
if (index !== -1) draft.session[index].title = next
|
if (index !== -1) draft.session[index].title = next
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
@ -433,7 +428,7 @@ export function MessageTimeline(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigateAfterSessionRemoval = (id: string, parentID?: string, nextSessionID?: string) => {
|
const navigateAfterSessionRemoval = (id: string, parentID?: string, nextSessionID?: string) => {
|
||||||
if (params.id !== id) return
|
if (props.sessionID !== id) return
|
||||||
if (parentID) {
|
if (parentID) {
|
||||||
navigate(`../${parentID}`)
|
navigate(`../${parentID}`)
|
||||||
return
|
return
|
||||||
|
|
@ -722,8 +717,6 @@ export function MessageTimeline(props: {
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Show when={params.id}>
|
|
||||||
{(id) => (
|
|
||||||
<div class="shrink-0 flex items-center gap-3">
|
<div class="shrink-0 flex items-center gap-3">
|
||||||
<SessionContextUsage placement="bottom" />
|
<SessionContextUsage placement="bottom" />
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
|
|
@ -787,12 +780,12 @@ export function MessageTimeline(props: {
|
||||||
</DropdownMenu.ItemLabel>
|
</DropdownMenu.ItemLabel>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</Show>
|
</Show>
|
||||||
<DropdownMenu.Item onSelect={() => void archiveSession(id())}>
|
<DropdownMenu.Item onSelect={() => void archiveSession(props.sessionID)}>
|
||||||
<DropdownMenu.ItemLabel>{language.t("common.archive")}</DropdownMenu.ItemLabel>
|
<DropdownMenu.ItemLabel>{language.t("common.archive")}</DropdownMenu.ItemLabel>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Separator />
|
<DropdownMenu.Separator />
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
onSelect={() => dialog.show(() => <DialogDeleteSession sessionID={id()} />)}
|
onSelect={() => dialog.show(() => <DialogDeleteSession sessionID={props.sessionID} />)}
|
||||||
>
|
>
|
||||||
<DropdownMenu.ItemLabel>{language.t("common.delete")}</DropdownMenu.ItemLabel>
|
<DropdownMenu.ItemLabel>{language.t("common.delete")}</DropdownMenu.ItemLabel>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
|
|
@ -898,8 +891,6 @@ export function MessageTimeline(props: {
|
||||||
</KobaltePopover.Portal>
|
</KobaltePopover.Portal>
|
||||||
</KobaltePopover>
|
</KobaltePopover>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</Show>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
@ -987,7 +978,7 @@ export function MessageTimeline(props: {
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<SessionTurn
|
<SessionTurn
|
||||||
sessionID={params.id ?? ""}
|
sessionID={props.sessionID}
|
||||||
messageID={messageID}
|
messageID={messageID}
|
||||||
actions={props.actions}
|
actions={props.actions}
|
||||||
active={active()}
|
active={active()}
|
||||||
|
|
|
||||||
|
|
@ -126,8 +126,8 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||||
const permissionsCommand = withCategory(language.t("command.category.permissions"))
|
const permissionsCommand = withCategory(language.t("command.category.permissions"))
|
||||||
|
|
||||||
const isAutoAcceptActive = () => {
|
const isAutoAcceptActive = () => {
|
||||||
const id = params.id
|
const sessionID = params.id
|
||||||
if (id) return permission.isAutoAccepting(id, sdk.directory)
|
if (sessionID) return permission.isAutoAccepting(sessionID, sdk.directory)
|
||||||
return permission.isAutoAcceptingDirectory(sdk.directory)
|
return permission.isAutoAcceptingDirectory(sdk.directory)
|
||||||
}
|
}
|
||||||
command.register("session", () => {
|
command.register("session", () => {
|
||||||
|
|
@ -146,8 +146,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||||
slash: "share",
|
slash: "share",
|
||||||
disabled: !params.id,
|
disabled: !params.id,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
const id = params.id
|
if (!params.id) return
|
||||||
if (!id) return
|
|
||||||
|
|
||||||
const write = (value: string) => {
|
const write = (value: string) => {
|
||||||
const body = typeof document === "undefined" ? undefined : document.body
|
const body = typeof document === "undefined" ? undefined : document.body
|
||||||
|
|
@ -199,7 +198,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = await sdk.client.session
|
const url = await sdk.client.session
|
||||||
.share({ sessionID: id })
|
.share({ sessionID: params.id })
|
||||||
.then((res) => res.data?.share?.url)
|
.then((res) => res.data?.share?.url)
|
||||||
.catch(() => undefined)
|
.catch(() => undefined)
|
||||||
if (!url) {
|
if (!url) {
|
||||||
|
|
@ -391,12 +390,12 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||||
keybind: "mod+shift+a",
|
keybind: "mod+shift+a",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
const id = params.id
|
const sessionID = params.id
|
||||||
if (id) permission.toggleAutoAccept(id, sdk.directory)
|
if (sessionID) permission.toggleAutoAccept(sessionID, sdk.directory)
|
||||||
else permission.toggleAutoAcceptDirectory(sdk.directory)
|
else permission.toggleAutoAcceptDirectory(sdk.directory)
|
||||||
|
|
||||||
const active = id
|
const active = sessionID
|
||||||
? permission.isAutoAccepting(id, sdk.directory)
|
? permission.isAutoAccepting(sessionID, sdk.directory)
|
||||||
: permission.isAutoAcceptingDirectory(sdk.directory)
|
: permission.isAutoAcceptingDirectory(sdk.directory)
|
||||||
showToast({
|
showToast({
|
||||||
title: active
|
title: active
|
||||||
|
|
@ -415,16 +414,16 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||||
slash: "undo",
|
slash: "undo",
|
||||||
disabled: !params.id || visibleUserMessages().length === 0,
|
disabled: !params.id || visibleUserMessages().length === 0,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
const id = params.id
|
const sessionID = params.id
|
||||||
if (!id) return
|
if (!sessionID) return
|
||||||
if (status().type !== "idle") {
|
if (status().type !== "idle") {
|
||||||
await sdk.client.session.abort({ sessionID: id }).catch(() => {})
|
await sdk.client.session.abort({ sessionID }).catch(() => {})
|
||||||
}
|
}
|
||||||
const revert = info()?.revert?.messageID
|
const revert = info()?.revert?.messageID
|
||||||
const message = findLast(userMessages(), (x) => !revert || x.id < revert)
|
const message = findLast(userMessages(), (x) => !revert || x.id < revert)
|
||||||
if (!message) return
|
if (!message) return
|
||||||
await sdk.client.session.revert({
|
await sdk.client.session.revert({
|
||||||
sessionID: id,
|
sessionID,
|
||||||
messageID: message.id,
|
messageID: message.id,
|
||||||
})
|
})
|
||||||
const parts = sync.data.part[message.id]
|
const parts = sync.data.part[message.id]
|
||||||
|
|
@ -445,20 +444,20 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||||
slash: "redo",
|
slash: "redo",
|
||||||
disabled: !params.id || !info()?.revert?.messageID,
|
disabled: !params.id || !info()?.revert?.messageID,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
const id = params.id
|
const sessionID = params.id
|
||||||
if (!id) return
|
if (!sessionID) return
|
||||||
const revertMessageID = info()?.revert?.messageID
|
const revertMessageID = info()?.revert?.messageID
|
||||||
if (!revertMessageID) return
|
if (!revertMessageID) return
|
||||||
const nextMessage = userMessages().find((x) => x.id > revertMessageID)
|
const nextMessage = userMessages().find((x) => x.id > revertMessageID)
|
||||||
if (!nextMessage) {
|
if (!nextMessage) {
|
||||||
await sdk.client.session.unrevert({ sessionID: id })
|
await sdk.client.session.unrevert({ sessionID })
|
||||||
prompt.reset()
|
prompt.reset()
|
||||||
const lastMsg = findLast(userMessages(), (x) => x.id >= revertMessageID)
|
const lastMsg = findLast(userMessages(), (x) => x.id >= revertMessageID)
|
||||||
setActiveMessage(lastMsg)
|
setActiveMessage(lastMsg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await sdk.client.session.revert({
|
await sdk.client.session.revert({
|
||||||
sessionID: id,
|
sessionID,
|
||||||
messageID: nextMessage.id,
|
messageID: nextMessage.id,
|
||||||
})
|
})
|
||||||
const priorMsg = findLast(userMessages(), (x) => x.id < nextMessage.id)
|
const priorMsg = findLast(userMessages(), (x) => x.id < nextMessage.id)
|
||||||
|
|
@ -472,8 +471,8 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||||
slash: "compact",
|
slash: "compact",
|
||||||
disabled: !params.id || visibleUserMessages().length === 0,
|
disabled: !params.id || visibleUserMessages().length === 0,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
const id = params.id
|
const sessionID = params.id
|
||||||
if (!id) return
|
if (!sessionID) return
|
||||||
const model = local.model.current()
|
const model = local.model.current()
|
||||||
if (!model) {
|
if (!model) {
|
||||||
showToast({
|
showToast({
|
||||||
|
|
@ -483,7 +482,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await sdk.client.session.summarize({
|
await sdk.client.session.summarize({
|
||||||
sessionID: id,
|
sessionID,
|
||||||
modelID: model.id,
|
modelID: model.id,
|
||||||
providerID: model.provider.id,
|
providerID: model.provider.id,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { useSessionLayout } from "./session-layout"
|
||||||
|
|
||||||
export const useSessionHashScroll = (input: {
|
export const useSessionHashScroll = (input: {
|
||||||
sessionKey: () => string
|
sessionKey: () => string
|
||||||
sessionID: () => string | undefined
|
|
||||||
messagesReady: () => boolean
|
messagesReady: () => boolean
|
||||||
visibleUserMessages: () => UserMessage[]
|
visibleUserMessages: () => UserMessage[]
|
||||||
turnStart: () => number
|
turnStart: () => number
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue