Extend the existing NewSpaceDialog project flow so an optional host folder becomes the space workspace root. When .git metadata is present, remote URL, default branch, and head commit are stored on the space. Team Computer file APIs expose the linked folder under project/ without a second VCS stack. Desktop adds a native folder picker; web falls back to an absolute path field. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
53 lines
1.9 KiB
TypeScript
53 lines
1.9 KiB
TypeScript
import { readdir, readFile, stat } from "node:fs/promises";
|
|
import type { ComputerFileEntry } from "@rakazo/adapter-kit";
|
|
import { normalizeWorkspacePath } from "./computer-support.js";
|
|
import {
|
|
isProjectWorkspacePath,
|
|
projectWorkspaceRelativePath,
|
|
resolveProjectHostPath,
|
|
} from "./project-workspace-path.js";
|
|
|
|
export async function listProjectWorkspaceFiles(
|
|
workspaceRoot: string,
|
|
storedPath: string,
|
|
): Promise<ComputerFileEntry[]> {
|
|
if (!isProjectWorkspacePath(storedPath)) {
|
|
throw new Error("Path is not under the project workspace");
|
|
}
|
|
const hostDirectory = resolveProjectHostPath(workspaceRoot, storedPath);
|
|
const relativeDirectory = projectWorkspaceRelativePath(storedPath);
|
|
const entries = await readdir(hostDirectory, { withFileTypes: true });
|
|
const listed = await Promise.all(
|
|
entries.map(async (entry) => {
|
|
const childHost = resolveProjectHostPath(
|
|
workspaceRoot,
|
|
relativeDirectory ? `project/${relativeDirectory}/${entry.name}` : `project/${entry.name}`,
|
|
);
|
|
const info = await stat(childHost);
|
|
const childStored = normalizeWorkspacePath(
|
|
relativeDirectory ? `project/${relativeDirectory}/${entry.name}` : `project/${entry.name}`,
|
|
);
|
|
return {
|
|
path: childStored,
|
|
kind: info.isDirectory() ? ("dir" as const) : ("file" as const),
|
|
size: info.size,
|
|
...(info.isFile() && info.mode & 0o100 ? { executable: true } : {}),
|
|
};
|
|
}),
|
|
);
|
|
return listed;
|
|
}
|
|
|
|
export async function readProjectWorkspaceFile(
|
|
workspaceRoot: string,
|
|
storedPath: string,
|
|
options?: { maxBytes?: number },
|
|
): Promise<Uint8Array> {
|
|
const hostPath = resolveProjectHostPath(workspaceRoot, storedPath);
|
|
const info = await stat(hostPath);
|
|
if (options?.maxBytes !== undefined && info.size > options.maxBytes) {
|
|
throw new Error(`computer file exceeds ${options.maxBytes} bytes`);
|
|
}
|
|
return new Uint8Array(await readFile(hostPath));
|
|
}
|