feat(server,ui): allow OpenCode directory override via proxy path
This commit is contained in:
@@ -4,12 +4,12 @@ import { CODENOMAD_API_BASE } from "./api-client"
|
||||
class SDKManager {
|
||||
private clients = new Map<string, OpencodeClient>()
|
||||
|
||||
private key(instanceId: string, worktreeSlug: string): string {
|
||||
return `${instanceId}:${worktreeSlug || "root"}`
|
||||
private key(instanceId: string, proxyPath: string): string {
|
||||
return `${instanceId}:${normalizeProxyPath(proxyPath)}`
|
||||
}
|
||||
|
||||
createClient(instanceId: string, proxyPath: string, worktreeSlug = "root"): OpencodeClient {
|
||||
const key = this.key(instanceId, worktreeSlug)
|
||||
createClient(instanceId: string, proxyPath: string, _worktreeSlug = "root"): OpencodeClient {
|
||||
const key = this.key(instanceId, proxyPath)
|
||||
const existing = this.clients.get(key)
|
||||
if (existing) {
|
||||
return existing
|
||||
@@ -23,12 +23,12 @@ class SDKManager {
|
||||
return client
|
||||
}
|
||||
|
||||
getClient(instanceId: string, worktreeSlug = "root"): OpencodeClient | null {
|
||||
return this.clients.get(this.key(instanceId, worktreeSlug)) ?? null
|
||||
getClient(instanceId: string, proxyPath: string): OpencodeClient | null {
|
||||
return this.clients.get(this.key(instanceId, proxyPath)) ?? null
|
||||
}
|
||||
|
||||
destroyClient(instanceId: string, worktreeSlug = "root"): void {
|
||||
this.clients.delete(this.key(instanceId, worktreeSlug))
|
||||
destroyClient(instanceId: string, proxyPath: string): void {
|
||||
this.clients.delete(this.key(instanceId, proxyPath))
|
||||
}
|
||||
|
||||
destroyClientsForInstance(instanceId: string): void {
|
||||
|
||||
@@ -329,12 +329,38 @@ function buildWorktreeProxyPath(instanceId: string, slug: string): string {
|
||||
return `/workspaces/${encodeURIComponent(instanceId)}/worktrees/${encodeURIComponent(normalizedSlug)}/instance`
|
||||
}
|
||||
|
||||
function encodeBase64UrlUtf8(input: string): string {
|
||||
const bytes = new TextEncoder().encode(input)
|
||||
// Convert bytes -> base64 (btoa expects a binary string)
|
||||
let binary = ""
|
||||
const chunkSize = 0x8000
|
||||
for (let i = 0; i < bytes.length; i += chunkSize) {
|
||||
const chunk = bytes.subarray(i, i + chunkSize)
|
||||
binary += String.fromCharCode(...chunk)
|
||||
}
|
||||
const base64 = btoa(binary)
|
||||
// base64 -> base64url (strip padding)
|
||||
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "")
|
||||
}
|
||||
|
||||
function buildWorktreeProxyPathWithDirectoryOverride(instanceId: string, slug: string, directory: string): string {
|
||||
const base = buildWorktreeProxyPath(instanceId, slug)
|
||||
const encoded = encodeBase64UrlUtf8(directory)
|
||||
return `${base}/__dir/${encoded}`
|
||||
}
|
||||
|
||||
function getOrCreateWorktreeClient(instanceId: string, slug: string): OpencodeClient {
|
||||
const normalized = normalizeWorktreeSlug(instanceId, slug || "root")
|
||||
const proxyPath = buildWorktreeProxyPath(instanceId, normalized)
|
||||
return sdkManager.createClient(instanceId, proxyPath, normalized)
|
||||
}
|
||||
|
||||
function getOrCreateWorktreeClientWithDirectoryOverride(instanceId: string, slug: string, directory: string): OpencodeClient {
|
||||
const normalized = normalizeWorktreeSlug(instanceId, slug || "root")
|
||||
const proxyPath = buildWorktreeProxyPathWithDirectoryOverride(instanceId, normalized, directory)
|
||||
return sdkManager.createClient(instanceId, proxyPath, normalized)
|
||||
}
|
||||
|
||||
function getRootClient(instanceId: string): OpencodeClient {
|
||||
return getOrCreateWorktreeClient(instanceId, "root")
|
||||
}
|
||||
@@ -359,7 +385,9 @@ export {
|
||||
removeParentSessionMapping,
|
||||
getWorktreeSlugForDirectory,
|
||||
buildWorktreeProxyPath,
|
||||
buildWorktreeProxyPathWithDirectoryOverride,
|
||||
getOrCreateWorktreeClient,
|
||||
getOrCreateWorktreeClientWithDirectoryOverride,
|
||||
getRootClient,
|
||||
createWorktree,
|
||||
deleteWorktree,
|
||||
|
||||
Reference in New Issue
Block a user