mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-15 12:55:51 +00:00
fix(workflow): 面板 label 截断保留 #数字 后缀(同 dim 多 finding 可区分)
audit workflow 用 verify:\${dim}#\${findingIdx} 命名 verify agent。
旧逻辑 slice(0, 18) 从右切把 #idx 全吃了——同 dimension 多 finding
肉眼无法区分。新逻辑:含 #数字 后缀时保留后缀,前缀截断 + … 省略号。
例:verify:correctness#0 → verify:correctn…#0
verify:architecture#15 → verify:archite…#15
Co-Authored-By: glm-5.2 <zai-org@claude-code-best.win>
This commit is contained in:
@@ -6,6 +6,7 @@ import { SentryErrorBoundary } from '../../components/SentryErrorBoundary.js';
|
||||
import type { RunProgress } from '../progress/store.js';
|
||||
import { call as panelCall } from '../panel/panelCall.js';
|
||||
import { clampSelected, WorkflowsPanel } from '../panel/WorkflowsPanel.js';
|
||||
import { truncateLabel } from '../panel/AgentList.js';
|
||||
import { STATUS_DOT } from '../panel/status.js';
|
||||
import { __resetWorkflowServiceForTests, getWorkflowService } from '../service.js';
|
||||
|
||||
@@ -20,6 +21,23 @@ test('clampSelected:空列表→0;越界→末位;负/NaN→0;正常→
|
||||
expect(clampSelected(Number.NaN, 3)).toBe(0);
|
||||
});
|
||||
|
||||
// truncateLabel:短 label 原样;含 `#数字` 后缀时保留后缀,前缀截断 + 省略号;
|
||||
// 无后缀则从右切。让 audit workflow 的 verify:${dim}#${idx} 多 finding 仍可区分。
|
||||
test('truncateLabel:短 label 原样;含 #数字 后缀保留后缀前缀截断;无后缀从右切', () => {
|
||||
// 短 label 原样
|
||||
expect(truncateLabel('agent-1', 18)).toBe('agent-1');
|
||||
expect(truncateLabel('review:bugs', 18)).toBe('review:bugs');
|
||||
// 刚好 max 长度(边界)
|
||||
expect(truncateLabel('review:correctness', 18)).toBe('review:correctness');
|
||||
// 超 max + 含 #数字 后缀:保留后缀,前缀截断 + 省略号
|
||||
expect(truncateLabel('verify:correctness#0', 18)).toBe('verify:correctn…#0');
|
||||
expect(truncateLabel('verify:architecture#15', 18)).toBe('verify:archite…#15');
|
||||
// 多位 #idx 也能区分
|
||||
expect(truncateLabel('verify:correctness#2', 18)).toBe('verify:correctn…#2');
|
||||
// 无 #数字 后缀:从右切(旧行为)
|
||||
expect(truncateLabel('a-very-long-label-no-suffix', 18)).toBe('a-very-long-label-');
|
||||
});
|
||||
|
||||
// STATUS_DOT 覆盖四种状态,且均为可见圆点字符。
|
||||
test('STATUS_DOT 覆盖 running/completed/failed/killed 且为非空字符', () => {
|
||||
const statuses = ['running', 'completed', 'failed', 'killed'] as const;
|
||||
|
||||
@@ -8,6 +8,22 @@ const SPINNER_FRAMES = ['·', '✢', '✱', '✶', '✻', '✽'];
|
||||
const FRAME_MS = 120;
|
||||
const LABEL_MAX = 18;
|
||||
|
||||
/**
|
||||
* 截断 label 到 max 字符。保留尾部 `#数字` 后缀(audit workflow 的
|
||||
* `verify:${dim}#${findingIdx}` 格式)——同 dimension 多 finding 的 verify
|
||||
* agent label 仍可区分(前缀用 `…` 省略)。无后缀则从右切(旧行为)。
|
||||
* 已导出便于单测覆盖。
|
||||
*/
|
||||
export function truncateLabel(raw: string, max: number): string {
|
||||
if (raw.length <= max) return raw;
|
||||
const m = raw.match(/#\d+$/);
|
||||
if (!m) return raw.slice(0, max);
|
||||
const suffix = m[0]; // 含 # 号
|
||||
const prefix = raw.slice(0, raw.length - suffix.length);
|
||||
const available = max - suffix.length - 1; // -1 留给 …
|
||||
return `${prefix.slice(0, available)}…${suffix}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 右 agent 列表(已按选中 phase 过滤)。
|
||||
* 选中行:仅在本列聚焦(focused=true)时铺 selectionBg 底(保留 fg,非反色);
|
||||
@@ -39,7 +55,7 @@ export function AgentList({
|
||||
const highlighted = selected && focused;
|
||||
const running = a.status === 'running';
|
||||
const mark = running ? frame : v.mark;
|
||||
const label = (a.label ?? `agent-${a.id}`).slice(0, LABEL_MAX);
|
||||
const label = truncateLabel(a.label ?? `agent-${a.id}`, LABEL_MAX);
|
||||
return (
|
||||
<Box key={a.id} backgroundColor={highlighted ? 'selectionBg' : undefined} justifyContent="space-between">
|
||||
<Box>
|
||||
|
||||
Reference in New Issue
Block a user