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 bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/app/src/context/file.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({
}

const search = (query: string, dirs: "true" | "false") =>
sdk.client.find.files({ query, dirs }).then(
sdk.client.find.files({ query, dirs, sessionID: params.id }).then(
(x) => (x.data ?? []).map(path.normalize),
() => [],
)
Expand Down
7 changes: 7 additions & 0 deletions packages/app/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export const dict = {
"command.session.share.description": "Share this session and copy the URL to clipboard",
"command.session.unshare": "Unshare session",
"command.session.unshare.description": "Stop sharing this session",
"command.session.directory.add": "Add workspace directory",
"command.session.directory.add.description": "Allow another directory for this session",

"palette.search.placeholder": "Search files, commands, and sessions",
"palette.empty": "No results found",
Expand Down Expand Up @@ -447,6 +449,11 @@ export const dict = {
"toast.session.unshare.success.description": "Session unshared successfully!",
"toast.session.unshare.failed.title": "Failed to unshare session",
"toast.session.unshare.failed.description": "An error occurred while unsharing the session",
"toast.session.directory.added.title": "Workspace directory added",
"toast.session.directory.added.description": "Added {{directory}} to this session",
"toast.session.directory.exists.title": "Workspace directory already added",
"toast.session.directory.exists.description": "{{directory}} is already available in this session",
"toast.session.directory.failed.title": "Failed to add workspace directory",

"toast.session.listFailed.title": "Failed to load sessions for {{project}}",
"toast.project.reloadFailed.title": "Failed to reload {{project}}",
Expand Down
74 changes: 72 additions & 2 deletions packages/app/src/pages/session/use-session-commands.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createMemo } from "solid-js"
import { useNavigate } from "@solidjs/router"
import { useCommand, type CommandOption } from "@/context/command"
import { useDialog } from "@opencode-ai/ui/context/dialog"
Expand All @@ -12,6 +13,7 @@ import { useSDK } from "@/context/sdk"
import { useSync } from "@/context/sync"
import { useTerminal } from "@/context/terminal"
import { DialogSelectFile } from "@/components/dialog-select-file"
import { DialogSelectDirectory } from "@/components/dialog-select-directory"
import { DialogSelectModel } from "@/components/dialog-select-model"
import { DialogSelectMcp } from "@/components/dialog-select-mcp"
import { DialogFork } from "@/components/dialog-fork"
Expand Down Expand Up @@ -408,6 +410,75 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
})
},
}),
sessionCommand({
id: "session.directory.add",
title: language.t("command.session.directory.add"),
description: language.t("command.session.directory.add.description"),
slash: "add-directory",
disabled: !params.id,
onSelect: async () => {
const sessionID = params.id
if (!sessionID) return

const selected = await new Promise<string | undefined>((resolve) => {
const done = (result: string | string[] | null) => {
if (Array.isArray(result)) {
resolve(result[0])
return
}
resolve(result ?? undefined)
}
dialog.show(
() => <DialogSelectDirectory title={language.t("command.session.directory.add")} onSelect={done} />,
() => done(null),
)
})

if (!selected) return

await sdk.client.session
.workspaceDirectory({
sessionID,
path: selected,
})
.then((res) => {
const data = res.data
if (!data) {
showToast({
title: language.t("toast.session.directory.failed.title"),
description: language.t("common.requestFailed"),
variant: "error",
})
return
}

if (!data.added) {
showToast({
title: language.t("toast.session.directory.exists.title"),
description: language.t("toast.session.directory.exists.description", {
directory: data.directory,
}),
})
return
}

showToast({
title: language.t("toast.session.directory.added.title"),
description: language.t("toast.session.directory.added.description", {
directory: data.directory,
}),
variant: "success",
})
})
.catch((error: Error) => {
showToast({
title: language.t("toast.session.directory.failed.title"),
description: error instanceof Error ? error.message : language.t("common.requestFailed"),
variant: "error",
})
})
},
}),
sessionCommand({
id: "session.undo",
title: language.t("command.session.undo"),
Expand All @@ -417,7 +488,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
onSelect: async () => {
const sessionID = params.id
if (!sessionID) return
if (status().type !== "idle") {
if (status()?.type !== "idle") {
await sdk.client.session.abort({ sessionID }).catch(() => {})
}
const revert = info()?.revert?.messageID
Expand Down Expand Up @@ -489,7 +560,6 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
disabled: !params.id || visibleUserMessages().length === 0,
onSelect: () => dialog.show(() => <DialogFork />),
}),
...share,
]
})
}
3 changes: 2 additions & 1 deletion packages/opencode/src/cli/cmd/tui/component/dialog-tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useDialog } from "@tui/ui/dialog"
import { useSDK } from "@tui/context/sdk"
import { createStore } from "solid-js/store"

export function DialogTag(props: { onSelect?: (value: string) => void }) {
export function DialogTag(props: { onSelect?: (value: string) => void; sessionID?: string }) {
const sdk = useSDK()
const dialog = useDialog()

Expand All @@ -17,6 +17,7 @@ export function DialogTag(props: { onSelect?: (value: string) => void }) {
async () => {
const result = await sdk.client.find.files({
query: store.filter,
sessionID: props.sessionID,
})
if (result.error) return []
const sliced = (result.data ?? []).slice(0, 5)
Expand Down
Loading
Loading