Spaces:
Running
Running
| /** | |
| * Local LeRobot dataset roots (absolute filesystem paths) are encoded in URLs as | |
| * `/local/<base64url(utf8 path)>/episode_0`. File bytes are served via | |
| * `/api/local-dataset/file?root=...&rel=...`. | |
| */ | |
| export const LOCAL_ORG = "local"; | |
| export const LOCAL_REPO_PREFIX = `${LOCAL_ORG}/`; | |
| function utf8ToBase64Url(s: string): string { | |
| const bytes = new TextEncoder().encode(s); | |
| let bin = ""; | |
| for (let i = 0; i < bytes.length; i++) { | |
| bin += String.fromCharCode(bytes[i]!); | |
| } | |
| const b64 = | |
| typeof btoa !== "undefined" | |
| ? btoa(bin) | |
| : Buffer.from(bytes).toString("base64"); | |
| return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); | |
| } | |
| function base64UrlToUtf8(s: string): string { | |
| const pad = s.length % 4 === 0 ? "" : "=".repeat(4 - (s.length % 4)); | |
| const b64 = s.replace(/-/g, "+").replace(/_/g, "/") + pad; | |
| let bin: string; | |
| if (typeof atob !== "undefined") { | |
| bin = atob(b64); | |
| } else { | |
| bin = Buffer.from(b64, "base64").toString("binary"); | |
| } | |
| const bytes = new Uint8Array(bin.length); | |
| for (let i = 0; i < bin.length; i++) { | |
| bytes[i] = bin.charCodeAt(i); | |
| } | |
| return new TextDecoder().decode(bytes); | |
| } | |
| export function normalizeUserLocalPathInput(input: string): string { | |
| const t = input.trim(); | |
| if (t.startsWith("file://")) { | |
| try { | |
| const u = new URL(t); | |
| return decodeURIComponent(u.pathname); | |
| } catch { | |
| return t; | |
| } | |
| } | |
| return t; | |
| } | |
| export function looksLikeAbsoluteFilesystemPath(input: string): boolean { | |
| const t = normalizeUserLocalPathInput(input); | |
| if (!t) return false; | |
| if (t.startsWith("/")) return true; | |
| return /^[A-Za-z]:[\\/]/.test(t); | |
| } | |
| export function encodeLocalDatasetRoot(absolutePath: string): string { | |
| return utf8ToBase64Url(absolutePath); | |
| } | |
| export function decodeLocalDatasetSegment( | |
| encodedSegment: string, | |
| ): string | null { | |
| if (!encodedSegment) return null; | |
| try { | |
| return base64UrlToUtf8(encodedSegment); | |
| } catch { | |
| return null; | |
| } | |
| } | |
| export function localRepoIdFromAbsolutePath(absolutePath: string): string { | |
| return `${LOCAL_REPO_PREFIX}${encodeLocalDatasetRoot(absolutePath)}`; | |
| } | |
| export function isLocalRepoId(repoId: string): boolean { | |
| return ( | |
| repoId.startsWith(LOCAL_REPO_PREFIX) && | |
| repoId.length > LOCAL_REPO_PREFIX.length | |
| ); | |
| } | |
| export function localDatasetFileApiPath( | |
| rootEncoded: string, | |
| relPath: string, | |
| ): string { | |
| const q = new URLSearchParams({ | |
| root: rootEncoded, | |
| rel: relPath, | |
| }); | |
| return `/api/local-dataset/file?${q.toString()}`; | |
| } | |
| /** Parse our local file API URL (absolute or relative) for server-side fs shortcut. */ | |
| export function tryParseLocalDatasetFileApiUrl( | |
| url: string, | |
| ): { rootEncoded: string; relPath: string } | null { | |
| const marker = "/api/local-dataset/file"; | |
| const idx = url.indexOf(marker); | |
| if (idx === -1) return null; | |
| const after = url.slice(idx + marker.length); | |
| const queryStart = after.indexOf("?"); | |
| if (queryStart === -1) return null; | |
| const search = after.slice(queryStart + 1); | |
| try { | |
| const params = new URLSearchParams(search); | |
| const root = params.get("root"); | |
| const rel = params.get("rel"); | |
| if (!root || !rel) return null; | |
| return { rootEncoded: root, relPath: rel }; | |
| } catch { | |
| return null; | |
| } | |
| } | |