diff --git a/static/src/components/chat/quickdock/RunnerDetailPanel.vue b/static/src/components/chat/quickdock/RunnerDetailPanel.vue index a8bb4c1f..90ec4be0 100644 --- a/static/src/components/chat/quickdock/RunnerDetailPanel.vue +++ b/static/src/components/chat/quickdock/RunnerDetailPanel.vue @@ -30,15 +30,23 @@ v-for="item in timelineItems" :key="item.key" class="qd-feed-row" - :class="[item.kind === 'tool' ? 'feed-tool' : 'feed-text', { 'is-new': animatedKeys.has(item.key) }]" + :class="[item.kind === 'tool' ? 'feed-tool' : item.kind === 'compression' ? 'feed-compressed' : 'feed-text', { 'is-new': animatedKeys.has(item.key) }]" > + @@ -283,14 +291,6 @@ function isEntryTerminal(status?: string) { ].includes(normalized); } -/** 工具条目状态标签:映射表存 key、使用处解析(规范 §3.3,模块顶层禁止调 t()) */ -const TOOL_STATE_LABEL_KEYS: Record = { - completed: 'quickdock.toolStateDone', - failed: 'quickdock.toolStateFailed', - calling: 'quickdock.toolStateCalling', - running: 'quickdock.toolStateProgress' -}; - function buildText(entry: any): string { const tool = entry.tool || ''; const args = entry.args || {}; @@ -309,7 +309,6 @@ interface ToolTimelineItem { kind: 'tool'; key: string; state: string; - stateLabel: string; toolName: string; text: string; } @@ -320,10 +319,16 @@ interface OutputTimelineItem { content: string; } -const timelineItems = computed<(ToolTimelineItem | OutputTimelineItem)[]>(() => { +interface CompressionTimelineItem { + kind: 'compression'; + key: string; + round: number; +} + +const timelineItems = computed<(ToolTimelineItem | OutputTimelineItem | CompressionTimelineItem)[]>(() => { void currentLocale.value; const entries = activityEntries.value || []; - const rawItems: ({ kind: 'tool'; key: string; entry: any } | OutputTimelineItem)[] = []; + const rawItems: ({ kind: 'tool'; key: string; entry: any } | OutputTimelineItem | CompressionTimelineItem)[] = []; let currentToolGroup: { kind: 'tool'; key: string; entry: any } | null = null; const flushToolGroup = () => { @@ -361,6 +366,17 @@ const timelineItems = computed<(ToolTimelineItem | OutputTimelineItem)[]>(() => return; } + // 上下文压缩提示:在压缩发生的位置插入一条提示条目 + if (entry?.type === 'progress' && entry?.subtype === 'compression') { + flushToolGroup(); + rawItems.push({ + kind: 'compression', + key: `compression-${entry.ts || index}`, + round: Number(entry.round) || 0, + }); + return; + } + if (!entry || entry.type !== 'progress' || !entry.tool) { return; } @@ -401,7 +417,7 @@ const timelineItems = computed<(ToolTimelineItem | OutputTimelineItem)[]>(() => flushToolGroup(); return rawItems.map((item) => { - if (item.kind === 'output') { + if (item.kind === 'output' || item.kind === 'compression') { return item; } const state = normalizeStatus(item.entry.status); @@ -409,7 +425,6 @@ const timelineItems = computed<(ToolTimelineItem | OutputTimelineItem)[]>(() => kind: 'tool' as const, key: item.key, state, - stateLabel: t(TOOL_STATE_LABEL_KEYS[state] || 'quickdock.toolStateProgress'), toolName: item.entry.tool || t('common.tool'), text: buildText(item.entry) }; diff --git a/static/src/components/chat/quickdock/quickdock.css b/static/src/components/chat/quickdock/quickdock.css index 1611d80a..dd894ae1 100644 --- a/static/src/components/chat/quickdock/quickdock.css +++ b/static/src/components/chat/quickdock/quickdock.css @@ -697,15 +697,16 @@ min-width: 0; } -.qd-feed-row.feed-tool .tool-result { +.qd-feed-row.feed-tool .tool-status { flex: none; margin-left: auto; - font-size: 11.5px; - color: var(--text-tertiary); - font-variant-numeric: tabular-nums; + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 14px; } -.qd-feed-row.feed-tool .tool-result.is-error { +.qd-feed-row.feed-tool .tool-status.is-error .qd-tool-done { color: var(--state-danger); } @@ -733,6 +734,25 @@ color: var(--accent); } +.qd-feed-row.feed-compressed { + justify-content: center; + padding: 2px 14px; +} + +.qd-feed-row.feed-compressed .feed-compressed__label { + display: inline-flex; + align-items: center; + gap: 5px; + font-size: 11.5px; + color: var(--text-tertiary); +} + +.qd-feed-row.feed-compressed .feed-compressed__icon { + width: 12px; + height: 12px; + flex: none; +} + .qd-feed-row.feed-term { font-family: ui-monospace, 'SF Mono', Menlo, monospace; font-size: 12px; diff --git a/static/src/locales/en-US/quickdock.ts b/static/src/locales/en-US/quickdock.ts index 578fb469..9e9617ce 100644 --- a/static/src/locales/en-US/quickdock.ts +++ b/static/src/locales/en-US/quickdock.ts @@ -39,10 +39,9 @@ export default { toolRunCommand: 'Run command {command}', toolEditFile: 'Edit {path}', toolReadMedia: 'Read media file {path}', - toolStateDone: 'Done', - toolStateFailed: 'Failed', - toolStateCalling: 'Calling...', - toolStateProgress: 'In progress', + + // —— Sub-agent detail panel: context compression notice —— + contextCompressed: 'Context compressed (round {round})', // —— File preview panel —— resizeWidthHint: 'Drag to resize width', diff --git a/static/src/locales/zh-CN/quickdock.ts b/static/src/locales/zh-CN/quickdock.ts index ab36406d..d8b45681 100644 --- a/static/src/locales/zh-CN/quickdock.ts +++ b/static/src/locales/zh-CN/quickdock.ts @@ -46,10 +46,9 @@ export default { toolRunCommand: '运行命令 {command}', toolEditFile: '编辑 {path}', toolReadMedia: '读取媒体文件 {path}', - toolStateDone: '完成', - toolStateFailed: '失败', - toolStateCalling: '调用中', - toolStateProgress: '进行中', + + // —— 子智能体详情面板:上下文压缩提示 —— + contextCompressed: '上下文已压缩(第 {round} 轮)', // —— 文件预览面板(FilePreviewPanel) —— resizeWidthHint: '拖拽调整宽度',