Improve workspace sidebar and file panel

This commit is contained in:
武阳
2026-05-06 17:46:49 +08:00
parent d9a8110b7c
commit 93a0eb74d7
6 changed files with 702 additions and 83 deletions
+52 -3
View File
@@ -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";