chat: run /chat sessions from the dedicated claude_sessions cwd
The standalone /chat route now tags its context as 'chat'; the backend runs those sessions with cwd = DATA_PATH/<email>/claude_sessions (created on demand), so their transcripts form an isolated Claude project group instead of polluting the home-dir history. Other chat contexts (email/project panels) keep their own cwd. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { readdirSync, readFileSync, existsSync, statSync } from 'node:fs';
|
import { readdirSync, readFileSync, existsSync, statSync, mkdirSync } from 'node:fs';
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
import { DATA_PATH } from '../../data-path';
|
import { DATA_PATH } from '../../data-path';
|
||||||
|
|
||||||
@@ -12,6 +12,13 @@ import { DATA_PATH } from '../../data-path';
|
|||||||
/** Dedicated working directory for /chat sessions, so they form their own Claude "project" group. */
|
/** Dedicated working directory for /chat sessions, so they form their own Claude "project" group. */
|
||||||
export const getClaudeSessionsCwd = (email: string): string => join(DATA_PATH, email, 'claude_sessions');
|
export const getClaudeSessionsCwd = (email: string): string => join(DATA_PATH, email, 'claude_sessions');
|
||||||
|
|
||||||
|
/** Same, but create the directory if it doesn't exist (call before spawning a /chat session). */
|
||||||
|
export const ensureClaudeSessionsCwd = (email: string): string => {
|
||||||
|
const dir = getClaudeSessionsCwd(email);
|
||||||
|
mkdirSync(dir, { recursive: true });
|
||||||
|
return dir;
|
||||||
|
};
|
||||||
|
|
||||||
const claudeProjectsDir = (email: string): string => join(DATA_PATH, email, 'home', '.claude', 'projects');
|
const claudeProjectsDir = (email: string): string => join(DATA_PATH, email, 'home', '.claude', 'projects');
|
||||||
|
|
||||||
/** Claude's folder name for a working directory. */
|
/** Claude's folder name for a working directory. */
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { ClientMessage, ServerMessage, Message, PiEvent } from './types';
|
|||||||
import { sessionManager } from './session-manager';
|
import { sessionManager } from './session-manager';
|
||||||
import * as storage from './storage';
|
import * as storage from './storage';
|
||||||
import { sendClaudeCodeStreaming } from '@@/channels/send-claude-code';
|
import { sendClaudeCodeStreaming } from '@@/channels/send-claude-code';
|
||||||
|
import { ensureClaudeSessionsCwd } from '../chat/claude-sessions';
|
||||||
import * as sidecar from '@@/sidecar-registry';
|
import * as sidecar from '@@/sidecar-registry';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { getHomeDirForRole } from '../../../servers/data-path';
|
import { getHomeDirForRole } from '../../../servers/data-path';
|
||||||
@@ -296,7 +297,10 @@ async function handleClaudeCodeChat(
|
|||||||
const { email, username, userId } = ws.data;
|
const { email, username, userId } = ws.data;
|
||||||
const homeDir = getHomeDirForRole(email, ws.data.role);
|
const homeDir = getHomeDirForRole(email, ws.data.role);
|
||||||
|
|
||||||
const cwd = resolveCwd(email, ws.data.role, msg.cwd);
|
// The standalone /chat route runs every session from a dedicated `claude_sessions` working
|
||||||
|
// directory, so its transcripts form their own Claude "project" group (source of truth) instead of
|
||||||
|
// polluting the home-dir history. Other contexts (email/project panels) keep their own cwd.
|
||||||
|
const cwd = msg.context === 'chat' ? ensureClaudeSessionsCwd(email) : resolveCwd(email, ws.data.role, msg.cwd);
|
||||||
|
|
||||||
const groupSlug = msg.groupSlug || null;
|
const groupSlug = msg.groupSlug || null;
|
||||||
|
|
||||||
|
|||||||
@@ -94,11 +94,13 @@ export const ChatPanelWrapper = () => {
|
|||||||
const chatContext =
|
const chatContext =
|
||||||
dashboardId === 'email' || dashboardId === 'screens/email'
|
dashboardId === 'email' || dashboardId === 'screens/email'
|
||||||
? { context: 'email' as const }
|
? { context: 'email' as const }
|
||||||
: dashboardId?.startsWith('proj-layout-')
|
: dashboardId === 'screens/chat'
|
||||||
? { context: 'project' as const, contextId: dashboardId.replace('proj-layout-', '') }
|
? { context: 'chat' as const }
|
||||||
: dashboardId && !dashboardId.startsWith('screens/')
|
: dashboardId?.startsWith('proj-layout-')
|
||||||
? { context: 'dashboard' as const, contextId: dashboardId }
|
? { context: 'project' as const, contextId: dashboardId.replace('proj-layout-', '') }
|
||||||
: {};
|
: dashboardId && !dashboardId.startsWith('screens/')
|
||||||
|
? { context: 'dashboard' as const, contextId: dashboardId }
|
||||||
|
: {};
|
||||||
|
|
||||||
const [savedId, setSavedId] = usePanelChannel<number | null>('chat:saved-id', null);
|
const [savedId, setSavedId] = usePanelChannel<number | null>('chat:saved-id', null);
|
||||||
const [selection, setSelection] = usePanelChannel<ChatSessionSelection | null>('chat:panel-session', null);
|
const [selection, setSelection] = usePanelChannel<ChatSessionSelection | null>('chat:panel-session', null);
|
||||||
|
|||||||
Reference in New Issue
Block a user