revert the second server too: one officer, one token, this origin

Andre wants to log out and log back in against a single server, so this takes out dc6b623 and my
token-resolution change with it — the latter first, because it was written against
useServerClient, which dc6b623 introduced.

Gone: the connections store, the server chips, the per-server client and the per-server socket
url. `useClient()` is back to one origin, `/api`, and the session it already holds. The chat
socket url is back to what it was:

  const token = localStorage.getItem('BEARER_TOKEN');
  const wsUrl = `${protocol}//${window.location.host}/api/chat/ws?token=${token}`;

Verified: the staged tree is byte-identical to dc6b623^ across all of src/.

Two things he should know rather than discover.

The old line reads localStorage and nothing else — the same single spelling I widened an hour ago
and have now removed again. If his token is NOT in localStorage, this code fails exactly as
before, and worse: a missing one interpolates as the literal string "null" rather than an empty
value. Reverting cannot fix that class of problem; it restores it.

`officer.connections.v1` stays in his browser's localStorage with alpha's API key in it. Nothing
reads it now, so it is inert, but it is a credential sitting in a store nobody owns any more and
should be cleared by hand.

Typecheck clean. 600 pass, 2 fail — cliamp and pty, unchanged all evening and unrelated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 23:37:02 +01:00
co-authored by Claude Opus 5
parent 52d567874f
commit 31ffe084f5
10 changed files with 58 additions and 539 deletions
@@ -5,7 +5,6 @@ import { WorkspaceView, chatListPath, cwdFromSplat, useSelectedChatSession } fro
import { toast } from '@/components/ui/sonner';
import { useIsMobile } from 'hooks/useIsMobile';
import { useClient } from 'hooks/useClient';
import { serverClient } from 'hooks/useServerClient';
import { errorText } from 'helpers/error-text';
import { useDashboardState } from 'state/useDashboardState';
import type { ClaudeSessionDetail } from 'state/useClaudeSessions';
@@ -74,7 +73,7 @@ export const SessionListPage = ({ isNew }: SessionListPageProps) => {
if (isNew) {
// A new chat has no transcript to read a cwd from, so the group in the URL is the authority —
// and it has to be on the selection, because that is what the composer runs in.
setSelected({ id: `new:${Date.now()}`, cwd: groupCwd, serverId: selectedRef.current?.serverId ?? null });
setSelected({ id: `new:${Date.now()}`, cwd: groupCwd });
return;
}
if (!sessionId) return;
@@ -82,13 +81,7 @@ export const SessionListPage = ({ isNew }: SessionListPageProps) => {
let cancelled = false;
(async () => {
try {
// Read the transcript from the machine the row came from, not from this origin. The list
// stamps the server onto the selection before navigating, so it is known by the time this runs;
// a bare deep link has none and correctly resolves against this origin.
const remote = selectedRef.current?.serverId ?? null;
const detail = await serverClient(remote).get<ClaudeSessionDetail>(
`/chat/sessions/${sessionId}?limit=${CHAT_TAIL}`,
);
const detail = await client.get<ClaudeSessionDetail>(`/chat/sessions/${sessionId}?limit=${CHAT_TAIL}`);
if (cancelled) return;
// The session's own cwd rides on the selection rather than being written back into the URL.
// It used to do both, and the URL copy was the one the composer read — so a deep link ran its
@@ -103,7 +96,6 @@ export const SessionListPage = ({ isNew }: SessionListPageProps) => {
cwd: detail.cwd,
title: detail.title,
partCount: detail.partCount,
serverId: remote,
});
} catch (err) {
if (cancelled) return;
@@ -111,7 +103,7 @@ export const SessionListPage = ({ isNew }: SessionListPageProps) => {
// no hint that the transcript could not be read, which is indistinguishable from a new session.
// Most often the id is stale — the transcript was deleted or pruned out from under the link.
toast.error(`Could not load this conversation: ${errorText(err, 'not found')}`);
setSelected({ id: sessionId, serverId: selectedRef.current?.serverId ?? null });
setSelected({ id: sessionId });
}
})();
return () => {