Commit edfc2010 by luoqi

merge: 助手窗口调高 + 拿掉工具灰行与「执行过程」

· 默认高度 620 → 760(max-h 78vh → 88vh)——确认单一出正文就被挤到要滚
· 正文里的「出分配方案 `propose_assignment`」灰行删掉:后半是函数名,不是主管的词
· 末尾「执行过程 · N 步 …→ 摆选项按钮」删掉:讲的是装置内部怎么跑的
· 组件(StepRow / StepTrace)一并删, 不留成没人用的导出
️ 可核查性换了地方:等待文案(说动作不说工具名)+ agent_invocations.output.steps + 裸台
parents 066cc349 d49d42e5
Pipeline #3580 failed in 0 seconds
...@@ -32,7 +32,7 @@ import { useHasPermission } from '@/hooks/use-permission'; ...@@ -32,7 +32,7 @@ import { useHasPermission } from '@/hooks/use-permission';
import { useAssistantStore } from '@/stores/assistant-store'; import { useAssistantStore } from '@/stores/assistant-store';
import { AssignmentConfirmSheet } from './assignment-confirm-sheet'; import { AssignmentConfirmSheet } from './assignment-confirm-sheet';
import { SignalPrompt } from './signal-prompts'; import { SignalPrompt } from './signal-prompts';
import { ReasoningRow, StepRow, StepTrace, toolMeta } from './step-trace'; import { ReasoningRow, toolMeta } from './step-trace';
import { isDiscardedDraft, stripToolEcho } from './chat-blocks'; import { isDiscardedDraft, stripToolEcho } from './chat-blocks';
import { import {
useAssistantChat, useAssistantChat,
...@@ -46,7 +46,6 @@ import { ...@@ -46,7 +46,6 @@ import {
* ⛔ 不再单独出一行灰字 —— 否则同一件事画两遍,而且顺序还是反的 * ⛔ 不再单独出一行灰字 —— 否则同一件事画两遍,而且顺序还是反的
* (侧信道事件比 fullStream 的 tool-call 先到)。 * (侧信道事件比 fullStream 的 tool-call 先到)。
*/ */
const PLACE_TOOLS = new Set(['show_sheet', 'show_guidance']);
/** /**
* ⭐ **小图标按钮的唯一定义**(2026-08-15)。 * ⭐ **小图标按钮的唯一定义**(2026-08-15)。
...@@ -289,20 +288,15 @@ function BlockView({ ...@@ -289,20 +288,15 @@ function BlockView({
orphanKeys?: Set<string>; orphanKeys?: Set<string>;
}) { }) {
/** /**
* ⭐ 思考 / 工具调用 **按到达顺序就地渲染**(2026-08-14 改,此前只在末尾的执行过程里)。 * ⭐ 思考**按到达顺序就地渲染**(2026-08-14 改,此前只在末尾的执行过程里)——
* 位置本身就是信息:「想 → 调 → 写 → 再调」和「全调完再写」是两种行为,堆在末尾看不出区别。
* *
* 🔴 改的理由:位置本身就是信息 —— 「想 → 调 → 写 → 再调」和「全调完再写」 * 🔴 **工具那一类 2026-08-19 起整个不到这儿了**(在 `MessageView` 的 `rest` 里就滤掉了,
* 是两种完全不同的行为,而堆在末尾看不出区别。归因一次要靠这个顺序。 * 理由写在那儿)。⇒ 这里⛔ 不留 `block.kind === 'tool'` 分支:
* ⚠️ 当初钉在末尾的顾虑是「qwen 会把 tool-call 全提到文本之前,等于先给主管看一屏工具记录」—— * 它永远进不来,而一段永远不执行的代码读起来像"这个功能还在"。
* 现在两条都变了:默认模型是会交错的 DeepSeek;而每行都是**一行收起态**, * 要把它放回来,改 `rest` 的过滤那一处就够了。
* 就算全提到前面也只是几行灰字,⛔ 不再是"一屏记录"。
* ⛔ `show_*` 不出行:它们在正文里**已经有可见产物**(卡片 / 按钮),
* 而且侧信道事件比 fullStream 的 tool-call 先到 —— 两个都画会出现"产物排在自己的调用记录前面"。
*/ */
if (block.kind === 'reasoning') return <ReasoningRow text={block.text} />; if (block.kind === 'reasoning') return <ReasoningRow text={block.text} />;
if (block.kind === 'tool') {
return PLACE_TOOLS.has(block.step.tool) ? null : <StepRow step={block.step} />;
}
// 位置标记本身不渲染 —— MessageView 已经把卡片搬到它那儿了(理论上到不了这) // 位置标记本身不渲染 —— MessageView 已经把卡片搬到它那儿了(理论上到不了这)
if (block.kind === 'sheet_anchor') return null; if (block.kind === 'sheet_anchor') return null;
if (block.kind === 'artifact') return <ArtifactView artifact={block.artifact} />; if (block.kind === 'artifact') return <ArtifactView artifact={block.artifact} />;
...@@ -345,7 +339,13 @@ function BlockView({ ...@@ -345,7 +339,13 @@ function BlockView({
/> />
); );
} }
return <Markdown text={block.text} />; /**
* ⚠️ 兜底显式判 `text`,⛔ 别写成 `return <Markdown text={block.text} />` ——
* 那一版能编译过,是因为上面还有一条 `block.kind === 'tool'` 分支替它把类型收窄了;
* 工具分支删掉之后(见上),少了收窄这条尾巴就不成立了。
* ⇒ 判据写在自己这一行,⛔ 不靠别处的分支顺手兜。
*/
return block.kind === 'text' ? <Markdown text={block.text} /> : null;
} }
// ── Artifact:模型产出的 HTML 在隔离沙箱 iframe 渲染(即用即焚)────────────── // ── Artifact:模型产出的 HTML 在隔离沙箱 iframe 渲染(即用即焚)──────────────
...@@ -677,7 +677,18 @@ function MessageView({ ...@@ -677,7 +677,18 @@ function MessageView({
const rest = message.blocks.filter( const rest = message.blocks.filter(
(b) => (b) =>
b.kind !== 'assignment_sheet' && b.kind !== 'assignment_sheet' &&
(showTrace || (b.kind !== 'reasoning' && b.kind !== 'tool')), /**
* 🔴 **工具灰行整个不给主管看**(2026-08-19 产品定)——「出分配方案 `propose_assignment`」
* 这一行里,前半是产品说法、后半是**函数名**,而主管的词汇表就是他在界面上见过的那些
* (同 ② 诚实层那条)。他要判断的是"这一版分得对不对",⛔ 不是"它走了哪条代码路径"。
* ⚠️ 可核查性**没有丢**,只是挪了地方:
* · 「正在出分配方案…」那句等待文案还在(`hintLabel`,说的是动作不是工具名);
* · 每一步的形状落在 `agent_invocations.output.steps`(服务端留痕,可回查);
* · 裸台(`/assistant-lab`)仍旧原样展示全部步骤 —— 排查去那儿。
* ⇒ 开关(`showTrace`)现在只管**思考**那一类。
*/
b.kind !== 'tool' &&
(showTrace || b.kind !== 'reasoning'),
); );
/** /**
...@@ -805,19 +816,11 @@ function MessageView({ ...@@ -805,19 +816,11 @@ function MessageView({
))} ))}
{showHint && <GeneratingHint label={hintLabel} />} {showHint && <GeneratingHint label={hintLabel} />}
{/** {/**
* ⭐ 执行过程 —— 这一轮**到底调了哪些工具**,默认收起(见 step-trace 的整段理由)。 * ⛔ 「执行过程 · N 步 出分配方案 → 摆选项按钮 → …」**已删**(2026-08-19 产品定)。
* * 同上面工具灰行那条理由:主管要判断的是这一版分得对不对,
* ⚠️ 摆在最后、且**说完才出现**:流式期间它每来一步就长一行, * 而这行小结讲的是**装置内部怎么跑的** —— 它连"摆按钮"这种渲染动作都列出来了。
* 而主管这时正在读上面的文字 —— 底下抖动比看不见更烦。 * ⚠️ `StepTrace` 组件本身**留着**,裸台(`/assistant-lab`)还在用它排查。
* ⚠️ 一步都没有时组件自己返回 null,⛔ 这里不用再判一次。
*/} */}
{!streaming && (
<StepTrace
steps={message.blocks
.filter((b): b is Extract<Block, { kind: 'tool' }> => b.kind === 'tool')
.map((b) => b.step)}
/>
)}
</div> </div>
); );
} }
...@@ -1078,11 +1081,12 @@ export function AssistantChat({ ...@@ -1078,11 +1081,12 @@ export function AssistantChat({
const [voice, setVoice] = useState<'idle' | 'live'>('idle'); const [voice, setVoice] = useState<'idle' | 'live'>('idle');
const [voiceErr, setVoiceErr] = useState<string | null>(null); const [voiceErr, setVoiceErr] = useState<string | null>(null);
/** /**
* 思考与工具调用**展不展开**(2026-08-15 产品加)。 * 思考**展不展开**(2026-08-15 产品加;2026-08-19 起工具调用不在它管辖内了)。
* *
* ⚠️ 默认展开:它是「模型到底调没调工具」的可核查记录,这条生产线最贵的一类问题 * ⚠️ 默认展开:模型讲了什么、怎么想的,主管看得懂也用得上。
* 就靠它从"推理"变成"看一眼"。收起是主管当下不想看,⛔ 不是默认不给。
* ⚠️ 只活在这个组件里,刷新回到默认 —— 它是一次阅读时的取舍,⛔ 不是账号设置。 * ⚠️ 只活在这个组件里,刷新回到默认 —— 它是一次阅读时的取舍,⛔ 不是账号设置。
* ⚠️ 「模型到底调没调工具」这件事**不再靠界面看**(工具行已删)——
* 它落在 `agent_invocations.output.steps` 里,回查见那边注释。
*/ */
const [showTrace, setShowTrace] = useState(true); const [showTrace, setShowTrace] = useState(true);
const dictRef = useRef<{ const dictRef = useRef<{
...@@ -1368,14 +1372,14 @@ export function AssistantChat({ ...@@ -1368,14 +1372,14 @@ export function AssistantChat({
</button> </button>
)} )}
{/* {/*
思考与工具调用的开关 —— ⚠️ 收起时**图标变实**(不是变淡): 思考的开关 —— ⚠️ 收起时**图标变实**(不是变淡):
「有东西被我收起来了」需要一直看得见,收起之后底部那行小结是唯一的痕迹 「有东西被我收起来了」需要一直看得见。
⛔ 别用变淡表示"关":那读起来像"这个功能不可用"。 ⛔ 别用变淡表示"关":那读起来像"这个功能不可用"。
*/} */}
<button <button
type="button" type="button"
onClick={() => setShowTrace((v) => !v)} onClick={() => setShowTrace((v) => !v)}
title={showTrace ? '收起思考与工具调用' : '展开思考与工具调用'} title={showTrace ? '收起思考' : '展开思考'}
className={cn( className={cn(
'inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors', 'inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors',
showTrace showTrace
......
...@@ -43,7 +43,13 @@ export function AssistantWidget() { ...@@ -43,7 +43,13 @@ export function AssistantWidget() {
* ⛔ 别再往回收:那张卡是这个窗口的**主要内容**,窗口要迁就它。 * ⛔ 别再往回收:那张卡是这个窗口的**主要内容**,窗口要迁就它。
*/ */
const W = Math.min(480, window.innerWidth - 16); const W = Math.min(480, window.innerWidth - 16);
const H = Math.min(620, Math.round(window.innerHeight * 0.78)); /**
* ⚠️ **这个 760 / 0.88 与下面 className 里的 `h-[760px] max-h-[88vh]` 是一对,改一处要改两处**。
* 🔴 620 → 760(2026-08-19 产品:「默认高度改高点」):这个窗口的主要内容是**确认单**,
* 而它下面还要跟一段正文和几排引导按钮 —— 620px 里卡片一出,正文就被挤到要滚,
* 而正文正是"这一版为什么长这样"的那半句。⛔ 别再往回收。
*/
const H = Math.min(760, Math.round(window.innerHeight * 0.88));
// 水平:钮在屏幕右半 → 窗口右缘对齐钮右缘;左半 → 左缘对齐 // 水平:钮在屏幕右半 → 窗口右缘对齐钮右缘;左半 → 左缘对齐
let x = fab.left + fab.width / 2 > window.innerWidth / 2 ? fab.right - W : fab.left; let x = fab.left + fab.width / 2 > window.innerWidth / 2 ? fab.right - W : fab.left;
// 垂直:优先弹在钮上方,放不下弹下方 // 垂直:优先弹在钮上方,放不下弹下方
...@@ -106,8 +112,8 @@ export function AssistantWidget() { ...@@ -106,8 +112,8 @@ export function AssistantWidget() {
'transition-[opacity,transform] duration-150', 'transition-[opacity,transform] duration-150',
maximized maximized
? 'inset-3' // 最大化:填满窗口(留 12px 边距),不写死宽高,随窗口自适应 ? 'inset-3' // 最大化:填满窗口(留 12px 边距),不写死宽高,随窗口自适应
: // ⚠️ `w-[480px]` 与上面 openAt 里的 480 是一对,改一处要改两处 : // ⚠️ `w-[480px]` / `h-[760px]` 与上面 openAt 里的 480 / 760 是一对,改一处要改两处
cn(!winRect && 'bottom-4 right-4', 'h-[620px] max-h-[78vh] w-[480px] max-w-[calc(100vw-2rem)]'), cn(!winRect && 'bottom-4 right-4', 'h-[760px] max-h-[88vh] w-[480px] max-w-[calc(100vw-2rem)]'),
open ? 'translate-y-0 opacity-100' : 'pointer-events-none invisible translate-y-2 opacity-0', open ? 'translate-y-0 opacity-100' : 'pointer-events-none invisible translate-y-2 opacity-0',
)} )}
> >
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment