Compare commits

..
Author SHA1 Message Date
weichen 84b73ab328 Merge pull request 'Show last-request and cumulative tokens in the usage badge (N3 WP6)' (#48) from feature/n3-usage-badge into main
Show last-request and cumulative tokens in the usage badge (N3 WP6)
2026-10-07 17:30:49 +00:00
weichen c71a77bb22 Show last-request and cumulative tokens in the usage badge (N3 WP6)
Why: run.Usage now carries the WP6 split fields; the badge should show
them ('+last · cumulative · duration · tools', cache hits in the
tooltip).
Evidence: npx tsc --noEmit clean; npx vitest run 82/82 green.
Impact: display only.
Refs: Agent-System-Backend#96, N3 plan WP6
2026-10-07 17:19:28 +00:00
weichen 50c7244601 Hide the conversation column when the preview expands (#47)
Restore hidden on the conversation column and center wide docx pages.
2026-10-05 05:38:03 +00:00
weichenandCursor 2464c16e6b Hide the conversation column when the preview expands
Why: .main { display: flex } overrides the UA [hidden] rule, so previewExpanded left the conversation column in the row and squeezed the preview.
Evidence: vitest test/previewfit.test.ts and test/design-guard.test.ts passed (10 tests). Headless Chromium at 1512x900: expanded .main is display:none and the preview slot is 1184px with the page centered (center delta 0); at 420px and 640px the wrapper stays column-width and the page stays left-aligned.
Impact: expanded preview fills the main row; docx pages center only when the column is wider than the page. Narrow-column fit scaling is unchanged. previewfit still returns 1 when available width is <= 0.
Refs: App.tsx hidden={previewExpanded}; styles.css .main and .docx-wrapper
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-05 05:37:21 +00:00
weichen 0a0b55612c Make the preview pane the only scrolling preview 2026-10-05 04:42:24 +00:00
3 changed files with 16 additions and 3 deletions
+5 -2
View File
@@ -78,7 +78,10 @@ export function AgentTracker() {
function UsageBadge({ usage }: { usage?: Usage | null }) {
if (!usage) return null
return <span className="effect-badge" title="token 用量与时长">
{usage.totalTokens > 0 ? `${usage.totalTokens} tok · ` : ''}{(usage.durationMs / 1000).toFixed(1)}s{usage.toolCalls > 0 ? ` · ${usage.toolCalls} 工具` : ''}
// N3 计费拆分:有上一请求数据时显示「+最近 · 累计(含缓存命中)」。
const last = (usage.lastPromptTokens ?? 0) + (usage.lastCompletionTokens ?? 0)
const cache = usage.cacheReadTokens ?? 0
return <span className="effect-badge" title={cache > 0 ? `token 用量与时长(缓存命中 ${cache})` : 'token 用量与时长'}>
{last > 0 ? `+${last} · ` : ''}{usage.totalTokens > 0 ? `累计 ${usage.totalTokens} tok · ` : ''}{(usage.durationMs / 1000).toFixed(1)}s{usage.toolCalls > 0 ? ` · ${usage.toolCalls} 工具` : ''}
</span>
}
+6
View File
@@ -60,6 +60,12 @@ export interface Usage {
promptTokens: number; completionTokens: number; totalTokens: number;
durationMs: number; toolCalls: number;
model?: string;
// N3 计费拆分(additive;旧记录缺省为 0):
// Last* 是最近一次请求的用量,Cache* 是缓存命中累计。
lastPromptTokens?: number;
lastCompletionTokens?: number;
cacheReadTokens?: number;
cacheWriteTokens?: number;
}
export interface Run {
+5 -1
View File
@@ -54,6 +54,8 @@ button { font-family: inherit; font-size: inherit; color: inherit; }
.divider:hover::before, .divider.dragging::before { background: var(--border-strong); }
.divider::after { content: ''; position: absolute; inset: 0 -3px; } /* 拖拽热区加宽 */
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--bg); border: 1px solid var(--border-soft); border-radius: var(--radius-lg); }
/* 作者 display 声明会压过 UA 的 [hidden],此处显式恢复;展开预览靠它隐藏对话列 */
.main[hidden] { display: none !important; }
.right-panel { background: var(--bg-panel); border: 1px solid var(--border-soft); border-radius: var(--radius-lg); display: flex; flex-direction: column; flex-shrink: 0; min-width: 0; }
.right-panel.collapsed { width: 44px !important; }
@@ -212,7 +214,9 @@ button { font-family: inherit; font-size: inherit; color: inherit; }
font-family: var(--mono); font-size: var(--fs-code); background: var(--bg); color: var(--text);
}
.docx-wrapper { background: var(--bg-inset) !important; padding: 12px; display: flex; flex-direction: column; align-items: flex-start !important; }
.docx-wrapper > section.docx { background: var(--paper) !important; color: var(--paper-ink); box-shadow: var(--shadow-md); }
/* 宽栏时纸张居中。auto margin 优先于 align-items;栏比纸窄时剩余空间为负,margin 归零,
纸张仍贴左,previewfit 的 transform-origin: top left 不用改。 */
.docx-wrapper > section.docx { background: var(--paper) !important; color: var(--paper-ink); box-shadow: var(--shadow-md); margin-inline: auto; }
/* 过程段内联组(流式/关闭自动折叠时,按原位渲染的过程容器) */
.part-group { margin: 2px 0; }