the session list was asking for a directory that does not exist
Your conversation was there the whole time. The dropdown was empty because I sent
the wrong kind of path.
what the header sent -Tests-platform no such directory
what is on disk -home-pastilhas-Tests-platform 1 transcript
Two conventions live next to each other and I used the wrong one. The file
endpoints take a HOME-RELATIVE path (`/Tests/platform`) — that is what `cwdToPath`
produces and what the file browser and editor pass. `/chat/sessions` takes the
ABSOLUTE one, because Claude's folder name is
`cwd.replace(/[^a-zA-Z0-9]/g, '-')` applied to the directory a turn actually ran
in, and a turn runs in a real directory.
`cwdOf` uses the query value verbatim (`query('cwd')?.trim() || home`), so nothing
rejected the relative form — it just resolved to a slug for a directory that has
never existed, and answered an empty list rather than an error. The failure had no
symptom beyond "no conversations", which is also what a genuinely empty directory
looks like.
Joined against `useChatPwds().defaultCwd` — the caller's home as the SERVER sees
it, and the same value `cwdOf` falls back to — rather than guessing at where home
is a second time.
Verified end to end: `~/Tests/platform` now resolves to
`/home/pastilhas/Tests/platform`, whose slug is `-home-pastilhas-Tests-platform`,
which is a directory that exists and holds the transcript.
tsgo clean, frontend builds, 846 pass / 7 fail unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { useClaudeSessions } from 'state/useClaudeSessions';
|
||||
import { useChatPwds, useClaudeSessions } from 'state/useClaudeSessions';
|
||||
import { useWorkspace, cwdToPath } from '../../components/Workspace';
|
||||
import { usePanelSession } from './use-panel-session';
|
||||
import type { ChatMessage } from './types';
|
||||
@@ -34,10 +34,23 @@ const title = (s: { title: string }) => s.title || '(untitled)';
|
||||
|
||||
export const ChatHeader = ({ panelId }: { panelId?: string }) => {
|
||||
const { workspace, cwd } = useWorkspace();
|
||||
const cwdPath = cwdToPath(cwd);
|
||||
// The endpoint takes a home-relative path and treats absent as "the caller's default", which is what an
|
||||
// unscoped panel wants.
|
||||
const { sessions, renameSession, deleteSession } = useClaudeSessions(cwdPath === '/' ? null : cwdPath);
|
||||
|
||||
/**
|
||||
* `/chat/sessions` wants an ABSOLUTE path, and that is not the convention next door.
|
||||
*
|
||||
* The file endpoints take a home-relative path (`/Tests/platform`); chat takes the real one, because
|
||||
* Claude's folder name is `cwd.replace(/[^a-zA-Z0-9]/g, '-')` applied to the directory a turn actually
|
||||
* ran in. Handing it the home-relative form asked for `-Tests-platform`, which is not a directory that
|
||||
* exists, so a dashboard with a perfectly good conversation in it listed nothing at all.
|
||||
*
|
||||
* `useChatPwds().defaultCwd` is the caller's home as the server sees it — the same value `cwdOf` falls
|
||||
* back to — so it is the right thing to join against rather than a second guess at where home is.
|
||||
*/
|
||||
const { defaultCwd } = useChatPwds();
|
||||
const relative = cwdToPath(cwd);
|
||||
const absoluteCwd = relative === '/' ? null : defaultCwd ? `${defaultCwd.replace(/\/$/, '')}${relative}` : null;
|
||||
|
||||
const { sessions, renameSession, deleteSession } = useClaudeSessions(absoluteCwd);
|
||||
const [sessionId, setSessionId] = usePanelSession(panelId, workspace);
|
||||
|
||||
const [renaming, setRenaming] = useState<string | null>(null);
|
||||
|
||||
Reference in New Issue
Block a user