chore: 提交本地修改
This commit is contained in:
1 parent
229830ee89
commit
2862eee33b
19 files changed
+78
-218
No files matched your search
@@ -65,28 +65,6 @@ import { usePublishSquares } from "@/core/system-settings/hooks";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
* Turn the admin-authored SOUL.md markdown into a clean, readable profile blurb
|
||||
* for the narrow panel. The view mode is a profile card, not a document view —
|
||||
* so we strip markdown syntax (headings, emphasis, inline code, list bullets,
|
||||
* blockquotes) rather than rendering it, keeping the line structure intact.
|
||||
*/
|
||||
function cleanProfileText(raw: string): string {
|
||||
return raw
|
||||
.split("\n")
|
||||
.map((line) =>
|
||||
line
|
||||
.replace(/^\s{0,3}#{1,6}\s*/, "")
|
||||
.replace(/^\s{0,3}>\s?/, "")
|
||||
.replace(/^(\s*)[-*+]\s+/, "$1• ")
|
||||
.replace(/(\*\*|__)(.*?)\1/g, "$2")
|
||||
.replace(/(\*|_)(.*?)\1/g, "$2")
|
||||
.replace(/`([^`]+)`/g, "$1"),
|
||||
)
|
||||
.join("\n")
|
||||
.replace(/\n{3,}/g, "\n\n")
|
||||
.trim();
|
||||
}
|
||||
|
||||
/** Local edit-mode draft — committed in one `updateAgent` call on 保存. */
|
||||
interface AgentDraft {
|
||||
@@ -232,9 +210,6 @@ export function AgentDetailPanel({
|
||||
() => normalizeAgentQuestions(agent?.common_questions),
|
||||
[agent?.common_questions],
|
||||
);
|
||||
const soulPreview = agent?.soul?.trim()
|
||||
? cleanProfileText(desensitize(agent.soul))
|
||||
: undefined;
|
||||
|
||||
function beginEdit() {
|
||||
if (!agent || !canEdit) return;
|
||||
@@ -609,31 +584,6 @@ export function AgentDetailPanel({
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* ── SOUL / 人设 ────────────────────────────────────────────────── */}
|
||||
{(editing || soulPreview) && (
|
||||
<Section
|
||||
icon={<SparklesIcon className="size-3.5" />}
|
||||
title="人设(SOUL)"
|
||||
>
|
||||
{editing && draft ? (
|
||||
<Textarea
|
||||
value={draft.soul}
|
||||
onChange={(e) =>
|
||||
setDraft({ ...draft, soul: e.currentTarget.value })
|
||||
}
|
||||
placeholder="输入 SOUL.md 内容"
|
||||
className="max-h-[45vh] min-h-48 resize-y font-mono text-xs"
|
||||
/>
|
||||
) : (
|
||||
// Viewport-relative cap: the SOUL preview expands with the screen
|
||||
// (taller than the old fixed 240px box) but never swallows the
|
||||
// whole panel — long content still scrolls inside.
|
||||
<p className="text-muted-foreground max-h-[40vh] overflow-y-auto whitespace-pre-wrap text-sm leading-relaxed">
|
||||
{soulPreview}
|
||||
</p>
|
||||
)}
|
||||
</Section>
|
||||
)}
|
||||
|
||||
{/* ── 常用问题 ───────────────────────────────────────────────────── */}
|
||||
{(editing || questions.length > 0 || canEdit) && (
|
||||
|
||||
@@ -4,16 +4,15 @@ import {
|
||||
ArrowDownIcon,
|
||||
Code2Icon,
|
||||
CopyIcon,
|
||||
DownloadIcon,
|
||||
EyeIcon,
|
||||
FileType2Icon,
|
||||
LoaderIcon,
|
||||
PackageIcon,
|
||||
SaveIcon,
|
||||
SquareArrowOutUpRightIcon,
|
||||
UploadCloudIcon,
|
||||
XIcon,
|
||||
} from "lucide-react";
|
||||
DownloadIcon,
|
||||
EyeIcon,
|
||||
FileType2Icon,
|
||||
LoaderIcon,
|
||||
PackageIcon,
|
||||
SaveIcon,
|
||||
UploadCloudIcon,
|
||||
XIcon,
|
||||
} from "lucide-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import type { AnchorHTMLAttributes, HTMLAttributes, ReactNode } from "react";
|
||||
@@ -38,12 +37,11 @@ import {
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||
import { CodeEditor } from "@/components/workspace/code-editor";
|
||||
import { publishArtifactToKnowledge } from "@/core/agents/api";
|
||||
import { useAgent } from "@/core/agents/hooks";
|
||||
import { apiFetch } from "@/core/api";
|
||||
import {
|
||||
downloadArtifactFile,
|
||||
openArtifactInNewTab,
|
||||
} from "@/core/artifacts/download";
|
||||
import { useAgent } from "@/core/agents/hooks";
|
||||
import { apiFetch } from "@/core/api";
|
||||
import {
|
||||
downloadArtifactFile,
|
||||
} from "@/core/artifacts/download";
|
||||
import {
|
||||
useArtifactContent,
|
||||
useUpdateArtifactContent,
|
||||
@@ -514,32 +512,7 @@ export function ArtifactFileDetail({
|
||||
}
|
||||
}, [displayContent, filepath]);
|
||||
|
||||
const handleOpenWriteFileInNewTab = useCallback(() => {
|
||||
const source = displayContent ?? "";
|
||||
if (!source.trim()) {
|
||||
toast.error("文件内容为空,暂时无法打开");
|
||||
return;
|
||||
}
|
||||
if (language === "mermaid") {
|
||||
void openMermaidSvgInNewTab(source).catch((error) => {
|
||||
console.error("Failed to open mermaid artifact:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Failed to open artifact");
|
||||
});
|
||||
return;
|
||||
}
|
||||
const blobType =
|
||||
language === "html"
|
||||
? "text/html;charset=utf-8"
|
||||
: language === "markdown"
|
||||
? "text/markdown;charset=utf-8"
|
||||
: "text/plain;charset=utf-8";
|
||||
const blob = new Blob([source], { type: blobType });
|
||||
const url = URL.createObjectURL(blob);
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
window.setTimeout(() => URL.revokeObjectURL(url), 60_000);
|
||||
}, [displayContent, language]);
|
||||
|
||||
const handleDownloadWriteFile = useCallback(() => {
|
||||
const handleDownloadWriteFile = useCallback(() => {
|
||||
const source = displayContent ?? "";
|
||||
if (!source.trim()) {
|
||||
toast.error("文件内容为空,暂时无法下载");
|
||||
@@ -571,7 +544,7 @@ export function ArtifactFileDetail({
|
||||
|
||||
return (
|
||||
<Artifact className={cn(className)}>
|
||||
<ArtifactHeader className="grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 px-4 py-3">
|
||||
<ArtifactHeader className="flex flex-wrap items-center gap-3 px-4 py-3">
|
||||
<div className="flex min-w-0 items-center gap-2">
|
||||
<div className="bg-muted/65 inline-flex min-w-0 items-center rounded-full border border-black/6 p-1 shadow-sm dark:border-white/8">
|
||||
<span className="bg-background text-muted-foreground inline-flex h-7 shrink-0 items-center rounded-full border border-black/6 px-2.5 text-[10px] font-semibold tracking-[0.16em] dark:border-white/8">
|
||||
@@ -601,7 +574,7 @@ export function ArtifactFileDetail({
|
||||
</ArtifactTitle>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-center">
|
||||
<div className="flex w-full items-center justify-center md:w-auto md:flex-1">
|
||||
{isSupportPreview && (
|
||||
<div className="flex items-center gap-2">
|
||||
<ToggleGroup
|
||||
@@ -644,8 +617,8 @@ export function ArtifactFileDetail({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<ArtifactActions className="bg-muted/45 rounded-full border border-black/6 p-1 dark:border-white/8">
|
||||
<div className="flex w-full items-center justify-end gap-2 md:ml-auto md:w-auto">
|
||||
<ArtifactActions className="bg-muted/45 max-w-full flex-wrap justify-end rounded-3xl border border-black/6 p-1 dark:border-white/8">
|
||||
{canPublishToKnowledge && (
|
||||
<ArtifactAction
|
||||
icon={isPublishingToKnowledge ? LoaderIcon : UploadCloudIcon}
|
||||
@@ -678,45 +651,6 @@ export function ArtifactFileDetail({
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<ArtifactAction
|
||||
icon={SquareArrowOutUpRightIcon}
|
||||
label={t.common.openInNewWindow}
|
||||
tooltip={t.common.openInNewWindow}
|
||||
onClick={async () => {
|
||||
if (useWriteFileStreaming) {
|
||||
handleOpenWriteFileInNewTab();
|
||||
return;
|
||||
}
|
||||
if (language === "mermaid") {
|
||||
try {
|
||||
await openMermaidSvgInNewTab(displayContent ?? "");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Failed to open artifact",
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await openArtifactInNewTab({
|
||||
filepath,
|
||||
threadId,
|
||||
isMock,
|
||||
publicShareCode,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Failed to open artifact",
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{isCodeFile && (
|
||||
<ArtifactAction
|
||||
icon={CopyIcon}
|
||||
|
||||
@@ -1,53 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { Database } from "lucide-react";
|
||||
|
||||
import {
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { useKnowledgeRagEnabled } from "@/core/settings";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { Tooltip } from "./tooltip";
|
||||
|
||||
/**
|
||||
* Sidebar toggle for knowledge-base RAG injection (phase 2).
|
||||
*
|
||||
* Session-wide and in-memory only: while enabled, every conversation sends
|
||||
* ``context.knowledge_rag_enabled`` as ``runtime.context`` so
|
||||
* ``KnowledgeRagMiddleware`` injects recalled knowledge before each model
|
||||
* call. A page reload resets the switch to off.
|
||||
*/
|
||||
export function KnowledgeRagToggle({ className }: { className?: string }) {
|
||||
const [enabled, setEnabled] = useKnowledgeRagEnabled();
|
||||
|
||||
return (
|
||||
<SidebarMenuItem>
|
||||
<Tooltip
|
||||
content={
|
||||
enabled
|
||||
? "知识库召回:已开启(本次会话内所有对话默认开启)"
|
||||
: "知识库召回:已关闭"
|
||||
}
|
||||
>
|
||||
<SidebarMenuButton
|
||||
isActive={enabled}
|
||||
onClick={() => setEnabled(!enabled)}
|
||||
className={className}
|
||||
>
|
||||
<Database />
|
||||
<span>知识库召回</span>
|
||||
<span
|
||||
className={cn(
|
||||
"ml-auto text-xs",
|
||||
enabled ? "text-primary" : "text-muted-foreground/70",
|
||||
)}
|
||||
>
|
||||
{enabled ? "已开启" : "已关闭"}
|
||||
</span>
|
||||
</SidebarMenuButton>
|
||||
</Tooltip>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
export function KnowledgeRagToggle({
|
||||
className: _className,
|
||||
}: {
|
||||
className?: string;
|
||||
}) {
|
||||
void _className;
|
||||
return null;
|
||||
}
|
||||
Reference in new issue
Block a user