Skip to content
Closed
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
4 changes: 2 additions & 2 deletions packages/opencode/src/cli/cmd/tui/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ async function getTerminalBackgroundColor(): Promise<"dark" | "light"> {
})
}

export function tui(input: { url: string; args: Args; onExit?: () => Promise<void> }) {
export function tui(input: { url: string; args: Args; directory?: string; onExit?: () => Promise<void> }) {
// promise to prevent immediate exit
return new Promise<void>(async (resolve) => {
const mode = await getTerminalBackgroundColor()
Expand All @@ -116,7 +116,7 @@ export function tui(input: { url: string; args: Args; onExit?: () => Promise<voi
<KVProvider>
<ToastProvider>
<RouteProvider>
<SDKProvider url={input.url}>
<SDKProvider url={input.url} directory={input.directory}>
<SyncProvider>
<ThemeProvider mode={mode}>
<LocalProvider>
Expand Down
3 changes: 2 additions & 1 deletion packages/opencode/src/cli/cmd/tui/attach.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ export const AttachCommand = cmd({
describe: "session id to continue",
}),
handler: async (args) => {
if (args.dir) process.chdir(args.dir)
const directory = args.dir ? args.dir : process.cwd()
await tui({
url: args.url,
args: { sessionID: args.session },
directory,
})
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export function Autocomplete(props: {
const command = useCommandDialog()
const { theme } = useTheme()
const dimensions = useTerminalDimensions()
const baseDirectory = () => sync.data.path.directory || process.cwd()

const [store, setStore] = createStore({
index: 0,
Expand Down Expand Up @@ -188,7 +189,7 @@ export function Autocomplete(props: {
const width = props.anchor().width - 4
options.push(
...result.data.map((item): AutocompleteOption => {
let url = `file://${process.cwd()}/${item}`
let url = `file://${baseDirectory()}/${item}`
let filename = item
if (lineRange && !item.endsWith("/")) {
filename = `${item}#${lineRange.startLine}${lineRange.endLine ? `-${lineRange.endLine}` : ""}`
Expand Down
3 changes: 2 additions & 1 deletion packages/opencode/src/cli/cmd/tui/context/sdk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { batch, onCleanup, onMount } from "solid-js"

export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
name: "SDK",
init: (props: { url: string }) => {
init: (props: { url: string; directory?: string }) => {
const abort = new AbortController()
const sdk = createOpencodeClient({
baseUrl: props.url,
signal: abort.signal,
directory: props.directory,
})

const emitter = createGlobalEmitter<{
Expand Down
9 changes: 5 additions & 4 deletions packages/opencode/src/cli/cmd/tui/context/theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
})

createEffect(() => {
getCustomThemes()
const directory = sync.data.path.directory || process.cwd()
getCustomThemes(directory)
.then((custom) => {
setStore(
produce((draft) => {
Expand All @@ -307,7 +308,7 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
if (store.active !== "system") {
setStore("ready", true)
}
})
})
})

const renderer = useRenderer()
Expand Down Expand Up @@ -378,13 +379,13 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
})

const CUSTOM_THEME_GLOB = new Bun.Glob("themes/*.json")
async function getCustomThemes() {
async function getCustomThemes(startDir?: string) {
const directories = [
Global.Path.config,
...(await Array.fromAsync(
Filesystem.up({
targets: [".opencode"],
start: process.cwd(),
start: startDir || process.cwd(),
}),
)),
]
Expand Down
12 changes: 5 additions & 7 deletions packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ import stripAnsi from "strip-ansi"
import { Footer } from "./footer.tsx"
import { usePromptRef } from "../../context/prompt"
import { Filesystem } from "@/util/filesystem"
import { PermissionPrompt } from "./permission"
import { DialogExportOptions } from "../../ui/dialog-export-options"
import { normalizePathFromDirectory } from "@tui/util/paths"
import { PermissionPrompt } from "./permission"
import { formatTranscript } from "../../util/transcript"

addDefaultParsers(parsers.parsers)
Expand Down Expand Up @@ -770,7 +771,7 @@ export function Session() {
// Just open in editor without saving
await Editor.open({ value: transcript, renderer })
} else {
const exportDir = process.cwd()
const exportDir = sync.data.path.directory || process.cwd()
const filename = options.filename.trim()
const filepath = path.join(exportDir, filename)

Expand Down Expand Up @@ -1777,11 +1778,8 @@ function TodoWrite(props: ToolProps<typeof TodoWriteTool>) {
}

function normalizePath(input?: string) {
if (!input) return ""
if (path.isAbsolute(input)) {
return path.relative(process.cwd(), input) || "."
}
return input
const directory = use().sync.data.path.directory || process.cwd()
return normalizePathFromDirectory(input, directory)
}

function input(input: Record<string, any>, omit?: string[]): string {
Expand Down
9 changes: 9 additions & 0 deletions packages/opencode/src/cli/cmd/tui/util/paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import path from "path"

export function normalizePathFromDirectory(input: string | undefined, directory: string) {
if (!input) return ""
if (path.isAbsolute(input)) {
return path.relative(directory, input) || "."
}
return input
}
27 changes: 27 additions & 0 deletions packages/opencode/test/tui/paths.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { describe, expect, test } from "bun:test"
import path from "path"
import { normalizePathFromDirectory } from "../../src/cli/cmd/tui/util/paths"

describe("normalizePathFromDirectory", () => {
test("returns relative path for absolute input", () => {
const directory = "/tmp/opencode-test"
const input = path.join(directory, "src", "index.ts")
expect(normalizePathFromDirectory(input, directory)).toBe(path.join("src", "index.ts"))
})

test("keeps relative input unchanged", () => {
const directory = "/tmp/opencode-test"
const input = "src/index.ts"
expect(normalizePathFromDirectory(input, directory)).toBe(input)
})

test("returns dot when input equals base directory", () => {
const directory = "/tmp/opencode-test"
expect(normalizePathFromDirectory(directory, directory)).toBe(".")
})

test("returns empty string for empty input", () => {
const directory = "/tmp/opencode-test"
expect(normalizePathFromDirectory("", directory)).toBe("")
})
})