anomalyco / anomalyco/opencode
Bug: getDirectory() shows a fake "/" parent for root-level files
@jlongster is already working on this.
Since Jul 30, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Description
Three related bugs in packages/core/src/util/path.ts, all from assuming a delimiter is present.
1. getDirectory() invents a parent for root-level files. It joins all-but-last segments and unconditionally appends "/", so a path with no separator yields "/":
getDirectory("README.md") -> "/" (expected "")
getDirectory("file.txt") -> "/" (expected "")
getDirectory("src/file.txt") -> "src/" (correct)
This is user-visible: the command palette renders directory + filename side by side (packages/app/src/components/dialog-command-palette-v2.tsx:282-283), so opening a repo-root file like README.md displays /README.md instead of README.md. Same pattern in dialog-select-file.tsx:135, context-items.tsx:27, and message-timeline.tsx:194.
Notably packages/app/src/pages/session/v2/session-file-list-v2.tsx:108 already works around it with value.includes("/") ? getDirectory(value) : undefined — the other call sites don't.
2. getFileExtension() returns the whole path when there is no extension. It splits on . and takes the last part, so with no dot the last part is the input:
getFileExtension("Makefile") -> "Makefile" (expected "")
getFileExtension("src/Dockerfile") -> "src/Dockerfile" (expected "")
getFileExtension(".gitignore") -> "gitignore" (expected "" — hidden file, not an extension)
It also ignores path structure, so getFileExtension("my.dir/Makefile") returns "dir/Makefile".
3. truncateMiddle() overflows instead of truncating at small widths. When maxLength is 1 or 2, Math.floor((maxLength - 1) / 2) is 0 and slice(-0) returns the entire string:
truncateMiddle("abcdefghij", 2) -> "a…abcdefghij" (12 chars, expected <= 2)
truncateMiddle("abcdefghij", 1) -> "…abcdefghij" (11 chars, expected <= 1)
A truncation helper returning something longer than its input limit breaks any fixed-width layout that trusts it.
Steps to reproduce
import { getDirectory, getFileExtension, truncateMiddle } from "@opencode-ai/core/util/path"
console.log(getDirectory("README.md")) // "/"
console.log(getFileExtension("Makefile")) // "Makefile"
console.log(truncateMiddle("abcdefghij", 2)) // "a…abcdefghij"
OS
Windows (platform-independent — pure string logic)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.