敏感词
This commit is contained in:
1 parent
6396ccc701
commit
f472bba9f0
38 files changed
+540
-173
No files matched your search
@@ -400,63 +400,26 @@ export function PageSidebar({
|
||||
onOpenChange={setNotificationOpen}
|
||||
/>
|
||||
<aside
|
||||
className={`fixed left-0 top-0 z-40 flex h-screen flex-col overflow-hidden shadow-sm theme-transition transition-all duration-300 ${
|
||||
className={`fixed left-0 top-16 z-40 flex h-[calc(100vh-4rem)] flex-col overflow-hidden shadow-sm theme-transition transition-all duration-300 ${
|
||||
isDark
|
||||
? "border-r border-blue-800/30 bg-slate-900"
|
||||
: "border-r border-red-100 bg-white"
|
||||
} ${collapsed ? "w-16" : "w-64"}`}
|
||||
>
|
||||
<div
|
||||
className={`flex h-16 items-center theme-transition ${
|
||||
isDark ? "border-b border-blue-800/30" : "border-b border-red-100"
|
||||
} ${collapsed ? "justify-center px-2" : "justify-between px-6"}`}
|
||||
<button
|
||||
type="button"
|
||||
onClick={onToggleCollapsed}
|
||||
title={collapsed ? "展开侧边栏" : "收起侧边栏"}
|
||||
className={`absolute -right-3 top-6 z-50 flex h-6 w-6 items-center justify-center rounded-full shadow-md theme-transition ${
|
||||
isDark
|
||||
? "bg-slate-700 text-slate-300 hover:bg-slate-600"
|
||||
: "bg-white text-gray-500 hover:bg-red-50 hover:text-red-600 border border-red-100"
|
||||
}`}
|
||||
>
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<div
|
||||
className={`flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg transition-transform duration-300 ease-out ${
|
||||
isDark
|
||||
? "bg-gradient-to-br from-blue-500 to-cyan-400"
|
||||
: "bg-gradient-to-br from-red-500 to-red-400"
|
||||
}`}
|
||||
>
|
||||
<FileText className="h-4 w-4 text-white" />
|
||||
</div>
|
||||
{!collapsed && (
|
||||
<div className="overflow-hidden whitespace-nowrap animate-in fade-in-0 slide-in-from-left-2 duration-300">
|
||||
<h1
|
||||
className={`text-sm font-semibold theme-transition ${
|
||||
isDark ? "text-white" : "text-gray-900"
|
||||
}`}
|
||||
>
|
||||
CM助手
|
||||
</h1>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!collapsed && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onToggleCollapsed}
|
||||
className={iconButtonClass}
|
||||
title="Collapse sidebar"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{collapsed ? <ChevronRight className="h-3 w-3" /> : <ChevronLeft className="h-3 w-3" />}
|
||||
</button>
|
||||
|
||||
<nav className={`flex-1 overflow-y-auto ${collapsed ? "p-2" : "p-4"} space-y-2 transition-all duration-300 ease-out`}>
|
||||
{collapsed && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onToggleCollapsed}
|
||||
className={`flex w-full items-center justify-center ${iconButtonClass}`}
|
||||
title="Expand sidebar"
|
||||
>
|
||||
<ChevronRight className="h-5 w-5" />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{visibleMenuItems.map((item) =>
|
||||
item.children ? renderBranch(item) : renderLeaf(item),
|
||||
)}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { BotIcon } from "lucide-react";
|
||||
|
||||
import { type Agent } from "@/core/agents";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function AgentWelcome({
|
||||
@@ -14,8 +15,10 @@ export function AgentWelcome({
|
||||
agent: Agent | null | undefined;
|
||||
agentName: string;
|
||||
}) {
|
||||
const displayName = agent?.name ?? agentName;
|
||||
const description = agent?.description;
|
||||
const displayName = desensitize(agent?.name ?? agentName);
|
||||
const description = agent?.description
|
||||
? desensitize(agent.description)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -48,6 +48,7 @@ import type { Agent } from "@/core/agents";
|
||||
import { getStoredAuth } from "@/core/auth";
|
||||
import { useI18n } from "@/core/i18n/hooks";
|
||||
import { useSkills } from "@/core/skills/hooks";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface AgentCardProps {
|
||||
@@ -195,12 +196,12 @@ export function AgentCard({ agent }: AgentCardProps) {
|
||||
<BotIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<CardTitle className="truncate text-base" title={agent.name}>
|
||||
{agent.name}
|
||||
<CardTitle className="truncate text-base" title={desensitize(agent.name)}>
|
||||
{desensitize(agent.name)}
|
||||
</CardTitle>
|
||||
{agent.model && (
|
||||
<Badge variant="secondary" className="mt-0.5 text-xs">
|
||||
{agent.model}
|
||||
{desensitize(agent.model)}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
@@ -252,7 +253,7 @@ export function AgentCard({ agent }: AgentCardProps) {
|
||||
</div>
|
||||
{agent.description && (
|
||||
<CardDescription className="mt-2 line-clamp-2 text-sm">
|
||||
{agent.description}
|
||||
{desensitize(agent.description)}
|
||||
</CardDescription>
|
||||
)}
|
||||
</CardHeader>
|
||||
@@ -272,7 +273,7 @@ export function AgentCard({ agent }: AgentCardProps) {
|
||||
variant="outline"
|
||||
className="text-xs"
|
||||
>
|
||||
{group}
|
||||
{desensitize(group)}
|
||||
</Badge>
|
||||
))}
|
||||
{agent.skills?.map((skill) => (
|
||||
@@ -286,7 +287,7 @@ export function AgentCard({ agent }: AgentCardProps) {
|
||||
setDetailSkillName(skill);
|
||||
}}
|
||||
>
|
||||
{skill}
|
||||
{desensitize(skill)}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
@@ -377,7 +378,7 @@ export function AgentCard({ agent }: AgentCardProps) {
|
||||
<Dialog open={editOpen} onOpenChange={setEditOpen}>
|
||||
<DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>编辑智能体:{agent.name}</DialogTitle>
|
||||
<DialogTitle>编辑智能体:{desensitize(agent.name)}</DialogTitle>
|
||||
<DialogDescription>
|
||||
可以修改名称、描述、技能白名单、SOUL 内容与发布状态。
|
||||
</DialogDescription>
|
||||
@@ -428,10 +429,10 @@ export function AgentCard({ agent }: AgentCardProps) {
|
||||
size="sm"
|
||||
variant={checked ? "default" : "outline"}
|
||||
onClick={() => toggleSkill(skill.name)}
|
||||
title={skill.description}
|
||||
title={desensitize(skill.description ?? "")}
|
||||
className="h-8 max-w-[200px] rounded-r-none"
|
||||
>
|
||||
<span className="truncate">{skill.name}</span>
|
||||
<span className="truncate">{desensitize(skill.name)}</span>
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -50,6 +50,7 @@ import { installSkill } from "@/core/skills/api";
|
||||
import { streamdownPlugins } from "@/core/streamdown";
|
||||
import { checkCodeFile, getFileName } from "@/core/utils/files";
|
||||
import { env } from "@/env";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { ArtifactLink } from "../citations/artifact-link";
|
||||
@@ -608,7 +609,7 @@ export function ArtifactFileDetail({
|
||||
viewMode === "preview" &&
|
||||
(language === "markdown" || language === "html") && (
|
||||
<ArtifactFilePreview
|
||||
content={displayContent}
|
||||
content={desensitize(displayContent ?? "")}
|
||||
language={language ?? "text"}
|
||||
animated={showPreviewSwitchPulse}
|
||||
activeCursor={isApplyingEdit}
|
||||
@@ -618,7 +619,11 @@ export function ArtifactFileDetail({
|
||||
<div className="size-full">
|
||||
<CodeEditor
|
||||
className="size-full resize-none rounded-none border-none bg-transparent"
|
||||
value={displayContent ?? ""}
|
||||
value={
|
||||
canEditArtifact
|
||||
? (displayContent ?? "")
|
||||
: desensitize(displayContent ?? "")
|
||||
}
|
||||
readonly={!canEditArtifact}
|
||||
onChange={
|
||||
canEditArtifact
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
type MessageResponseProps,
|
||||
} from "@/components/ai-elements/message";
|
||||
import { streamdownPlugins } from "@/core/streamdown";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { CitationLink } from "../citations/citation-link";
|
||||
@@ -63,6 +64,8 @@ export function MarkdownContent({
|
||||
|
||||
if (!content) return null;
|
||||
|
||||
const displayContent = desensitize(content);
|
||||
|
||||
return (
|
||||
<MessageResponse
|
||||
className={className}
|
||||
@@ -70,7 +73,7 @@ export function MarkdownContent({
|
||||
rehypePlugins={rehypePlugins}
|
||||
components={components}
|
||||
>
|
||||
{content}
|
||||
{displayContent}
|
||||
</MessageResponse>
|
||||
);
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
} from "@/core/messages/utils";
|
||||
import { useRehypeSplitWordsIntoSpans } from "@/core/rehype";
|
||||
import { humanMessagePlugins } from "@/core/streamdown";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { CopyButton } from "../copy-button";
|
||||
@@ -226,7 +227,7 @@ function MessageContent_({
|
||||
<TaskTrigger title="">
|
||||
<div className="text-muted-foreground flex w-full cursor-default items-center gap-2 text-sm select-none">
|
||||
<Loader className="size-4" />
|
||||
<span>{contentToDisplay}</span>
|
||||
<span>{desensitize(contentToDisplay)}</span>
|
||||
</div>
|
||||
</TaskTrigger>
|
||||
</Task>
|
||||
@@ -240,7 +241,7 @@ function MessageContent_({
|
||||
<AIElementMessageContent className={className}>
|
||||
<Reasoning isStreaming={isLoading}>
|
||||
<ReasoningTrigger />
|
||||
<ReasoningContent>{reasoningContent}</ReasoningContent>
|
||||
<ReasoningContent>{desensitize(reasoningContent)}</ReasoningContent>
|
||||
</Reasoning>
|
||||
<MessageTokenUsage
|
||||
enabled={tokenUsageEnabled}
|
||||
@@ -259,7 +260,7 @@ function MessageContent_({
|
||||
components={components}
|
||||
parseIncompleteMarkdown={false}
|
||||
>
|
||||
{contentToDisplay}
|
||||
{desensitize(contentToDisplay)}
|
||||
</AIElementMessageResponse>
|
||||
) : null;
|
||||
return (
|
||||
|
||||
@@ -58,6 +58,7 @@ import {
|
||||
import type { AgentThread, AgentThreadState } from "@/core/threads/types";
|
||||
import { pathOfThread, titleOfThread } from "@/core/threads/utils";
|
||||
import { env } from "@/env";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { isIMEComposing } from "@/lib/ime";
|
||||
|
||||
export function RecentChatList() {
|
||||
@@ -211,7 +212,7 @@ export function RecentChatList() {
|
||||
className="block w-full whitespace-nowrap group-hover/side-menu-item:overflow-hidden"
|
||||
href={pathOfThread(thread)}
|
||||
>
|
||||
{titleOfThread(thread)}
|
||||
{desensitize(titleOfThread(thread))}
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
{env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY !== "true" && (
|
||||
|
||||
@@ -42,6 +42,7 @@ import type {
|
||||
MemoryTarget,
|
||||
MemoryV2Config,
|
||||
} from "@/core/memory/types";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
|
||||
import { SettingsSection } from "./settings-section";
|
||||
|
||||
@@ -173,7 +174,7 @@ export function MemorySettingsPage() {
|
||||
className="flex items-start justify-between gap-3 rounded-md border p-3"
|
||||
>
|
||||
<p className="min-w-0 flex-1 whitespace-pre-wrap text-sm [overflow-wrap:anywhere]">
|
||||
{entry}
|
||||
{desensitize(entry)}
|
||||
</p>
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
<Button
|
||||
@@ -234,7 +235,7 @@ export function MemorySettingsPage() {
|
||||
</SelectItem>
|
||||
{experts.map((a) => (
|
||||
<SelectItem key={a.id} value={a.id}>
|
||||
{a.name}
|
||||
{desensitize(a.name)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
@@ -272,7 +273,7 @@ export function MemorySettingsPage() {
|
||||
</SelectItem>
|
||||
{experts.map((a) => (
|
||||
<SelectItem key={a.id} value={a.id}>
|
||||
{a.name}
|
||||
{desensitize(a.name)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
@@ -356,7 +357,7 @@ export function MemorySettingsPage() {
|
||||
<div className="text-muted-foreground mb-1 font-medium">
|
||||
{m.entryToDeleteLabel}
|
||||
</div>
|
||||
<p className="break-words">{entryToDelete.content}</p>
|
||||
<p className="break-words">{desensitize(entryToDelete.content)}</p>
|
||||
</div>
|
||||
) : null}
|
||||
<DialogFooter>
|
||||
@@ -539,10 +540,10 @@ function MemoryV1View({
|
||||
{Math.round(fact.confidence * 100)}%
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm whitespace-pre-wrap [overflow-wrap:anywhere]">{fact.content}</p>
|
||||
<p className="text-sm whitespace-pre-wrap [overflow-wrap:anywhere]">{desensitize(fact.content)}</p>
|
||||
{fact.sourceError && (
|
||||
<p className="text-xs text-red-600 bg-red-50 rounded px-2 py-1">
|
||||
避免:{fact.sourceError}
|
||||
避免:{desensitize(fact.sourceError)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -566,7 +567,7 @@ function MemoryV1View({
|
||||
<dt className="font-medium text-muted-foreground mb-0.5">
|
||||
{CTX_LABELS[key] ?? key}
|
||||
</dt>
|
||||
<dd className="whitespace-pre-wrap [overflow-wrap:anywhere]">{value}</dd>
|
||||
<dd className="whitespace-pre-wrap [overflow-wrap:anywhere]">{desensitize(value)}</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
@@ -585,7 +586,7 @@ function MemoryV1View({
|
||||
<dt className="font-medium text-muted-foreground mb-0.5">
|
||||
{HISTORY_LABELS[key] ?? key}
|
||||
</dt>
|
||||
<dd className="whitespace-pre-wrap [overflow-wrap:anywhere]">{value}</dd>
|
||||
<dd className="whitespace-pre-wrap [overflow-wrap:anywhere]">{desensitize(value)}</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
@@ -686,7 +687,7 @@ function MemorySearchPanel() {
|
||||
</SelectItem>
|
||||
{experts.map((a) => (
|
||||
<SelectItem key={a.id} value={a.id}>
|
||||
{a.name}
|
||||
{desensitize(a.name)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
@@ -719,7 +720,7 @@ function MemorySearchPanel() {
|
||||
) : results !== null ? (
|
||||
mode === "reflect" ? (
|
||||
<div className="rounded-md border p-3 text-sm whitespace-pre-wrap [overflow-wrap:anywhere]">
|
||||
{reflectText.trim() || m.searchNoResults}
|
||||
{reflectText.trim() ? desensitize(reflectText.trim()) : m.searchNoResults}
|
||||
</div>
|
||||
) : results.length === 0 ? (
|
||||
<div className="text-muted-foreground rounded-md border border-dashed p-3 text-sm">
|
||||
@@ -735,7 +736,7 @@ function MemorySearchPanel() {
|
||||
key={`${index}-${item.slice(0, 16)}`}
|
||||
className="rounded-md border p-3 text-sm whitespace-pre-wrap [overflow-wrap:anywhere]"
|
||||
>
|
||||
{item}
|
||||
{desensitize(item)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -68,6 +68,7 @@ import {
|
||||
} from "@/core/skills/hooks";
|
||||
import type { Skill } from "@/core/skills/type";
|
||||
import { env } from "@/env";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { SettingsSection } from "./settings-section";
|
||||
@@ -404,7 +405,7 @@ function SkillRow({
|
||||
>
|
||||
<ItemTitle>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span>{skill.name}</span>
|
||||
<span>{desensitize(skill.name)}</span>
|
||||
{isBuiltin && (
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{t.settings.skills.badgeBuiltin}
|
||||
@@ -474,7 +475,7 @@ function SkillRow({
|
||||
</div>
|
||||
</ItemTitle>
|
||||
<ItemDescription className="line-clamp-4">
|
||||
{skill.description}
|
||||
{desensitize(skill.description ?? "")}
|
||||
</ItemDescription>
|
||||
{skill.use_count !== undefined && (
|
||||
<div className="text-muted-foreground mt-1 text-xs">
|
||||
@@ -560,7 +561,9 @@ function SkillRow({
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t.settings.skills.deleteAction}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{t.settings.skills.deleteConfirm.replace("{name}", skill.name)}
|
||||
{desensitize(
|
||||
t.settings.skills.deleteConfirm.replace("{name}", skill.name),
|
||||
)}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
@@ -809,22 +812,22 @@ function InstallSkillDialog({
|
||||
<div className="flex flex-col gap-2 rounded-md border p-3 text-sm">
|
||||
<div className="flex items-center gap-2 text-emerald-600">
|
||||
<CheckCircle2 className="size-4" />
|
||||
<span className="font-medium">{validation.skill_name}</span>
|
||||
<span className="font-medium">{desensitize(validation.skill_name)}</span>
|
||||
</div>
|
||||
<Field label={dialog.descriptionLabel}>
|
||||
<span className="line-clamp-3 whitespace-pre-wrap">
|
||||
{validation.description || "—"}
|
||||
{validation.description ? desensitize(validation.description) : "—"}
|
||||
</span>
|
||||
</Field>
|
||||
{validation.license && (
|
||||
<Field label={dialog.licenseLabel}>{validation.license}</Field>
|
||||
<Field label={dialog.licenseLabel}>{desensitize(validation.license)}</Field>
|
||||
)}
|
||||
{validation.allowed_tools.length > 0 && (
|
||||
<Field label={dialog.toolsLabel}>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{validation.allowed_tools.map((tool) => (
|
||||
<Badge key={tool} variant="secondary" className="text-xs">
|
||||
{tool}
|
||||
{desensitize(tool)}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
@@ -834,7 +837,7 @@ function InstallSkillDialog({
|
||||
<Field label={dialog.warningsLabel}>
|
||||
<ul className="list-disc pl-4 text-xs">
|
||||
{validation.warnings.map((w, idx) => (
|
||||
<li key={idx}>{w}</li>
|
||||
<li key={idx}>{desensitize(w)}</li>
|
||||
))}
|
||||
</ul>
|
||||
</Field>
|
||||
@@ -843,7 +846,9 @@ function InstallSkillDialog({
|
||||
<div className="text-amber-600 mt-1 flex items-start gap-2 text-xs">
|
||||
<AlertCircle className="mt-0.5 size-3.5 shrink-0" />
|
||||
<span>
|
||||
{dialog.conflictCustom.replace("{name}", validation.skill_name)}
|
||||
{desensitize(
|
||||
dialog.conflictCustom.replace("{name}", validation.skill_name),
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -851,7 +856,9 @@ function InstallSkillDialog({
|
||||
<div className={cn("mt-1 flex items-start gap-2 text-xs", adminCanOverwritePublic ? "text-amber-600" : "text-destructive")}>
|
||||
<AlertCircle className="mt-0.5 size-3.5 shrink-0" />
|
||||
<span>
|
||||
{(adminCanOverwritePublic ? dialog.conflictPublicAdminHint : dialog.conflictPublic).replace("{name}", validation.skill_name)}
|
||||
{desensitize(
|
||||
(adminCanOverwritePublic ? dialog.conflictPublicAdminHint : dialog.conflictPublic).replace("{name}", validation.skill_name),
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
import { useI18n } from "@/core/i18n/hooks";
|
||||
import { useDeleteCustomSkill, useSetSkillState } from "@/core/skills/hooks";
|
||||
import type { Skill } from "@/core/skills/type";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type Kind = "stale" | "archived";
|
||||
@@ -146,7 +147,7 @@ function SkillStateRow({ skill, kind }: { skill: Skill; kind: Kind }) {
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span className="font-medium">{skill.name}</span>
|
||||
<span className="font-medium">{desensitize(skill.name)}</span>
|
||||
{isArchived ? (
|
||||
<Badge variant="secondary" className="text-xs" title={tt.badgeArchivedTitle}>
|
||||
{tt.badgeArchived}
|
||||
@@ -180,7 +181,7 @@ function SkillStateRow({ skill, kind }: { skill: Skill; kind: Kind }) {
|
||||
)}
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-1 line-clamp-2 text-sm">
|
||||
{skill.description}
|
||||
{desensitize(skill.description ?? "")}
|
||||
</p>
|
||||
<p className="text-muted-foreground mt-1 flex flex-wrap gap-x-3 text-xs">
|
||||
<span>{timeLabel}</span>
|
||||
@@ -254,7 +255,7 @@ function SkillStateRow({ skill, kind }: { skill: Skill; kind: Kind }) {
|
||||
<DialogHeader>
|
||||
<DialogTitle>{tt.deleteAction}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{tt.deleteConfirm.replace("{name}", skill.name)}
|
||||
{desensitize(tt.deleteConfirm.replace("{name}", skill.name))}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
@@ -295,12 +296,12 @@ function SkillViewDialog({
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{skill.name}</DialogTitle>
|
||||
<DialogTitle>{desensitize(skill.name)}</DialogTitle>
|
||||
<DialogDescription>{tv.title}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-3 text-sm">
|
||||
<Row label={tv.descriptionLabel}>
|
||||
<span className="whitespace-pre-wrap">{skill.description}</span>
|
||||
<span className="whitespace-pre-wrap">{desensitize(skill.description ?? "")}</span>
|
||||
</Row>
|
||||
<Row label={tv.stateLabel}>
|
||||
<span className={cn("font-medium", stateColor(skill.state))}>
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
} from "@/core/skills/hooks";
|
||||
import type { Skill } from "@/core/skills/type";
|
||||
import { reasoningPlugins } from "@/core/streamdown";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
|
||||
const markdownClassName =
|
||||
"!h-auto !w-full max-w-none min-w-0 text-sm leading-7 " +
|
||||
@@ -147,7 +148,7 @@ export function SkillDetailDialog({
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<DialogTitle className="truncate text-base">
|
||||
{skill?.name ?? skillName ?? ""}
|
||||
{desensitize(skill?.name ?? skillName ?? "")}
|
||||
</DialogTitle>
|
||||
{skill?.builtin && (
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
@@ -165,7 +166,7 @@ export function SkillDetailDialog({
|
||||
)}
|
||||
</div>
|
||||
<DialogDescription className="mt-1 line-clamp-2 text-sm leading-relaxed">
|
||||
{skill?.description || "-"}
|
||||
{skill?.description ? desensitize(skill.description) : "-"}
|
||||
</DialogDescription>
|
||||
</div>
|
||||
</div>
|
||||
@@ -328,7 +329,7 @@ export function SkillDetailDialog({
|
||||
</div>
|
||||
) : showRawSource ? (
|
||||
<pre className="text-foreground/80 max-w-full overflow-x-auto rounded-lg border bg-muted p-4 font-mono text-xs leading-relaxed whitespace-pre-wrap">
|
||||
{contentData?.content}
|
||||
{desensitize(contentData?.content ?? "")}
|
||||
</pre>
|
||||
) : (
|
||||
<MarkdownContent
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { XIcon } from "lucide-react";
|
||||
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { Tag } from "@/core/tags";
|
||||
|
||||
@@ -24,7 +25,7 @@ export function TagChip({
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{tag.name}
|
||||
{desensitize(tag.name)}
|
||||
{onRemove && (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useEffect } from "react";
|
||||
|
||||
import { useI18n } from "@/core/i18n/hooks";
|
||||
import type { AgentThreadState } from "@/core/threads";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
|
||||
import { useThreadChat } from "./chats";
|
||||
import { FlipDisplay } from "./flip-display";
|
||||
@@ -44,7 +45,7 @@ export function ThreadTitle({
|
||||
}
|
||||
return (
|
||||
<FlipDisplay uniqueKey={threadId}>
|
||||
{thread.values.title ?? "Untitled"}
|
||||
{desensitize(thread.values.title ?? "Untitled")}
|
||||
</FlipDisplay>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user