feat(client): expose v2 project APIs (#34456)

This commit is contained in:
Kit Langton 2026-06-29 14:10:11 -04:00 committed by GitHub
commit 935ac2db91
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 473 additions and 244 deletions

View file

@ -17,18 +17,18 @@ import { useCommandShortcut } from "../keymap"
import { useProject } from "../context/project"
import { Spinner } from "./spinner"
import { DialogWorkspaceFileChanges } from "./dialog-workspace-file-changes"
import type { ProjectDirectories } from "@opencode-ai/sdk/v2"
import type { ProjectDirectoriesOutput } from "@opencode-ai/client"
import { useRoute } from "../context/route"
export type MoveSessionSelection = { type: "directory"; directory: string; subdirectory: boolean } | { type: "new" }
type ProjectDirectory = ProjectDirectories[number]
type ProjectDirectory = ProjectDirectoriesOutput[number]
type DialogMoveSessionProps = {
projectID: string
current?: MoveSessionSelection
onSelect: (selection: MoveSessionSelection) => void
onCurrentChange?: (selection: MoveSessionSelection) => void
initialDirectories?: ProjectDirectory[]
initialDirectories?: ReadonlyArray<ProjectDirectory>
initialRemoving?: string
}
@ -58,12 +58,13 @@ export function DialogMoveSession(props: DialogMoveSessionProps) {
// A failed current-checkout lookup only affects which row is highlighted, so
// swallow it and let the directory list render without a current marker.
// Once the current project is known, a mismatch is a guaranteed miss.
const [loadedProject] = createResource(
() => (projectContext.project() === props.projectID ? undefined : props.projectID),
() => (projectContext.project() === undefined ? props.projectID : undefined),
(projectID) =>
sdk.client.project
.current({}, { throwOnError: true })
.then((result) => (result.data?.id === projectID ? result.data.worktree : undefined))
sdk.api.project
.current({ location: { directory: projectContext.instance.directory() || paths.cwd } })
.then((project) => (project.id === projectID ? project.directory : undefined))
.catch(() => undefined),
)
const currentCheckout = createMemo(() => {
@ -73,15 +74,19 @@ export function DialogMoveSession(props: DialogMoveSessionProps) {
const [directories, { refetch }] = createResource(
() => (props.initialRemoving ? undefined : props.projectID),
async (projectID, info): Promise<ProjectDirectory[] | undefined> => {
async (projectID, info): Promise<ReadonlyArray<ProjectDirectory> | undefined> => {
try {
const location = { directory: projectContext.instance.directory() || paths.cwd }
await sdk.api.projectCopies.refresh({
projectID,
location: { directory: projectContext.instance.directory() || paths.cwd },
location,
})
const directories = await sdk.api.project.directories({
projectID,
location,
})
const directories = await sdk.client.project.directories({ projectID }, { throwOnError: true })
setLoadError(undefined)
return directories.data ?? []
return directories
} catch (error) {
setLoadError(error)
// An initial load with no data surfaces the inline error view below. A

View file

@ -37,18 +37,17 @@ export const { use: useProject, provider: ProjectProvider } = createSimpleContex
async function sync() {
const workspace = store.workspace.current
const location = { workspace }
const [instancePath, project] = await Promise.all([
sdk.client.path.get({ workspace }),
sdk.client.project.current({ workspace }),
sdk.api.project.current({ location }),
])
const directories = project.data?.id
? await sdk.client.project.directories({ projectID: project.data.id, workspace })
: undefined
const directories = await sdk.api.project.directories({ projectID: project.id, location })
batch(() => {
setStore("instance", "path", reconcile(instancePath.data || defaultPath))
setStore("project", "id", project.data?.id)
setStore("project", "worktree", project.data?.worktree)
setStore("project", "mainDir", directories?.data?.findLast((item) => item.strategy === undefined)?.directory)
setStore("project", "id", project.id)
setStore("project", "worktree", project.directory)
setStore("project", "mainDir", directories.findLast((item) => item.strategy === undefined)?.directory)
})
}