Improve workspace sidebar and file panel
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { readFile, stat } from "node:fs/promises";
|
||||
import { readdir, readFile, stat } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { accountBaseRoot, getCurrentAccount } from "@/lib/claw-auth";
|
||||
import {
|
||||
accountBaseRoot,
|
||||
accountSessionInputRoot,
|
||||
accountSessionOutputRoot,
|
||||
getCurrentAccount,
|
||||
} from "@/lib/claw-auth";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
|
||||
@@ -11,8 +16,15 @@ export async function GET(req: Request) {
|
||||
|
||||
const url = new URL(req.url);
|
||||
const requestedPath = url.searchParams.get("path");
|
||||
const sessionId = url.searchParams.get("session_id");
|
||||
if (!requestedPath && sessionId) {
|
||||
return Response.json({
|
||||
input: await listSessionFiles(account.id, sessionId, "input"),
|
||||
output: await listSessionFiles(account.id, sessionId, "output"),
|
||||
});
|
||||
}
|
||||
if (!requestedPath) {
|
||||
return Response.json({ error: "缺少文件路径" }, { status: 400 });
|
||||
return Response.json({ error: "缺少文件路径或会话 ID" }, { status: 400 });
|
||||
}
|
||||
|
||||
const accountRoot = path.resolve(accountBaseRoot(account.id));
|
||||
@@ -38,6 +50,43 @@ export async function GET(req: Request) {
|
||||
}
|
||||
}
|
||||
|
||||
async function listSessionFiles(
|
||||
accountId: string,
|
||||
sessionId: string,
|
||||
kind: "input" | "output",
|
||||
) {
|
||||
const accountRoot = path.resolve(accountBaseRoot(accountId));
|
||||
const dir =
|
||||
kind === "input"
|
||||
? accountSessionInputRoot(accountId, sessionId)
|
||||
: accountSessionOutputRoot(accountId, sessionId);
|
||||
const resolvedDir = path.resolve(dir);
|
||||
if (!resolvedDir.startsWith(`${accountRoot}${path.sep}`)) return [];
|
||||
|
||||
try {
|
||||
const entries = await readdir(resolvedDir, { withFileTypes: true });
|
||||
const files = await Promise.all(
|
||||
entries
|
||||
.filter((entry) => entry.isFile())
|
||||
.map(async (entry) => {
|
||||
const filePath = path.join(resolvedDir, entry.name);
|
||||
const fileStat = await stat(filePath);
|
||||
return {
|
||||
name: entry.name,
|
||||
path: filePath,
|
||||
kind,
|
||||
size: fileStat.size,
|
||||
modified_at: fileStat.mtime.toISOString(),
|
||||
download_url: `/api/claw/files?path=${encodeURIComponent(filePath)}`,
|
||||
};
|
||||
}),
|
||||
);
|
||||
return files.sort((a, b) => b.modified_at.localeCompare(a.modified_at));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function contentTypeFor(filePath: string) {
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
if (ext === ".json") return "application/json; charset=utf-8";
|
||||
|
||||
Reference in New Issue
Block a user