worktrees - Implementation

This commit is contained in:
Shantur Rathore
2026-02-07 11:46:56 +00:00
parent 6f73adaef6
commit ef14b9acb6
17 changed files with 1399 additions and 72 deletions

View File

@@ -20,6 +20,9 @@ import type {
WorkspaceLogEntry,
WorkspaceEventPayload,
WorkspaceEventType,
WorktreeListResponse,
WorktreeMap,
WorktreeCreateRequest,
} from "../../../server/src/api-types"
import { getLogger } from "./logger"
@@ -127,6 +130,39 @@ export const serverApi = {
fetchWorkspaces(): Promise<WorkspaceDescriptor[]> {
return request<WorkspaceDescriptor[]>("/api/workspaces")
},
fetchWorktrees(id: string): Promise<WorktreeListResponse> {
return request<WorktreeListResponse>(`/api/workspaces/${encodeURIComponent(id)}/worktrees`)
},
createWorktree(id: string, payload: WorktreeCreateRequest): Promise<{ slug: string; directory: string; branch?: string }> {
return request<{ slug: string; directory: string; branch?: string }>(`/api/workspaces/${encodeURIComponent(id)}/worktrees`, {
method: "POST",
body: JSON.stringify(payload),
})
},
deleteWorktree(id: string, slug: string, options?: { force?: boolean }): Promise<void> {
const params = new URLSearchParams()
if (options?.force) {
params.set("force", "true")
}
const suffix = params.toString() ? `?${params.toString()}` : ""
return request(`/api/workspaces/${encodeURIComponent(id)}/worktrees/${encodeURIComponent(slug)}${suffix}`, {
method: "DELETE",
})
},
readWorktreeMap(id: string): Promise<WorktreeMap> {
return request<WorktreeMap>(`/api/workspaces/${encodeURIComponent(id)}/worktrees/map`)
},
writeWorktreeMap(id: string, map: WorktreeMap): Promise<void> {
return request(`/api/workspaces/${encodeURIComponent(id)}/worktrees/map`, {
method: "PUT",
body: JSON.stringify(map),
})
},
createWorkspace(payload: WorkspaceCreateRequest): Promise<WorkspaceDescriptor> {
return request<WorkspaceDescriptor>("/api/workspaces", {
method: "POST",

View File

@@ -4,8 +4,13 @@ import { CODENOMAD_API_BASE } from "./api-client"
class SDKManager {
private clients = new Map<string, OpencodeClient>()
createClient(instanceId: string, proxyPath: string): OpencodeClient {
const existing = this.clients.get(instanceId)
private key(instanceId: string, worktreeSlug: string): string {
return `${instanceId}:${worktreeSlug || "root"}`
}
createClient(instanceId: string, proxyPath: string, worktreeSlug = "root"): OpencodeClient {
const key = this.key(instanceId, worktreeSlug)
const existing = this.clients.get(key)
if (existing) {
return existing
}
@@ -13,17 +18,25 @@ class SDKManager {
const baseUrl = buildInstanceBaseUrl(proxyPath)
const client = createOpencodeClient({ baseUrl })
this.clients.set(instanceId, client)
this.clients.set(key, client)
return client
}
getClient(instanceId: string): OpencodeClient | null {
return this.clients.get(instanceId) ?? null
getClient(instanceId: string, worktreeSlug = "root"): OpencodeClient | null {
return this.clients.get(this.key(instanceId, worktreeSlug)) ?? null
}
destroyClient(instanceId: string): void {
this.clients.delete(instanceId)
destroyClient(instanceId: string, worktreeSlug = "root"): void {
this.clients.delete(this.key(instanceId, worktreeSlug))
}
destroyClientsForInstance(instanceId: string): void {
for (const key of Array.from(this.clients.keys())) {
if (key === instanceId || key.startsWith(`${instanceId}:`)) {
this.clients.delete(key)
}
}
}
destroyAll(): void {