copy: second-round copy review across console, settings, agent and server messages
- Trim descriptions, empty states, confirm buttons and toasts to facts - Unify terms per glossary: 待处理/待识别/整理记录/运行记录/凭证/子会话/Agent 上游 - Subscription-login termsNote states facts only (borrowed client identity, ToS/ban risk) - Shorter, concrete goal templates for built-in Agent checks - Human-readable nouns instead of table names in instance CRUD errors - Audit labels for pi_upstream / schedule / automation_grant actions - Glossary: add 上游、订阅登录、凭证、定时任务、巡检、运行记录、子会话、停止、持续授权 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c67f6a9682
commit
31a54186c7
58 files changed
+200
-188
No files matched your search
@@ -174,10 +174,10 @@ export function ToolCallCard({
|
||||
reason={authReason ?? call.reason ?? "未授权"}
|
||||
explanation={
|
||||
authReason
|
||||
? '有副作用的能力必须命中有效的持续授权(automation_grant)或单次审批(approval),由服务端在执行前核对;模型声称"用户已同意"不会被采信。需要放行时到「设置 → 持续授权」发放,或对计划申请单次审批。'
|
||||
? '有副作用的能力需要有效的持续授权或单次审批,由服务端在执行前核对,模型声称"用户已同意"无效。发布收录策略会生成持续授权,也可以为计划申请单次审批。'
|
||||
: mode === "plan_only" && writeKind
|
||||
? "本次是「只要方案」:白名单只放行只读、预览、提案类能力,执行类调用一律拒绝。要真正执行,请按方案以执行模式重新发起。"
|
||||
: "这个能力不在本次运行的能力白名单内(或已超出调用预算),调用在到达处理器前就被拦下。Agent 无法绕过。"
|
||||
? "本次是「只要方案」,只放行只读、预览、提案类能力。要执行,点「按方案执行」。"
|
||||
: "这个能力不在本次运行的白名单内,或已超出调用预算,调用没有执行。"
|
||||
}
|
||||
parameters={[
|
||||
{ id: "call", label: "调用 ID", value: call.toolCallId },
|
||||
@@ -219,9 +219,7 @@ export function ToolCallCard({
|
||||
<dt className="text-muted-foreground">幂等键</dt>
|
||||
<dd className="min-w-0 font-mono break-all text-foreground/80">
|
||||
{audit?.idempotencyKey ??
|
||||
(meta && meta.kind !== "read"
|
||||
? "由服务端生成(能力:版本:运行:输入哈希),审计未取到"
|
||||
: "只读能力不记操作账本")}
|
||||
(meta && meta.kind !== "read" ? "服务端已生成,审计里没有取到" : "只读能力不记操作账本")}
|
||||
</dd>
|
||||
{audit?.grantId || audit?.approvalId ? (
|
||||
<>
|
||||
@@ -298,13 +296,13 @@ function EndNotice({ item }: { item: Extract<StreamItem, { kind: "end" }> }) {
|
||||
{budget
|
||||
? `超出预算${item.budget ? `(${BUDGET_LABEL[item.budget] ?? item.budget})` : ""},已停止`
|
||||
: aborted
|
||||
? "已中止"
|
||||
? "已停止"
|
||||
: "运行失败"}
|
||||
</p>
|
||||
{item.message ? <p className="mt-0.5 text-caption break-words">{item.message}</p> : null}
|
||||
{budget ? (
|
||||
<p className="mt-1 text-meta text-muted-foreground">
|
||||
已完成的外部动作不会撤销;可调大预算后追加消息续跑。
|
||||
已完成的外部动作不会撤销。调大预算后追加消息可继续运行。
|
||||
</p>
|
||||
) : null}
|
||||
</MessageBubbleContent>
|
||||
@@ -636,7 +634,7 @@ export function ApprovalItem({ approval: a }: { approval: Approval }) {
|
||||
<ApprovalCard
|
||||
status={status}
|
||||
title={`批准执行这份${PLAN_LABEL[a.planType] ?? a.planType}?`}
|
||||
description={a.reason ?? "审批绑定计划 ID、payload hash 与版本号;计划变化后旧审批自动失效。"}
|
||||
description={a.reason ?? "计划变化后,这份审批自动失效。"}
|
||||
badges={
|
||||
<>
|
||||
{risk ? <RiskBadge level={risk} /> : null}
|
||||
@@ -645,7 +643,7 @@ export function ApprovalItem({ approval: a }: { approval: Approval }) {
|
||||
}
|
||||
onApprove={() => act("approved")}
|
||||
onReject={() => act("rejected")}
|
||||
disabledReason={admin ? undefined : "只有控制台管理员会话能批准或拒绝"}
|
||||
disabledReason={admin ? undefined : "只有管理员能批准或拒绝"}
|
||||
result={
|
||||
a.decidedAt
|
||||
? `${a.status === "approved" ? "批准" : a.status === "rejected" ? "拒绝" : "处理"}于 ${formatDateTime(a.decidedAt)}`
|
||||
@@ -736,7 +734,7 @@ export function FinalReport({
|
||||
<StreamingResponse status="complete" copyText={said || undefined} contentClassName="max-h-60 overflow-auto">
|
||||
{said || "(没有文字汇报)"}
|
||||
</StreamingResponse>
|
||||
<p className="mt-2 text-meta text-muted-foreground">模型的自述,仅供参考,不作为完成依据。</p>
|
||||
<p className="mt-2 text-meta text-muted-foreground">仅供参考,不作为完成依据。</p>
|
||||
</div>
|
||||
<div className="min-w-0 rounded-xl border border-border/70 bg-foreground/[0.02] p-3">
|
||||
<p className="mb-1.5 flex items-center gap-1.5 text-label font-semibold tracking-[0.18em] text-muted-foreground uppercase">
|
||||
@@ -798,12 +796,12 @@ export function FinalReport({
|
||||
/>
|
||||
) : null}
|
||||
<p className="mt-2 text-meta text-muted-foreground">
|
||||
汇总自下载计划、下载任务与整理记录(生成于 {formatDateTime(report.generatedAt)}
|
||||
);"已提交"只代表进入下载器,整理成功才算入库。
|
||||
取自下载计划、下载任务和整理记录(生成于 {formatDateTime(report.generatedAt)}
|
||||
)。"已提交"指已进入下载器,整理成功才算入库。
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<p className="mt-2 text-meta text-muted-foreground">服务端汇报尚未生成;以任务页、整理记录的实际状态为准。</p>
|
||||
<p className="mt-2 text-meta text-muted-foreground">服务端汇报还没有生成,以任务和整理记录的实际状态为准。</p>
|
||||
)}
|
||||
{run.error ? (
|
||||
<p className="mt-2 text-caption break-words text-destructive">
|
||||
@@ -833,7 +831,7 @@ export function RunAnnouncer({ status, finished }: { status: AgentRunStatus; fin
|
||||
prev.current = status;
|
||||
}, [status]);
|
||||
useEffect(() => {
|
||||
if (finished) setMsg("回复完成,最终汇报已生成");
|
||||
if (finished) setMsg("最终汇报已生成");
|
||||
}, [finished]);
|
||||
return (
|
||||
<span className="sr-only" role="status" aria-live="polite">
|
||||
|
||||
@@ -93,7 +93,7 @@ export function AgentDrawer() {
|
||||
Agent
|
||||
</SheetTitle>
|
||||
<SheetDescription className="break-words">
|
||||
{context?.label ? `当前对象:${context.label}` : "交代目标,Agent 在授权范围内边执行边汇报。"}
|
||||
{context?.label ? `当前对象:${context.label}` : "交代目标,Agent 在授权范围内执行并汇报。"}
|
||||
<span className="ml-1 hidden text-muted-foreground/75 sm:inline">
|
||||
({agentShortcutLabel()} 开关,Esc 关闭)
|
||||
</span>
|
||||
|
||||
@@ -37,16 +37,16 @@ import {
|
||||
import { SubagentTree } from "./agent-subagent-tree.tsx";
|
||||
import { useAgentStream } from "./use-agent-stream.ts";
|
||||
|
||||
const TRIGGER_LABEL = { user: "用户发起", event: "事件触发", schedule: "定时", subagent: "子代理" } as const;
|
||||
const TRIGGER_LABEL = { user: "用户发起", event: "事件触发", schedule: "定时", subagent: "子会话" } as const;
|
||||
|
||||
export const MODE_HELP: Record<AgentMode, { label: string; help: string }> = {
|
||||
execute: {
|
||||
label: "授权内执行",
|
||||
help: "在已授权范围内执行;未授权的动作会被服务端拒绝并在对话里标出。",
|
||||
help: "未授权的动作会被服务端拒绝并在对话里标出。",
|
||||
},
|
||||
plan_only: {
|
||||
label: "只要方案",
|
||||
help: "只调查、出方案,不执行任何写操作;满意后可一键按方案执行。",
|
||||
help: "只调查、出方案,不执行写操作。之后可按方案执行。",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -134,7 +134,7 @@ export function GoalComposer({
|
||||
<div className="pt-2">
|
||||
<p className="mb-1.5 flex items-center gap-1.5 px-1 text-meta text-muted-foreground">
|
||||
<Sparkles aria-hidden className="size-3.5" />
|
||||
试试这些
|
||||
常用目标
|
||||
</p>
|
||||
<ul aria-label="快捷目标" className="flex flex-col gap-1.5">
|
||||
{suggestions.map((s) => (
|
||||
@@ -267,9 +267,7 @@ export function AgentRunPanel({
|
||||
className="flex items-center gap-2 rounded-xl border border-warning/40 bg-warning/10 px-3 py-2 text-caption text-warning"
|
||||
>
|
||||
<WifiOff aria-hidden className="size-4 shrink-0" />
|
||||
<span className="min-w-0 flex-1">
|
||||
实时连接中断,正在重连;恢复后按 after= 补读漏掉的事件,期间每 2.5 秒轮询兜底。
|
||||
</span>
|
||||
<span className="min-w-0 flex-1">实时连接中断,正在重连。期间每 2.5 秒轮询一次。</span>
|
||||
</div>
|
||||
) : null}
|
||||
{live.error ? (
|
||||
@@ -320,7 +318,7 @@ export function AgentRunPanel({
|
||||
maxRows={6}
|
||||
maxLength={8000}
|
||||
aria-label="追加消息"
|
||||
placeholder={streaming ? "补充或纠正(运行中也可追加)" : "追加消息,继续这次会话"}
|
||||
placeholder={streaming ? "补充或纠正(运行中也可追加)" : "追加消息"}
|
||||
toolbar={
|
||||
mode === "plan_only" && finished ? (
|
||||
<Button type="button" size="sm" variant="outline" onClick={executePlan} disabled={create.isPending}>
|
||||
@@ -334,7 +332,7 @@ export function AgentRunPanel({
|
||||
/>
|
||||
<p className="px-1 text-meta text-muted-foreground">
|
||||
{mode === "plan_only" && finished
|
||||
? "「按方案执行」会以授权内执行模式新开一次运行,仍受服务端授权校验。"
|
||||
? "「按方案执行」会新开一次授权内执行的运行,仍受服务端授权校验。"
|
||||
: MODE_HELP[mode].help}{" "}
|
||||
Enter 发送,Shift+Enter 换行{streaming ? ",停止 = 中止本次运行" : ""}。
|
||||
</p>
|
||||
@@ -344,12 +342,12 @@ export function AgentRunPanel({
|
||||
open={confirmStop}
|
||||
onOpenChange={setConfirmStop}
|
||||
title="停止这次运行?"
|
||||
description="停止后续步骤;已经完成的外部动作(如已提交的下载)不会被撤销。"
|
||||
confirmLabel="停止"
|
||||
description="后续步骤不再执行,已完成的外部动作(如已提交的下载)不会撤销。"
|
||||
confirmLabel="停止运行"
|
||||
destructive
|
||||
onConfirm={() =>
|
||||
abort.mutateAsync(r.id).then(
|
||||
() => toast.success("已请求中止"),
|
||||
() => toast.success("已请求停止"),
|
||||
(e) => {
|
||||
toast.error(errorMessage(e));
|
||||
throw e;
|
||||
|
||||
@@ -75,7 +75,7 @@ export function AgentSessionList({
|
||||
plain
|
||||
icon={Bot}
|
||||
title={status ? "没有这个状态的会话" : "还没有会话"}
|
||||
description={status ? "换个筛选看看。" : "交代一个目标开始;也可以在任意页面右上角打开 Agent 侧栏。"}
|
||||
description={status ? undefined : "交代一个目标开始。任意页面都能从右下角打开 Agent。"}
|
||||
/>
|
||||
) : (
|
||||
<ul className="space-y-1">
|
||||
|
||||
@@ -26,7 +26,7 @@ function budgetText(b: Record<string, number | undefined>) {
|
||||
if (b.maxTokens !== undefined) parts.push(`${tokens(b.maxTokens)} token`);
|
||||
if (b.maxDurationSec !== undefined) parts.push(`${b.maxDurationSec}s`);
|
||||
if (b.maxCostUsd !== undefined) parts.push(`$${b.maxCostUsd}`);
|
||||
return parts.length ? parts.join(" · ") : "按设置缺省";
|
||||
return parts.length ? parts.join(" · ") : "沿用设置";
|
||||
}
|
||||
|
||||
function Node({ node, byParent, depth }: { node: AgentRunNode; byParent: Map<string, AgentRunNode[]>; depth: number }) {
|
||||
|
||||
@@ -42,7 +42,7 @@ const RULES: Rule[] = [
|
||||
},
|
||||
{
|
||||
match: /^\/console\/identity/,
|
||||
goals: ["帮我识别待识别池里的文件", "找出外部身份映射可能错误的作品", "补全缺少元数据的作品"],
|
||||
goals: ["识别待识别的文件", "找出外部身份可能错误的作品", "补全缺少元数据的作品"],
|
||||
},
|
||||
{
|
||||
match: /^\/console\/subscriptions/,
|
||||
@@ -50,7 +50,7 @@ const RULES: Rule[] = [
|
||||
},
|
||||
{
|
||||
match: /^\/console\/sources/,
|
||||
goals: ["哪些来源不新鲜了,原因是什么", "检查所有 RSS 的抓取状态", "最近一天各来源抓到了什么"],
|
||||
goals: ["哪些来源不新鲜了,原因是什么", "检查所有 Feed 的抓取状态", "最近一天各来源抓到了什么"],
|
||||
},
|
||||
{
|
||||
match: /^\/console\/engine/,
|
||||
|
||||
Reference in new issue
Block a user