feat(i18n): 全局将「专家」文案改为「智能体」
统一智能体功能的 UI 文案:侧边栏、智能体页、新建/保存流程、 审批卡片、登录提示及后端审批消息中的「专家」均改为「智能体」。 保留 prompt 人设、QA 子应用等非该功能语义的「专家」表述。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
a59d80d7f3
48 files changed
+2191
-110
No files matched your search
@@ -93,7 +93,9 @@ export default function ChatPage() {
|
||||
|
||||
const handleSubmit = useCallback(
|
||||
(message: PromptInputMessage) => {
|
||||
// Only the opening turn of a brand-new thread may carry the prefix.
|
||||
const shouldApplyPrefix =
|
||||
isNewThread &&
|
||||
!hasStartedConversation &&
|
||||
promptPrefixOn &&
|
||||
promptPrefixSettings?.enabled === true;
|
||||
@@ -101,19 +103,17 @@ export default function ChatPage() {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("workspace:sandbox-resume-autoscroll"),
|
||||
);
|
||||
const messageToSend = shouldApplyPrefix
|
||||
? {
|
||||
...message,
|
||||
text: `${promptPrefixSettings?.prompt_prefix ?? ""}\n\n${message.text}`,
|
||||
}
|
||||
: message;
|
||||
// The prefix is intentionally NOT concatenated into the message text:
|
||||
// doing so would make the user see it. We only flag the request via
|
||||
// context; the backend tags the message and PromptPrefixMiddleware
|
||||
// injects the prefix into the LLM request only.
|
||||
void sendMessage(
|
||||
threadId,
|
||||
messageToSend,
|
||||
message,
|
||||
shouldApplyPrefix ? { prompt_prefix_enabled: true } : undefined,
|
||||
);
|
||||
},
|
||||
[sendMessage, threadId, hasStartedConversation, promptPrefixOn, promptPrefixSettings],
|
||||
[sendMessage, threadId, isNewThread, hasStartedConversation, promptPrefixOn, promptPrefixSettings],
|
||||
);
|
||||
|
||||
const handleClarificationSubmit = useCallback(
|
||||
@@ -129,13 +129,14 @@ export default function ChatPage() {
|
||||
|
||||
const promptPrefixProp = useMemo(() => {
|
||||
if (!promptPrefixSettings?.enabled) return undefined;
|
||||
if (hasStartedConversation) return undefined;
|
||||
// The prefix toggle is offered only on the opening turn of a new thread.
|
||||
if (!isNewThread || hasStartedConversation) return undefined;
|
||||
return {
|
||||
label: promptPrefixSettings.switch_label || "前缀",
|
||||
on: promptPrefixOn,
|
||||
onToggle: () => setPromptPrefixOn((v) => !v),
|
||||
};
|
||||
}, [promptPrefixSettings, hasStartedConversation, promptPrefixOn]);
|
||||
}, [promptPrefixSettings, isNewThread, hasStartedConversation, promptPrefixOn]);
|
||||
|
||||
const messageListPaddingBottom = showFollowups
|
||||
? MESSAGE_LIST_DEFAULT_PADDING_BOTTOM +
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
Play,
|
||||
Plus,
|
||||
RefreshCw,
|
||||
TagsIcon,
|
||||
Trash2,
|
||||
} from "lucide-react";
|
||||
import { useRouteNavigate as useNavigate } from "@/core/route-base";
|
||||
@@ -35,7 +36,11 @@ import {
|
||||
WorkspaceContainer,
|
||||
WorkspaceHeader,
|
||||
} from "@/components/workspace/workspace-container";
|
||||
import { TagChipList } from "@/components/workspace/tags/tag-chip";
|
||||
import { TagPickerDialog } from "@/components/workspace/tags/tag-picker-dialog";
|
||||
import { TagSearchBar } from "@/components/workspace/tags/tag-search-bar";
|
||||
import { useAgents } from "@/core/agents";
|
||||
import { getStoredAuth } from "@/core/auth";
|
||||
import {
|
||||
downloadScheduledTaskRun,
|
||||
type PublishedScheduledTask,
|
||||
@@ -283,7 +288,10 @@ const emptyForm = {
|
||||
|
||||
export default function ScheduledTasksPage() {
|
||||
const navigate = useNavigate();
|
||||
const { data: tasks = [], isLoading } = useScheduledTasks();
|
||||
const [search, setSearch] = useState("");
|
||||
const [tagId, setTagId] = useState<string | null>(null);
|
||||
// Name + tag filtering is resolved server-side via the /api/scheduled-tasks query.
|
||||
const { data: tasks = [], isLoading } = useScheduledTasks({ search, tagId });
|
||||
const { data: deliveryProfile } = useScheduledTaskDeliveryProfile();
|
||||
const { agents } = useAgents();
|
||||
const actions = useScheduledTaskActions();
|
||||
@@ -299,6 +307,8 @@ export default function ScheduledTasksPage() {
|
||||
const [runsTimeFilter, setRunsTimeFilter] = useState<"all" | "today" | "7d" | "30d">("all");
|
||||
const [subscribeTarget, setSubscribeTarget] = useState<PublishedScheduledTask | null>(null);
|
||||
const [subscribeNotify, setSubscribeNotify] = useState(false);
|
||||
const [tagPickerTask, setTagPickerTask] = useState<ScheduledTask | null>(null);
|
||||
const isAdmin = useMemo(() => getStoredAuth()?.system_role === "admin", []);
|
||||
|
||||
const sortedTasks = useMemo(
|
||||
() =>
|
||||
@@ -466,6 +476,14 @@ export default function ScheduledTasksPage() {
|
||||
<TabsTrigger value="plaza" className="flex-1">广场</TabsTrigger>
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
{activeTab === "mine" && (
|
||||
<TagSearchBar
|
||||
targetType="scheduled_task"
|
||||
onSearchChange={setSearch}
|
||||
tagId={tagId}
|
||||
onTagIdChange={setTagId}
|
||||
/>
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardContent className="min-h-0 flex-1 p-0">
|
||||
<ScrollArea className="size-full">
|
||||
@@ -527,7 +545,23 @@ export default function ScheduledTasksPage() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{(task.tags?.length ?? 0) > 0 && (
|
||||
<TagChipList tags={task.tags!} className="mt-3" />
|
||||
)}
|
||||
<div className="mt-3 flex flex-wrap gap-2">
|
||||
{isAdmin && (
|
||||
<Button
|
||||
size="icon"
|
||||
variant="outline"
|
||||
title="编辑标签"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setTagPickerTask(task);
|
||||
}}
|
||||
>
|
||||
<TagsIcon className="size-4" />
|
||||
</Button>
|
||||
)}
|
||||
{isOwner ? (
|
||||
<>
|
||||
<Button
|
||||
@@ -934,6 +968,16 @@ export default function ScheduledTasksPage() {
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{isAdmin && tagPickerTask && (
|
||||
<TagPickerDialog
|
||||
open={!!tagPickerTask}
|
||||
onOpenChange={(open) => !open && setTagPickerTask(null)}
|
||||
targetType="scheduled_task"
|
||||
targetId={tagPickerTask.task_id}
|
||||
currentTags={tagPickerTask.tags ?? []}
|
||||
/>
|
||||
)}
|
||||
</WorkspaceContainer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { TagManagementPage } from "@/components/workspace/admin/tag-management-page";
|
||||
|
||||
export default function TagsPage() {
|
||||
return <TagManagementPage />;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import PromptPrefixSettingsPage from "./PromptPrefixSettingsPage";
|
||||
import SkillEvolutionPage from "./SkillEvolutionPage";
|
||||
import SkillsPage from "./SkillsPage";
|
||||
import UsersPage from "./UsersPage";
|
||||
import TagsPage from "./TagsPage";
|
||||
import RecommendedQuestionsPage from "./RecommendedQuestionsPage";
|
||||
|
||||
export function WorkspaceLayout({
|
||||
@@ -183,6 +184,18 @@ export default function WorkspaceRoutes({
|
||||
</WorkspaceLayout>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="admin/tags"
|
||||
element={
|
||||
getStoredAuth()?.system_role === "admin" ? (
|
||||
<WorkspaceLayout {...layoutProps}>
|
||||
<TagsPage />
|
||||
</WorkspaceLayout>
|
||||
) : (
|
||||
<Navigate to="/page/workspace/chats/new" replace />
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="settings/recommended-questions"
|
||||
element={
|
||||
|
||||
Reference in new issue
Block a user