mirror of
https://github.com/luckyyzh/pi-agent-integrated.git
synced 2026-10-03 02:59:35 +00:00
feat: integrate Pi backend and Pi Web
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { stat } from "fs/promises";
|
||||
import {
|
||||
getBrowseStartDirectory,
|
||||
getParentDirectory,
|
||||
listDirectories,
|
||||
resolveDirectory,
|
||||
} from "@/lib/directory-browser";
|
||||
|
||||
// GET /api/cwd/browse?path=...:列出文件系统中的可读子目录。
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const requested = request.nextUrl.searchParams.get("path")?.trim();
|
||||
const candidate = getBrowseStartDirectory(requested);
|
||||
|
||||
let resolved: string;
|
||||
try {
|
||||
resolved = await resolveDirectory(candidate);
|
||||
} catch {
|
||||
return NextResponse.json({ error: "Directory does not exist" }, { status: 404 });
|
||||
}
|
||||
|
||||
|
||||
const directoryStat = await stat(resolved);
|
||||
if (!directoryStat.isDirectory()) {
|
||||
return NextResponse.json({ error: "Path is not a directory" }, { status: 400 });
|
||||
}
|
||||
|
||||
const directories = await listDirectories(resolved);
|
||||
|
||||
return NextResponse.json({
|
||||
path: resolved,
|
||||
parentPath: getParentDirectory(resolved),
|
||||
directories,
|
||||
});
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: String(error) }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { statSync, type Stats } from "fs";
|
||||
import { homedir } from "os";
|
||||
import { isAbsolute, resolve } from "path";
|
||||
import { allowFileRoot } from "@/lib/file-access";
|
||||
|
||||
function normalizeCwd(cwd: string): string {
|
||||
if (cwd === "~") return homedir();
|
||||
if (cwd.startsWith("~/")) return resolve(homedir(), cwd.slice(2));
|
||||
return isAbsolute(cwd) ? cwd : resolve(cwd);
|
||||
}
|
||||
|
||||
// POST /api/cwd/validate body: { cwd: string }
|
||||
// Validates a candidate workspace before the UI selects it.
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const body = await req.json() as { cwd?: unknown };
|
||||
const cwd = typeof body.cwd === "string" ? body.cwd.trim() : "";
|
||||
|
||||
if (!cwd) {
|
||||
return NextResponse.json({ error: "Path is required" }, { status: 400 });
|
||||
}
|
||||
|
||||
const normalizedCwd = normalizeCwd(cwd);
|
||||
let stat: Stats;
|
||||
try {
|
||||
stat = statSync(normalizedCwd);
|
||||
} catch {
|
||||
return NextResponse.json({ error: `Directory does not exist: ${cwd}` }, { status: 400 });
|
||||
}
|
||||
|
||||
if (!stat.isDirectory()) {
|
||||
return NextResponse.json({ error: `Path is not a directory: ${cwd}` }, { status: 400 });
|
||||
}
|
||||
|
||||
allowFileRoot(normalizedCwd);
|
||||
return NextResponse.json({ success: true, cwd: normalizedCwd });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: String(error) }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user