From a3f572244b687bb8523e89f51200a7e9216dfd44 Mon Sep 17 00:00:00 2001 From: bowenliang123 Date: Mon, 19 Oct 2026 10:39:53 +0800 Subject: [PATCH] feat(client): drop the collapsed file row's error dot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Failures now surface only on the expanded op rows. The collapsed row's aggregate tally added little on its own (its edit ops already flag the failing tool call), so FileEntry.errs — which existed only for that dot — and the files.errs strings go with it; each op keeps its own err flag for the expanded dots. --- src/client/components/fileCard.tsx | 1 - src/client/fileActivity.ts | 3 --- src/client/i18nEn.ts | 1 - src/client/i18nZh.ts | 1 - tests/client/components/fileCard.spec.ts | 6 +++--- tests/client/components/fileCardWindow.spec.ts | 2 +- tests/client/fileActivity.spec.ts | 9 +++------ 7 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/client/components/fileCard.tsx b/src/client/components/fileCard.tsx index 6082646..3bf018a 100644 --- a/src/client/components/fileCard.tsx +++ b/src/client/components/fileCard.tsx @@ -319,7 +319,6 @@ export function makeFileCard(kit: ViewKit, settings: ContextSettings): Component {fmt(e.searches)} ) : null} {e.added + e.removed > 0 ? : null} - {e.errs > 0 ? : null} {e.ops[0].time !== undefined ? {fmtTime(e.ops[0].time)} : null} diff --git a/src/client/fileActivity.ts b/src/client/fileActivity.ts index e631c7d..57c6efb 100644 --- a/src/client/fileActivity.ts +++ b/src/client/fileActivity.ts @@ -28,7 +28,6 @@ export interface FileEntry { searches: number added: number removed: number - errs: number ops: FileOp[] /** Set when `path` is a pathless search's PATTERN, not a file path — display must not relativize it. */ pattern?: true @@ -243,7 +242,6 @@ function aggregateOps(ops: readonly FileOp[], before: number | null): FileActivi searches: 0, added: 0, removed: 0, - errs: 0, ops: [], ...(op.pattern === true ? { pattern: true as const } : {}), } @@ -254,7 +252,6 @@ function aggregateOps(ops: readonly FileOp[], before: number | null): FileActivi else entry.searches++ entry.added += op.added entry.removed += op.removed - if (op.err) entry.errs++ entry.ops.push(op) } const entries = [...byPath.values()] diff --git a/src/client/i18nEn.ts b/src/client/i18nEn.ts index 34cc0ae..c496703 100644 --- a/src/client/i18nEn.ts +++ b/src/client/i18nEn.ts @@ -173,7 +173,6 @@ export const DICT_EN = { 'files.open': 'Open on your system', 'files.preview': 'Preview in the sidebar', 'files.readEst': 'Lines read, estimated from the limit argument', - 'files.errs': '{n} failed', 'files.form.image': 'Image', 'files.form.dir': 'Directory', 'files.form.text': 'File', diff --git a/src/client/i18nZh.ts b/src/client/i18nZh.ts index f6cf890..9f8e72b 100644 --- a/src/client/i18nZh.ts +++ b/src/client/i18nZh.ts @@ -171,7 +171,6 @@ export const DICT_ZH = { 'files.open': '在系统中打开', 'files.preview': '在侧边栏预览', 'files.readEst': '按调用参数 limit 估算的读取行数', - 'files.errs': '{n} 次失败', 'files.form.image': '图片', 'files.form.dir': '目录', 'files.form.text': '文件', diff --git a/tests/client/components/fileCard.spec.ts b/tests/client/components/fileCard.spec.ts index 0e24286..6120945 100644 --- a/tests/client/components/fileCard.spec.ts +++ b/tests/client/components/fileCard.spec.ts @@ -18,7 +18,7 @@ function fileOp(seq: number, kind: FileOp['kind'], tool: string, over: Partial): FileEntry { - return { path, form: 'text', reads: 0, writes: 0, searches: 0, added: 0, removed: 0, errs: 0, ops: [], ...over } + return { path, form: 'text', reads: 0, writes: 0, searches: 0, added: 0, removed: 0, ops: [], ...over } } function richActivity(over: Partial = {}): FileActivity { @@ -29,7 +29,6 @@ function richActivity(over: Partial = {}): FileActivity { writes: 2, added: 2, removed: 3, - errs: 1, ops: [ fileOp(7, 'read', 'read'), fileOp(5, 'write', 'edit', { added: 2, removed: 1 }), @@ -129,7 +128,8 @@ describe('FileCard — header, rows, and filters', () => { assert.ok(aRow.querySelector('.lc-fa-path b')?.textContent === 'a.ts') assert.equal(queryAll(aRow, '.lc-fa-badge').length, 2) // read + write assert.ok(text(aRow).includes('+2') && text(aRow).includes('−3')) - assert.ok(aRow.querySelector('.lc-br-err-dot') !== null) + // Failures surface on the expanded op rows only: the collapsed row keeps no error dot. + assert.equal(queryAll(aRow, '.lc-br-err-dot').length, 0) assert.ok(aRow.title === '/src/a.ts') const dirRow = rows.find(r => r.title === '/src/') assert.ok(dirRow !== undefined) diff --git a/tests/client/components/fileCardWindow.spec.ts b/tests/client/components/fileCardWindow.spec.ts index 558b604..66dd698 100644 --- a/tests/client/components/fileCardWindow.spec.ts +++ b/tests/client/components/fileCardWindow.spec.ts @@ -75,7 +75,7 @@ afterAll(() => { function entry(index: number): FileEntry { const op: FileOp = { seq: index, kind: 'read', tool: 'read', time: T0 + index, err: false, added: 0, removed: 0, path: '' } - return { path: `/src/file-${String(index).padStart(3, '0')}.ts`, form: 'text', reads: 1, writes: 0, searches: 0, added: 0, removed: 0, errs: 0, ops: [op] } + return { path: `/src/file-${String(index).padStart(3, '0')}.ts`, form: 'text', reads: 1, writes: 0, searches: 0, added: 0, removed: 0, ops: [op] } } function activityOf(count: number): FileActivity { diff --git a/tests/client/fileActivity.spec.ts b/tests/client/fileActivity.spec.ts index 7acbfe8..2d23211 100644 --- a/tests/client/fileActivity.spec.ts +++ b/tests/client/fileActivity.spec.ts @@ -108,7 +108,6 @@ describe('activityOf', () => { assert.equal(file.searches, 0) assert.equal(file.added, 2) // edit new_string: 'x\nq' assert.equal(file.removed, 3) // edit old_string: 'x\ny\nz' - assert.equal(file.errs, 0) // Ops newest first inside the entry. assert.deepEqual(file.ops.map(o => o.seq), [7, 5, 3]) assert.equal(file.ops[0].kind, 'read') @@ -148,16 +147,14 @@ describe('activityOf', () => { assert.deepEqual(a.totals.image, { files: 2, ops: 2 }) }) - test('counts failures from the fold stamp or the snapshot error flag', () => { + test('stamps the error flag from the fold or the snapshot', () => { const a = run([ op(3, 'read', { file_path: '/a.ts' }, { err: true }), op(5, 'read', { file_path: '/a.ts' }, {}, { isError: true }), op(7, 'read', { file_path: '/b.ts' }), ]) - const file = a.entries[1] - assert.equal(file.errs, 2) - assert.equal(file.ops[0].err, true) - assert.equal(a.entries[0].errs, 0) + assert.deepEqual(a.entries[1].ops.map(o => o.err), [true, true]) + assert.equal(a.entries[0].ops[0].err, false) }) test('carries the archive removal stamp onto the op for locate targeting', () => {