say which harness owns a chat row, on both kinds
The list is merged from two stores and only OpenCode rows were badged, so Claude was marked by the ABSENCE of a badge — legible only if you already knew the list mixes two harnesses. Both carry one now, and since `harness` is absent on older Claude rows, anything not OpenCode reads as Claude, matching the server's own default. The badge no longer replaces the message count, it sits before it: the count is real on Claude rows and a hardcoded 0 on OpenCode ones (the session list has no count field and a real one costs an HTTP call per row), so those rows show the badge and no count rather than a zero that means "never asked". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,24 @@ import type { SelectedSession } from './ChatDetailPanel';
|
||||
import { chatListPath, chatNewPath, chatSessionPath, cwdFromSplat } from './chat-routes';
|
||||
import { PwdSelector } from './PwdSelector';
|
||||
|
||||
/**
|
||||
* Which agent owns a conversation, said on EVERY row.
|
||||
*
|
||||
* Only OpenCode rows carried a badge before, which marks one harness and leaves the other inferred from
|
||||
* its absence — fine when you already know the list mixes two, useless when you don't. The list is
|
||||
* merged from two stores (Claude transcripts, OpenCode's session db) and the harness decides where a
|
||||
* reply is dispatched, so it is a property of the row, not a footnote on the odd one out.
|
||||
*
|
||||
* `harness` is absent on older Claude rows, so anything that is not OpenCode reads as Claude — the same
|
||||
* default the server applies.
|
||||
*/
|
||||
const HarnessBadge = ({ harness }: { harness?: 'claude' | 'opencode' }) =>
|
||||
harness === 'opencode' ? (
|
||||
<span className="rounded bg-info/10 px-1.5 py-0.5 font-medium text-info">OpenCode</span>
|
||||
) : (
|
||||
<span className="rounded bg-primary/10 px-1.5 py-0.5 font-medium text-primary">Claude</span>
|
||||
);
|
||||
|
||||
// Reads the /chat conversation list from Claude's own transcript store (source of truth).
|
||||
// Clicking a session loads its transcript and continues the real Claude session via --resume.
|
||||
export const SessionList = () => {
|
||||
@@ -194,13 +212,14 @@ export const SessionList = () => {
|
||||
className="min-w-0 flex-1"
|
||||
meta={[
|
||||
<RelativeTime key="t" value={session.updatedAt} />,
|
||||
session.harness === 'opencode' ? (
|
||||
<span key="h" className="rounded bg-info/10 px-1.5 py-0.5 font-medium text-info">
|
||||
OpenCode
|
||||
</span>
|
||||
) : (
|
||||
`${session.messageCount} msg${session.messageCount === 1 ? '' : 's'}`
|
||||
),
|
||||
<HarnessBadge key="h" harness={session.harness} />,
|
||||
// Claude's transcripts give a real turn count. OpenCode's session list has no
|
||||
// count field, so the number on those rows is a hardcoded 0 and costs an HTTP
|
||||
// call per row to make real — the badge stands in its place rather than beside a
|
||||
// zero that means "not asked".
|
||||
session.harness === 'opencode'
|
||||
? null
|
||||
: `${session.messageCount} msg${session.messageCount === 1 ? '' : 's'}`,
|
||||
// One row, several transcripts: this conversation was `/clear`ed and carried on,
|
||||
// and the server has spliced the parts back together. Worth saying out loud —
|
||||
// the message count above covers all of them, and opening the row shows all of
|
||||
|
||||
Reference in New Issue
Block a user