feat(frontend): 手工合并 layout、脚本与上传接口

This commit is contained in:
肖应宇 2026-03-28 22:49:47 +08:00
parent e6183e84fc
commit c67dad6db5
4 changed files with 22 additions and 22 deletions

View File

@ -6,10 +6,11 @@
"scripts": {
"demo:save": "node scripts/save-demo.js",
"build": "next build",
"check": "next lint && tsc --noEmit",
"check": "eslint . --ext .ts,.tsx && tsc --noEmit",
"dev": "next dev --turbo",
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
"format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
"format:write": "prettier --write .",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix",
"preview": "next build && next start",
@ -70,7 +71,7 @@
"marked": "^17.0.5",
"motion": "^12.26.2",
"nanoid": "^5.1.6",
"next": "^16.1.4",
"next": "^16.1.7",
"next-themes": "^0.4.6",
"nuxt-og-image": "^5.1.13",
"ogl": "^1.0.11",

View File

@ -2,7 +2,6 @@ import "@/styles/globals.css";
import "katex/dist/katex.min.css";
import { type Metadata } from "next";
import { Geist } from "next/font/google";
import { ThemeProvider } from "@/components/theme-provider";
import { I18nProvider } from "@/core/i18n/context";
@ -13,22 +12,12 @@ export const metadata: Metadata = {
description: "A LangChain-based framework for building super agents.",
};
const geist = Geist({
subsets: ["latin"],
variable: "--font-geist-sans",
});
export default async function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
const locale = await detectLocaleServer();
return (
<html
lang={locale}
className={geist.variable + ""}
suppressContentEditableWarning
suppressHydrationWarning
>
<html lang={locale} suppressContentEditableWarning suppressHydrationWarning>
<body>
<ThemeProvider attribute="class" enableSystem disableTransitionOnChange>
<I18nProvider initialLocale={locale}>{children}</I18nProvider>

View File

@ -6,6 +6,7 @@ import { useCallback, useEffect, useLayoutEffect, useState } from "react";
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
import { Toaster } from "@/components/ui/sonner";
import { CommandPalette } from "@/components/workspace/command-palette";
import { WorkspaceSidebar } from "@/components/workspace/workspace-sidebar";
import { getLocalSettings, useLocalSettings } from "@/core/settings";
@ -42,10 +43,10 @@ export default function WorkspaceLayout({
open={open}
onOpenChange={handleOpenChange}
>
{/* MARK: 生产环境下必须注释才能提交!!!! */}
{/* {!isSkillMode && <WorkspaceSidebar className="" />} */}
{!isSkillMode && <WorkspaceSidebar className="" />}
<SidebarInset className="min-w-0">{children}</SidebarInset>
</SidebarProvider>
<CommandPalette />
<Toaster
position="top-center"
toastOptions={{

View File

@ -31,6 +31,16 @@ export interface ListFilesResponse {
export type UploadTarget = "skill";
async function readErrorDetail(
response: Response,
fallback: string,
): Promise<string> {
const error = await response
.json()
.catch(() => ({ detail: fallback }));
return error.detail ?? fallback;
}
/**
* Upload files to a thread
*/
@ -58,10 +68,7 @@ export async function uploadFiles(
);
if (!response.ok) {
const error = await response
.json()
.catch(() => ({ detail: "Upload failed" }));
throw new Error(error.detail ?? "Upload failed");
throw new Error(await readErrorDetail(response, "Upload failed"));
}
return response.json();
@ -78,7 +85,9 @@ export async function listUploadedFiles(
);
if (!response.ok) {
throw new Error("Failed to list uploaded files");
throw new Error(
await readErrorDetail(response, "Failed to list uploaded files"),
);
}
return response.json();
@ -99,7 +108,7 @@ export async function deleteUploadedFile(
);
if (!response.ok) {
throw new Error("Failed to delete file");
throw new Error(await readErrorDetail(response, "Failed to delete file"));
}
return response.json();