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
15 changes: 14 additions & 1 deletion packages/opencode/src/cli/cmd/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { NotFoundError } from "@/storage/storage"
import { EOL } from "os"
import path from "path"
import { which } from "@opencode-ai/core/util/which"
import { InstanceRef } from "@/effect/instance-ref"

function pagerCmd(): string[] {
const lessOptions = ["-R", "-S"]
Expand Down Expand Up @@ -84,7 +85,11 @@ export const SessionListCommand = effectCmd({
default: "table",
}),
handler: Effect.fn("Cli.session.list")(function* (args) {
const sessions = yield* Session.Service.use((svc) => svc.list({ roots: true, limit: args.maxCount }))
const ctx = yield* InstanceRef
if (!ctx) return yield* Effect.die("InstanceRef not provided")
const sessions = yield* Session.Service.use((svc) =>
svc.list(createSessionListQuery({ directory: ctx.directory, maxCount: args.maxCount })),
)

if (sessions.length === 0) return

Expand Down Expand Up @@ -115,6 +120,14 @@ export const SessionListCommand = effectCmd({
}),
})

export function createSessionListQuery(input: { directory: string; maxCount?: number }) {
return {
directory: input.directory,
roots: true,
limit: input.maxCount,
}
}

function formatSessionTable(sessions: Session.Info[]): string {
const lines: string[] = []

Expand Down
12 changes: 12 additions & 0 deletions packages/opencode/test/cli/session.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { describe, expect, test } from "bun:test"
import { createSessionListQuery } from "../../src/cli/cmd/session"

describe("session list", () => {
test("scopes the query to the current exact directory", () => {
expect(createSessionListQuery({ directory: "/workspace/packages/opencode", maxCount: 12 })).toEqual({
directory: "/workspace/packages/opencode",
roots: true,
limit: 12,
})
})
})
2 changes: 1 addition & 1 deletion packages/tui/src/component/dialog-session-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { DialogSessionDeleteFailed } from "./dialog-session-delete-failed"
import { useCommandShortcut } from "../keymap"
import { useEvent } from "../context/event"

type SessionListFilter = { scope?: "project"; path?: string }
type SessionListFilter = { scope?: "project"; directory?: string }

export function createDialogSessionListQuery(input: { search?: string; filter: SessionListFilter }) {
const search = input.search?.trim()
Expand Down
22 changes: 13 additions & 9 deletions packages/tui/src/context/sync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import { createSimpleContext } from "./helper"
import { useExit } from "./exit"
import { useArgs } from "./args"
import { batch, onMount } from "solid-js"
import path from "path"
import { useKV } from "./kv"
import { usePermission } from "./permission"

Expand All @@ -51,6 +50,14 @@ function search<T>(items: T[], target: string, key: (item: T) => string) {
return { found: false, index: left }
}

export function createSessionListFilter(input: { directoryFilterEnabled: boolean; directory?: string }): {
scope?: "project"
directory?: string
} {
if (!input.directoryFilterEnabled || !input.directory) return { scope: "project" }
return { directory: input.directory }
}

export const {
context: SyncContext,
use: useSync,
Expand Down Expand Up @@ -151,14 +158,11 @@ export const {
hydratingSessions.get(sessionID)?.parts.add(partID)
}

function sessionListQuery(): { scope?: "project"; path?: string } {
if (!kv.get("session_directory_filter_enabled", true)) return { scope: "project" }
if (!project.data.instance.path.worktree || !project.data.instance.path.directory) return { scope: "project" }
return {
path: path
.relative(path.resolve(project.data.instance.path.worktree), project.data.instance.path.directory)
.replaceAll("\\", "/"),
}
function sessionListQuery() {
return createSessionListFilter({
directoryFilterEnabled: kv.get("session_directory_filter_enabled", true),
directory: project.data.instance.path.directory,
})
}

function listSessions() {
Expand Down
6 changes: 3 additions & 3 deletions packages/tui/test/component/dialog-session-list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { describe, expect, test } from "bun:test"
import { createDialogSessionListQuery, loadDialogSessionList } from "../../src/component/dialog-session-list"

describe("dialog session list", () => {
test("requests root sessions for the default browse list", () => {
expect(createDialogSessionListQuery({ filter: { path: "packages/tui" } })).toEqual({
test("requests root sessions in the exact directory for the default browse list", () => {
expect(createDialogSessionListQuery({ filter: { directory: "/workspace/packages/tui" } })).toEqual({
roots: true,
limit: 100,
path: "packages/tui",
directory: "/workspace/packages/tui",
})
})

Expand Down
16 changes: 16 additions & 0 deletions packages/tui/test/context/session-list-filter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { describe, expect, test } from "bun:test"
import { createSessionListFilter } from "../../src/context/sync"

describe("session list filter", () => {
test("uses the current exact directory when filtering is enabled", () => {
expect(createSessionListFilter({ directoryFilterEnabled: true, directory: "/workspace/packages/tui" })).toEqual({
directory: "/workspace/packages/tui",
})
})

test("uses the project scope when directory filtering is disabled", () => {
expect(createSessionListFilter({ directoryFilterEnabled: false, directory: "/workspace/packages/tui" })).toEqual({
scope: "project",
})
})
})
Loading