Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/app/src/components/prompt-input/submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ export function createPromptSubmit(input: PromptSubmitInput) {
})
if (created) {
seed(sessionDirectory, created)
void globalSync.project.loadSessions(sessionDirectory)
session = created
if (shouldAutoAccept) permission.enableAutoAccept(session.id, sessionDirectory)
local.session.promote(sessionDirectory, session.id)
Expand Down
28 changes: 17 additions & 11 deletions packages/app/src/context/sync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -472,17 +472,23 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
if (!tracked(directory, sessionID)) return
const data = session.data
if (!data) return
setStore(
"session",
produce((draft) => {
const match = Binary.search(draft, sessionID, (s) => s.id)
if (match.found) {
draft[match.index] = data
return
}
draft.splice(match.index, 0, data)
}),
)
const upsertSession = (setter: Setter) =>
setter(
"session",
produce((draft) => {
const match = Binary.search(draft, sessionID, (s) => s.id)
if (match.found) {
draft[match.index] = data
return
}
draft.splice(match.index, 0, data)
}),
)
upsertSession(setStore)
if (data.directory !== directory) {
const [, targetSetStore] = globalSync.child(data.directory)
upsertSession(targetSetStore)
}
})

const messagesReq =
Expand Down
26 changes: 24 additions & 2 deletions packages/app/src/pages/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ export default function Layout(props: ParentProps) {
const direct = projects.find((p) => workspaceKey(p.worktree) === key)
if (direct) return direct

const [child] = globalSync.child(directory, { bootstrap: false })
const [child] = globalSync.child(directory, { bootstrap: true })
const id = child.project
if (!id) return

Expand Down Expand Up @@ -1839,6 +1839,17 @@ export default function Layout(props: ParentProps) {
),
)

createEffect(
on(
() => [route().slug, params.id, currentDir()] as const,
([slug, _id, dir]) => {
if (!slug || !dir) return
void globalSync.project.loadSessions(dir)
},
{ defer: true },
),
)

function handleDragStart(event: unknown) {
const id = getDraggableId(event)
if (!id) return
Expand Down Expand Up @@ -2329,6 +2340,17 @@ export default function Layout(props: ParentProps) {
}

const projects = () => layout.projects.list()
const panelProject = createMemo(() => {
const current = currentProject()
if (current) return current
const directory = currentDir()
if (directory) {
const root = projectRoot(directory)
const fromRoot = projects().find((project) => workspaceKey(project.worktree) === workspaceKey(root))
if (fromRoot) return fromRoot
}
return projects()[0]
})
const projectOverlay = () => <ProjectDragOverlay projects={projects} activeProject={() => store.activeProject} />
const sidebarContent = (mobile?: boolean) => (
<SidebarContent
Expand All @@ -2352,7 +2374,7 @@ export default function Layout(props: ParentProps) {
helpLabel={() => language.t("sidebar.help")}
onOpenHelp={() => platform.openLink("https://opencode.ai/desktop-feedback")}
renderPanel={() =>
mobile ? <SidebarPanel project={currentProject} mobile /> : <SidebarPanel project={currentProject} merged />
mobile ? <SidebarPanel project={panelProject} mobile /> : <SidebarPanel project={panelProject} merged />
}
/>
)
Expand Down
10 changes: 7 additions & 3 deletions packages/app/src/pages/layout/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { type Session } from "@opencode-ai/sdk/v2/client"

type SessionStore = {
session?: Session[]
project?: string
path: { directory: string }
}

Expand All @@ -28,11 +29,14 @@ function sortSessions(now: number) {
}
}

const isRootVisibleSession = (session: Session, directory: string) =>
workspaceKey(session.directory) === workspaceKey(directory) && !session.parentID && !session.time?.archived
const isRootVisibleSession = (session: Session, store: SessionStore) => {
if (session.parentID || session.time?.archived) return false
if (store.project && session.projectID && store.project === session.projectID) return true
return workspaceKey(session.directory) === workspaceKey(store.path.directory)
}

export const roots = (store: SessionStore) =>
(store.session ?? []).filter((session) => isRootVisibleSession(session, store.path.directory))
(store.session ?? []).filter((session) => isRootVisibleSession(session, store))

export const sortedRootSessions = (store: SessionStore, now: number) => roots(store).sort(sortSessions(now))

Expand Down
2 changes: 0 additions & 2 deletions packages/opencode/src/session/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,6 @@ export const layer = Layer.effect(
m.info.role === "user" && !m.parts.every((p) => "synthetic" in p && p.synthetic)
const idx = input.history.findIndex(real)
if (idx === -1) return
if (input.history.filter(real).length !== 1) return

const context = input.history.slice(0, idx + 1)
const firstUser = context[idx]
if (!firstUser || firstUser.info.role !== "user") return
Expand Down
7 changes: 2 additions & 5 deletions packages/opencode/src/session/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -750,11 +750,8 @@ export function* list(input?: {
if (input?.workspaceID) {
conditions.push(eq(SessionTable.workspace_id, input.workspaceID))
}
if (!Flag.OPENCODE_EXPERIMENTAL_WORKSPACES) {
if (input?.directory) {
conditions.push(eq(SessionTable.directory, input.directory))
}
}
// Keep session list stable across cwd changes within the same project.
// Project scoping is already enforced via project_id above.
if (input?.roots) {
conditions.push(isNull(SessionTable.parent_id))
}
Expand Down
Loading