From 801eba92843c8b43ba1bd2c37a49b9a7600b0ac7 Mon Sep 17 00:00:00 2001 From: Andre Padez Date: Tue, 11 Aug 2026 02:43:14 +0100 Subject: [PATCH] say which harness owns a chat row, on both kinds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../src/apps/ChatHistory/SessionList.tsx | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/workspaces/officerdev/src/apps/ChatHistory/SessionList.tsx b/src/workspaces/officerdev/src/apps/ChatHistory/SessionList.tsx index 4c836465..8cf84826 100644 --- a/src/workspaces/officerdev/src/apps/ChatHistory/SessionList.tsx +++ b/src/workspaces/officerdev/src/apps/ChatHistory/SessionList.tsx @@ -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' ? ( + OpenCode + ) : ( + Claude + ); + // 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={[ , - session.harness === 'opencode' ? ( - - OpenCode - - ) : ( - `${session.messageCount} msg${session.messageCount === 1 ? '' : 's'}` - ), + , + // 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