Skip to content

Commit ad09599

Browse files
bloveclaude
andcommitted
fix(chat): drop misleading "<1s" from merged reasoning label when timing is unknown
Addresses the second AI review comment on #724. When no reasoning step reports a duration, durationMs is undefined and the label previously read "Thought for <1s · N steps" — "<1s" implies fast when it really means "no timing data". Now label by step count alone ("N steps") in that case; the "Thought for {total} · N steps" form is used only when at least one step reported timing. Updates the pinned unit test to assert the new behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 7e84281 commit ad09599

2 files changed

Lines changed: 12 additions & 6 deletions

File tree

libs/chat/src/lib/compositions/chat/chat.component.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -733,13 +733,13 @@ describe('ChatComponent — reasoning runs (merged pill)', () => {
733733
expect(run.label).toBe('Thought for 2s · 2 steps');
734734
});
735735

736-
it('all durations undefined → durationMs undefined; label falls back to "<1s" (documents current behavior)', () => {
737-
// Flagged by review: "<1s" reads as "fast" when it really means "no timing
738-
// data". This pins the CURRENT behavior so any intentional change is visible.
736+
it('all durations undefined → durationMs undefined; label drops the duration phrase ("N steps")', () => {
737+
// Per review: "Thought for <1s" reads as "fast" when timing is actually
738+
// unknown. With no step reporting a duration, label by step count alone.
739739
const a = api([user('u1'), reasoning('a1', 'first'), tool('t1'), reasoning('a2', 'second')]);
740740
const run = a.reasoningRun(1);
741741
expect(run.durationMs).toBeUndefined();
742-
expect(run.label).toBe('Thought for <1s · 2 steps');
742+
expect(run.label).toBe('2 steps');
743743
});
744744

745745
it('mixed defined/undefined durations sum only the numeric ones', () => {

libs/chat/src/lib/compositions/chat/chat.component.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,8 @@ export class ChatComponent {
500500
/**
501501
* Aggregate the reasoning RUN starting at `index`: joins each step's
502502
* reasoning, sums durations, counts steps, and computes the streaming flag
503-
* and the merged label ("Thought for {total} · {N} steps" when N > 1).
503+
* and the merged label when N > 1 ("Thought for {total} · {N} steps", or
504+
* just "{N} steps" when no step reported timing).
504505
*/
505506
protected reasoningRun(index: number): {
506507
content: string;
@@ -523,9 +524,14 @@ export class ChatComponent {
523524
const durationMs = durations.length ? durations.reduce((a, b) => a + b, 0) : undefined;
524525
const last = steps[steps.length - 1];
525526
const streaming = last ? this.isReasoningStreaming(last.msg, last.idx) : false;
527+
// Only claim a duration when at least one step reported timing. Otherwise
528+
// "Thought for <1s" would read as "fast" when it really means "unknown", so
529+
// drop the duration phrase and label by step count alone.
526530
const label =
527531
steps.length > 1
528-
? `Thought for ${formatDuration(durationMs ?? 0)} · ${steps.length} steps`
532+
? durationMs !== undefined
533+
? `Thought for ${formatDuration(durationMs)} · ${steps.length} steps`
534+
: `${steps.length} steps`
529535
: undefined;
530536
return { content, durationMs, streaming, label };
531537
}

0 commit comments

Comments
 (0)