This commit is contained in:
bluelovers 2026-06-22 03:00:08 -04:00 committed by GitHub
commit d2726892cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 84 additions and 6 deletions

View file

@ -220,6 +220,13 @@ export interface FileSystemFileContentResponse {
encoding: "utf-8" | "base64"
}
export interface DetectPathExistingInRecentResponse {
exists: boolean
currentPath: string
currentReal: string
foundResult: string | undefined
}
export interface ConfigFileDescriptor {
id: string
label: string

View file

@ -1,6 +1,8 @@
import { FastifyInstance } from "fastify"
import { z } from "zod"
import fs from "node:fs/promises"
import { FileSystemBrowser } from "../../filesystem/browser"
import { RecentFolder, RecentFolderSchema } from '../../config/schema'
interface RouteDeps {
fileSystemBrowser: FileSystemBrowser
@ -21,6 +23,11 @@ const FilesystemFileContentQuerySchema = z.object({
encoding: z.enum(["utf-8", "base64"]).optional(),
})
const FilesystemFileRealpathQuerySchema = z.object({
currentPath: z.string(),
recentPaths: z.array(z.string()).default([]),
})
export function registerFilesystemRoutes(app: FastifyInstance, deps: RouteDeps) {
app.get("/api/filesystem", async (request, reply) => {
const query = FilesystemQuerySchema.parse(request.query ?? {})
@ -66,4 +73,39 @@ export function registerFilesystemRoutes(app: FastifyInstance, deps: RouteDeps)
reply.code(400).type("text/plain").send((error as Error).message)
}
})
app.post("/api/filesystem/detect-path-existing-in-recent", async (request, reply) => {
const query = FilesystemFileRealpathQuerySchema.parse(request.body ?? {})
try {
const currentPath = query.currentPath
const currentReal = await fs.realpath(currentPath)
let exists = false
let foundResult: string | undefined
const fn = async (path: string) => {
await fs.access(path, fs.constants.F_OK)
return currentReal === await fs.realpath(path)
}
for (const path of query.recentPaths) {
if (currentPath === path || currentReal === path || await fn(path).catch(() => false)) {
exists = true
foundResult = path
break
}
}
return {
exists,
currentPath,
currentReal,
foundResult
}
} catch (error) {
reply.code(400).type("text/plain").send((error as Error).message)
}
})
}

View file

@ -31,7 +31,7 @@ import {
showFolderSelection,
setShowFolderSelection,
} from "./stores/ui"
import { useConfig } from "./stores/preferences"
import { recentFolders, useConfig } from "./stores/preferences"
import {
createInstance,
getExistingInstanceForFolder,
@ -70,6 +70,9 @@ import {
selectInstanceTab,
selectSidecarTab,
} from "./stores/app-tabs"
import { serverApi } from './lib/api-client'
import { RecentFolder } from '../../server/src/api-types'
import { Instance } from './types/instance'
const log = getLogger("actions")
@ -280,13 +283,31 @@ const App: Component = () => {
if (!folderPath) {
return
}
let existingInstance = getExistingInstanceForFolder(folderPath)
if (!existingInstance) {
const detectResult = await serverApi.detectPathExistingInRecent(folderPath, [
...(Array.from(instances().values()) as Instance[]).reduce((acc: string[], instance: Instance) => {
if (instance.status === "stopped") return acc
acc.push(instance.folder)
return acc
}, [] as string[]),
...recentFolders().map((folder: RecentFolder) => folder.path),
]).catch(() => null)
if (detectResult?.exists) {
folderPath = detectResult.foundResult!
existingInstance = getExistingInstanceForFolder(folderPath)
}
}
const selectedBinary = binaryPath || serverSettings().opencodeBinary || "opencode"
const projectName = getProjectNameForFolder(folderPath)
recordWorkspaceLaunch(folderPath, selectedBinary)
clearLaunchError()
if (!options?.forceNew) {
const existingInstance = getExistingInstanceForFolder(folderPath)
if (existingInstance) {
setAlreadyOpenFolderChoice({ folderPath, binaryPath: selectedBinary, instanceId: existingInstance.id })
return
@ -500,7 +521,7 @@ const App: Component = () => {
const tauriBridge = (window as { __TAURI__?: { event?: { listen: (event: string, handler: (event: { payload: unknown }) => void) => Promise<() => void> } } }).__TAURI__
if (tauriBridge?.event) {
let unlistenMenu: (() => void) | null = null
tauriBridge.event.listen("menu:newInstance", () => {
handleNewInstanceRequest()
}).then((unlisten) => {
@ -542,7 +563,7 @@ const App: Component = () => {
<p class="text-xs font-medium text-muted uppercase tracking-wide mb-1">{t("app.launchError.binaryPathLabel")}</p>
<p class="text-sm font-mono text-primary break-all">{launchErrorPath()}</p>
</div>
<Show when={launchErrorMessage()}>
<div class="rounded-lg border border-base bg-surface-secondary p-4 flex flex-col gap-2 flex-1 min-h-0">
<p class="text-xs font-medium text-muted uppercase tracking-wide">{t("app.launchError.errorOutputLabel")}</p>
@ -667,7 +688,7 @@ const App: Component = () => {
</div>
</div>
</Show>
<SettingsScreen />
<SideCarPickerDialog open={sidecarPickerOpen()} onClose={() => setSidecarPickerOpen(false)} onOpenSidecar={handleOpenSidecar} />
<Show when={alreadyOpenFolderChoice()}>
@ -694,7 +715,7 @@ const App: Component = () => {
</Dialog.Portal>
</Dialog>
</Show>
<AlertDialog />
<Toaster

View file

@ -42,6 +42,8 @@ import type {
WorktreeCreateRequest,
WorktreeGitDiffResponse,
WorktreeGitStatusResponse,
RecentFolder,
DetectPathExistingInRecentResponse,
} from "../../../server/src/api-types"
import { getClientIdentity } from "./client-identity"
import { getLogger } from "./logger"
@ -484,6 +486,12 @@ export const serverApi = {
}
return request<FileSystemFileContentResponse>(`/api/filesystem/files/content?${params.toString()}`)
},
detectPathExistingInRecent(currentPath: string, recentPaths: string[]): Promise<DetectPathExistingInRecentResponse> {
return request<DetectPathExistingInRecentResponse>(`/api/filesystem/detect-path-existing-in-recent`, {
method: "POST",
body: JSON.stringify({ currentPath, recentPaths }),
})
},
readInstanceData(id: string): Promise<InstanceData> {
return request<InstanceData>(`/api/storage/instances/${encodeURIComponent(id)}`)
},