diff --git a/server/src/modules/workspaces/workspaces.routes.ts b/server/src/modules/workspaces/workspaces.routes.ts index e348fd77..f198169e 100644 --- a/server/src/modules/workspaces/workspaces.routes.ts +++ b/server/src/modules/workspaces/workspaces.routes.ts @@ -16,17 +16,17 @@ const getTrimmedString = (value: unknown): string => { return value.trim(); }; -const parseWorkspacePathFromBody = (req: Request): string => { +const parseWorkspaceIdFromBody = (req: Request): string => { const body = req.body as Record | undefined; - const workspacePath = getTrimmedString(body?.workspacePath); - if (!workspacePath) { - throw new AppError('workspacePath is required.', { - code: 'WORKSPACE_PATH_REQUIRED', + const workspaceId = getTrimmedString(body?.workspaceId); + if (!workspaceId) { + throw new AppError('workspaceId is required.', { + code: 'WORKSPACE_ID_REQUIRED', statusCode: 400, }); } - return workspacePath; + return workspaceId; }; const parseWorkspaceCustomNameFromBody = (req: Request): string | null => { @@ -46,27 +46,27 @@ router.get( router.patch( '/star', asyncHandler(async (req: Request, res: Response) => { - const workspacePath = parseWorkspacePathFromBody(req); - const isStarred = workspaceService.toggleWorkspaceStar(workspacePath); - res.json(createApiSuccessResponse({ workspacePath, isStarred })); + const workspaceId = parseWorkspaceIdFromBody(req); + const isStarred = workspaceService.toggleWorkspaceStar(workspaceId); + res.json(createApiSuccessResponse({ workspaceId, isStarred })); }), ); router.patch( '/name', asyncHandler(async (req: Request, res: Response) => { - const workspacePath = parseWorkspacePathFromBody(req); + const workspaceId = parseWorkspaceIdFromBody(req); const workspaceCustomName = parseWorkspaceCustomNameFromBody(req); - workspaceService.updateWorkspaceCustomName(workspacePath, workspaceCustomName); - res.json(createApiSuccessResponse({ workspacePath, workspaceCustomName })); + workspaceService.updateWorkspaceCustomName(workspaceId, workspaceCustomName); + res.json(createApiSuccessResponse({ workspaceId, workspaceCustomName })); }), ); router.delete( '/', asyncHandler(async (req: Request, res: Response) => { - const workspacePath = parseWorkspacePathFromBody(req); - const result = await workspaceService.deleteWorkspace(workspacePath); + const workspaceId = parseWorkspaceIdFromBody(req); + const result = await workspaceService.deleteWorkspace(workspaceId); res.json(createApiSuccessResponse(result)); }), ); diff --git a/server/src/modules/workspaces/workspaces.service.ts b/server/src/modules/workspaces/workspaces.service.ts index 5162f68a..ff934e6b 100644 --- a/server/src/modules/workspaces/workspaces.service.ts +++ b/server/src/modules/workspaces/workspaces.service.ts @@ -19,6 +19,7 @@ export type WorkspaceSessionRecord = { }; export type WorkspaceRecord = { + workspaceId: string; workspaceOriginalPath: string; workspaceCustomName: string | null; workspaceDisplayName: string; @@ -107,6 +108,7 @@ const buildWorkspaceSessionCollection = (): WorkspaceRecord[] => { const lastActivity = sessions[0]?.lastActivity || null; return { + workspaceId: workspaceRow.workspace_id, workspaceOriginalPath: workspaceRow.workspace_path, workspaceCustomName: workspaceRow.custom_workspace_name, workspaceDisplayName: @@ -130,8 +132,8 @@ export const workspaceService = { return buildWorkspaceSessionCollection(); }, - toggleWorkspaceStar(workspacePath: string): boolean { - const workspaceRow = workspaceOriginalPathsDb.getWorkspacePath(workspacePath); + toggleWorkspaceStar(workspaceId: string): boolean { + const workspaceRow = workspaceOriginalPathsDb.getWorkspaceById(workspaceId); if (!workspaceRow) { throw new AppError('Workspace not found.', { code: 'WORKSPACE_NOT_FOUND', @@ -140,22 +142,40 @@ export const workspaceService = { } const nextIsStarred = workspaceRow.isStarred !== 1; - workspaceOriginalPathsDb.updateWorkspaceIsStarred(workspacePath, nextIsStarred); + workspaceOriginalPathsDb.updateWorkspaceIsStarredById(workspaceId, nextIsStarred); return nextIsStarred; }, - updateWorkspaceCustomName(workspacePath: string, workspaceCustomName: string | null): void { - workspaceOriginalPathsDb.updateCustomWorkspaceName(workspacePath, workspaceCustomName); + updateWorkspaceCustomName(workspaceId: string, workspaceCustomName: string | null): void { + const workspaceRow = workspaceOriginalPathsDb.getWorkspaceById(workspaceId); + if (!workspaceRow) { + throw new AppError('Workspace not found.', { + code: 'WORKSPACE_NOT_FOUND', + statusCode: 404, + }); + } + + workspaceOriginalPathsDb.updateCustomWorkspaceNameById(workspaceId, workspaceCustomName); }, - async deleteWorkspace(workspacePath: string): Promise<{ + async deleteWorkspace(workspaceId: string): Promise<{ + workspaceId: string; workspacePath: string; deletedWorkspace: boolean; deletedSessionCount: number; jsonlDeletedCount: number; failedSessionFileDeletes: string[]; }> { + const workspaceRow = workspaceOriginalPathsDb.getWorkspaceById(workspaceId); + if (!workspaceRow) { + throw new AppError('Workspace not found.', { + code: 'WORKSPACE_NOT_FOUND', + statusCode: 404, + }); + } + + const workspacePath = workspaceRow.workspace_path; const sessionRows = sessionsDb.getSessionsByWorkspacePath(workspacePath); const failedSessionFileDeletes: string[] = []; let jsonlDeletedCount = 0; @@ -175,9 +195,10 @@ export const workspaceService = { } } - workspaceOriginalPathsDb.deleteWorkspacePath(workspacePath); + workspaceOriginalPathsDb.deleteWorkspaceById(workspaceId); return { + workspaceId, workspacePath, deletedWorkspace: true, deletedSessionCount: sessionRows.length, diff --git a/server/src/shared/database/migrations.ts b/server/src/shared/database/migrations.ts index 538a57cf..63b661f1 100644 --- a/server/src/shared/database/migrations.ts +++ b/server/src/shared/database/migrations.ts @@ -10,6 +10,14 @@ import { } from "@/shared/database/schema.js"; import { logger } from "@/shared/utils/logger.js"; +const SQLITE_UUID_SQL = ` +lower(hex(randomblob(4))) || '-' || +lower(hex(randomblob(2))) || '-' || +lower(hex(randomblob(2))) || '-' || +lower(hex(randomblob(2))) || '-' || +lower(hex(randomblob(6))) +`; + const addColumnToTableIfNotExists = ( db: Database, tableName: string, @@ -61,7 +69,9 @@ export const runMigrations = (db: Database) => { db.exec("UPDATE sessions SET updated_at = COALESCE(updated_at, CURRENT_TIMESTAMP)"); db.exec(WORK_SPACE_PATH_SQL); - const workspaceOriginalPathsTableInfo = db.prepare("PRAGMA table_info(workspace_original_paths)").all() as { name: string }[]; + const workspaceOriginalPathsTableInfo = db + .prepare("PRAGMA table_info(workspace_original_paths)") + .all() as { name: string; pk: number }[]; const workspaceOriginalPathsColumnNames = workspaceOriginalPathsTableInfo.map((col) => col.name); addColumnToTableIfNotExists( db, @@ -70,6 +80,13 @@ export const runMigrations = (db: Database) => { "custom_workspace_name", "TEXT DEFAULT NULL", ); + addColumnToTableIfNotExists( + db, + "workspace_original_paths", + workspaceOriginalPathsColumnNames, + "workspace_id", + "TEXT", + ); addColumnToTableIfNotExists( db, "workspace_original_paths", @@ -77,9 +94,61 @@ export const runMigrations = (db: Database) => { "isStarred", "BOOLEAN DEFAULT 0", ); + db.exec(` + UPDATE workspace_original_paths + SET workspace_id = ${SQLITE_UUID_SQL} + WHERE workspace_id IS NULL OR trim(workspace_id) = '' + `); + const workspaceOriginalPathsPrimaryKeyColumn = + workspaceOriginalPathsTableInfo.find((column) => column.pk === 1)?.name ?? null; + if (workspaceOriginalPathsPrimaryKeyColumn !== "workspace_id") { + logger.info( + "Running migration: Rebuilding workspace_original_paths to set workspace_id as primary key", + ); + db.exec("PRAGMA foreign_keys = OFF"); + try { + db.exec("BEGIN TRANSACTION"); + db.exec("DROP TABLE IF EXISTS workspace_original_paths__new"); + db.exec(` + CREATE TABLE workspace_original_paths__new ( + workspace_id TEXT PRIMARY KEY NOT NULL, + workspace_path TEXT NOT NULL UNIQUE, + custom_workspace_name TEXT DEFAULT NULL, + isStarred BOOLEAN DEFAULT 0 + ) + `); + db.exec(` + INSERT INTO workspace_original_paths__new ( + workspace_id, + workspace_path, + custom_workspace_name, + isStarred + ) + SELECT + CASE + WHEN workspace_id IS NULL OR trim(workspace_id) = '' + THEN ${SQLITE_UUID_SQL} + ELSE workspace_id + END, + workspace_path, + custom_workspace_name, + COALESCE(isStarred, 0) + FROM workspace_original_paths + `); + db.exec("DROP TABLE workspace_original_paths"); + db.exec("ALTER TABLE workspace_original_paths__new RENAME TO workspace_original_paths"); + db.exec("COMMIT"); + } catch (migrationError) { + db.exec("ROLLBACK"); + throw migrationError; + } finally { + db.exec("PRAGMA foreign_keys = ON"); + } + } db.exec( "CREATE INDEX IF NOT EXISTS idx_workspace_original_paths_is_starred ON workspace_original_paths(isStarred)" ); + db.exec("DROP INDEX IF EXISTS idx_workspace_original_paths_workspace_id"); db.exec(LAST_SCANNED_AT_SQL); diff --git a/server/src/shared/database/repositories/workspace-original-paths.db.ts b/server/src/shared/database/repositories/workspace-original-paths.db.ts index c77f28bc..2fe30d73 100644 --- a/server/src/shared/database/repositories/workspace-original-paths.db.ts +++ b/server/src/shared/database/repositories/workspace-original-paths.db.ts @@ -1,3 +1,5 @@ +import { randomUUID } from 'node:crypto'; + import { getConnection } from '@/shared/database/connection.js'; import type { WorkspaceOriginalPathRow } from '@/shared/database/types.js'; @@ -5,21 +7,21 @@ export const workspaceOriginalPathsDb = { createWorkspacePath(workspacePath: string, customWorkspaceName: string | null = null): void { const db = getConnection(); db.prepare(` - INSERT INTO workspace_original_paths (workspace_path, custom_workspace_name) - VALUES (?, ?) + INSERT INTO workspace_original_paths (workspace_id, workspace_path, custom_workspace_name) + VALUES (?, ?, ?) ON CONFLICT(workspace_path) DO UPDATE SET custom_workspace_name = CASE WHEN workspace_original_paths.custom_workspace_name IS NULL OR workspace_original_paths.custom_workspace_name = '' THEN excluded.custom_workspace_name ELSE workspace_original_paths.custom_workspace_name END - `).run(workspacePath, customWorkspaceName); + `).run(randomUUID(), workspacePath, customWorkspaceName); }, getWorkspacePath(workspacePath: string): WorkspaceOriginalPathRow | null { const db = getConnection(); const row = db.prepare(` - SELECT workspace_path, custom_workspace_name, isStarred + SELECT workspace_id, workspace_path, custom_workspace_name, isStarred FROM workspace_original_paths WHERE workspace_path = ? `).get(workspacePath) as WorkspaceOriginalPathRow | undefined; @@ -27,10 +29,21 @@ export const workspaceOriginalPathsDb = { return row ?? null; }, + getWorkspaceById(workspaceId: string): WorkspaceOriginalPathRow | null { + const db = getConnection(); + const row = db.prepare(` + SELECT workspace_id, workspace_path, custom_workspace_name, isStarred + FROM workspace_original_paths + WHERE workspace_id = ? + `).get(workspaceId) as WorkspaceOriginalPathRow | undefined; + + return row ?? null; + }, + getWorkspacePaths(): WorkspaceOriginalPathRow[] { const db = getConnection(); return db.prepare(` - SELECT workspace_path, custom_workspace_name, isStarred + SELECT workspace_id, workspace_path, custom_workspace_name, isStarred FROM workspace_original_paths `).all() as WorkspaceOriginalPathRow[]; }, @@ -49,10 +62,19 @@ export const workspaceOriginalPathsDb = { updateCustomWorkspaceName(workspacePath: string, customWorkspaceName: string | null): void { const db = getConnection(); db.prepare(` - INSERT INTO workspace_original_paths (workspace_path, custom_workspace_name) - VALUES (?, ?) + INSERT INTO workspace_original_paths (workspace_id, workspace_path, custom_workspace_name) + VALUES (?, ?, ?) ON CONFLICT(workspace_path) DO UPDATE SET custom_workspace_name = excluded.custom_workspace_name - `).run(workspacePath, customWorkspaceName); + `).run(randomUUID(), workspacePath, customWorkspaceName); + }, + + updateCustomWorkspaceNameById(workspaceId: string, customWorkspaceName: string | null): void { + const db = getConnection(); + db.prepare(` + UPDATE workspace_original_paths + SET custom_workspace_name = ? + WHERE workspace_id = ? + `).run(customWorkspaceName, workspaceId); }, updateWorkspaceIsStarred(workspacePath: string, isStarred: boolean): void { @@ -64,6 +86,15 @@ export const workspaceOriginalPathsDb = { `).run(isStarred ? 1 : 0, workspacePath); }, + updateWorkspaceIsStarredById(workspaceId: string, isStarred: boolean): void { + const db = getConnection(); + db.prepare(` + UPDATE workspace_original_paths + SET isStarred = ? + WHERE workspace_id = ? + `).run(isStarred ? 1 : 0, workspaceId); + }, + deleteWorkspacePath(workspacePath: string): void { const db = getConnection(); db.prepare(` @@ -71,4 +102,12 @@ export const workspaceOriginalPathsDb = { WHERE workspace_path = ? `).run(workspacePath); }, + + deleteWorkspaceById(workspaceId: string): void { + const db = getConnection(); + db.prepare(` + DELETE FROM workspace_original_paths + WHERE workspace_id = ? + `).run(workspaceId); + }, }; diff --git a/server/src/shared/database/schema.ts b/server/src/shared/database/schema.ts index 758936dd..f3bd20ee 100644 --- a/server/src/shared/database/schema.ts +++ b/server/src/shared/database/schema.ts @@ -86,7 +86,8 @@ CREATE TABLE IF NOT EXISTS sessions ( export const WORK_SPACE_PATH_SQL = ` CREATE TABLE IF NOT EXISTS workspace_original_paths ( - workspace_path TEXT PRIMARY KEY NOT NULL, + workspace_id TEXT PRIMARY KEY NOT NULL, + workspace_path TEXT NOT NULL UNIQUE, custom_workspace_name TEXT DEFAULT NULL, isStarred BOOLEAN DEFAULT 0 ); diff --git a/server/src/shared/database/types.ts b/server/src/shared/database/types.ts index 68d365e3..0349e764 100644 --- a/server/src/shared/database/types.ts +++ b/server/src/shared/database/types.ts @@ -129,6 +129,7 @@ export type SessionWithSummary = { }; export type WorkspaceOriginalPathRow = { + workspace_id: string; workspace_path: string; custom_workspace_name: string | null; isStarred: number; // SQLite boolean: 0 | 1 diff --git a/src/App.tsx b/src/App.tsx index 0ac60761..73cf7e7f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,6 +7,7 @@ import { RootLayout } from '@/components/refactored/shared/RootLayout'; // Mock page components const Home = () =>

Home Page

Select a session or create a new project.

; +const WorkspaceContent = () =>

Workspace View

Select a session or start a new one.

; const SessionContent = () =>

Session View

Chat interface goes here.

; const router = createBrowserRouter([ @@ -26,6 +27,10 @@ const router = createBrowserRouter([ path: "/sessions/:sessionId", element: , }, + { + path: "/workspace/:workspaceId", + element: , + }, ], }, ]); diff --git a/src/components/refactored/sidebar/data/workspacesApi.ts b/src/components/refactored/sidebar/data/workspacesApi.ts index 9957f060..a613dd92 100644 --- a/src/components/refactored/sidebar/data/workspacesApi.ts +++ b/src/components/refactored/sidebar/data/workspacesApi.ts @@ -57,16 +57,16 @@ export const getWorkspaceSessions = async (): Promise => { }; export const updateWorkspaceStar = async ( - workspacePath: string, -): Promise<{ workspacePath: string; isStarred: boolean }> => { + workspaceId: string, +): Promise<{ workspaceId: string; isStarred: boolean }> => { const response = await authenticatedFetch(SIDEBAR_ENDPOINTS.updateWorkspaceStar, { method: 'PATCH', - body: JSON.stringify({ workspacePath }), + body: JSON.stringify({ workspaceId }), }); const payload = await parseJsonSafely<{ success?: boolean; data?: { - workspacePath?: string; + workspaceId?: string; isStarred?: boolean; }; error?: { message?: string }; @@ -80,18 +80,18 @@ export const updateWorkspaceStar = async ( } return { - workspacePath: payload?.data?.workspacePath || workspacePath, + workspaceId: payload?.data?.workspaceId || workspaceId, isStarred: Boolean(payload?.data?.isStarred), }; }; export const updateWorkspaceCustomName = async ( - workspacePath: string, + workspaceId: string, workspaceCustomName: string | null, ): Promise => { const response = await authenticatedFetch(SIDEBAR_ENDPOINTS.updateWorkspaceCustomName, { method: 'PATCH', - body: JSON.stringify({ workspacePath, workspaceCustomName }), + body: JSON.stringify({ workspaceId, workspaceCustomName }), }); const payload = await parseJsonSafely<{ error?: { message?: string } }>(response); @@ -103,10 +103,10 @@ export const updateWorkspaceCustomName = async ( } }; -export const deleteWorkspaceByPath = async (workspacePath: string): Promise => { +export const deleteWorkspaceById = async (workspaceId: string): Promise => { const response = await authenticatedFetch(SIDEBAR_ENDPOINTS.deleteWorkspace, { method: 'DELETE', - body: JSON.stringify({ workspacePath }), + body: JSON.stringify({ workspaceId }), }); const payload = await parseJsonSafely<{ error?: { message?: string } }>(response); diff --git a/src/components/refactored/sidebar/hooks/useWorkspaces.ts b/src/components/refactored/sidebar/hooks/useWorkspaces.ts index 65d82db4..033751af 100644 --- a/src/components/refactored/sidebar/hooks/useWorkspaces.ts +++ b/src/components/refactored/sidebar/hooks/useWorkspaces.ts @@ -3,7 +3,7 @@ import { useLocation, useNavigate } from 'react-router-dom'; import { deleteSessionById, - deleteWorkspaceByPath, + deleteWorkspaceById, getWorkspaceSessions, updateSessionCustomName, updateWorkspaceCustomName, @@ -95,7 +95,7 @@ export const useWorkspaces = () => { [filteredWorkspaces], ); - const toggleWorkspace = useCallback((workspacePath: string) => { + const toggleWorkspace = useCallback((workspaceId: string, workspacePath: string) => { setExpandedWorkspaces((previousSet) => { const nextSet = new Set(previousSet); @@ -107,7 +107,8 @@ export const useWorkspaces = () => { return nextSet; }); - }, []); + navigate(`/workspace/${encodeURIComponent(workspaceId)}`); + }, [navigate]); const openSession = useCallback( (workspacePath: string, sessionId: string) => { @@ -125,9 +126,9 @@ export const useWorkspaces = () => { navigate('/'); }, [navigate]); - const toggleWorkspaceStar = useCallback(async (workspacePath: string) => { + const toggleWorkspaceStar = useCallback(async (workspaceId: string) => { try { - await updateWorkspaceStar(workspacePath); + await updateWorkspaceStar(workspaceId); await refreshWorkspaces(); } catch (error) { console.error('Failed to update workspace star:', error); @@ -149,10 +150,17 @@ export const useWorkspaces = () => { return; } + const editingWorkspace = workspaces.find( + (workspace) => workspace.workspaceOriginalPath === editingWorkspacePath, + ); + if (!editingWorkspace) { + return; + } + setIsSavingWorkspaceName(true); try { const trimmedName = editingWorkspaceName.trim(); - await updateWorkspaceCustomName(editingWorkspacePath, trimmedName || null); + await updateWorkspaceCustomName(editingWorkspace.workspaceId, trimmedName || null); await refreshWorkspaces(); cancelWorkspaceRename(); } catch (error) { @@ -165,10 +173,12 @@ export const useWorkspaces = () => { editingWorkspaceName, editingWorkspacePath, refreshWorkspaces, + workspaces, ]); const requestWorkspaceDelete = useCallback((workspace: WorkspaceRecord) => { setWorkspaceDeleteTarget({ + workspaceId: workspace.workspaceId, workspacePath: workspace.workspaceOriginalPath, workspaceName: getWorkspaceDisplayName(workspace), sessionCount: workspace.sessions.length, @@ -184,10 +194,11 @@ export const useWorkspaces = () => { return; } + const deletingWorkspaceId = workspaceDeleteTarget.workspaceId; const deletingWorkspacePath = workspaceDeleteTarget.workspacePath; setWorkspaceDeleteTarget(null); try { - await deleteWorkspaceByPath(deletingWorkspacePath); + await deleteWorkspaceById(deletingWorkspaceId); // If the current session belonged to the deleted workspace, reset to root. const hadSelectedSession = workspaces.some( diff --git a/src/components/refactored/sidebar/types/index.ts b/src/components/refactored/sidebar/types/index.ts index 835d2917..be23a0f4 100644 --- a/src/components/refactored/sidebar/types/index.ts +++ b/src/components/refactored/sidebar/types/index.ts @@ -15,6 +15,7 @@ export type WorkspaceSession = { }; export type WorkspaceRecord = { + workspaceId: string; workspaceOriginalPath: string; workspaceCustomName: string | null; workspaceDisplayName: string; @@ -24,6 +25,7 @@ export type WorkspaceRecord = { }; export type WorkspaceDeleteTarget = { + workspaceId: string; workspacePath: string; workspaceName: string; sessionCount: number; diff --git a/src/components/refactored/sidebar/view/SidebarWorkspaceItem.tsx b/src/components/refactored/sidebar/view/SidebarWorkspaceItem.tsx index 88c19e68..7ceea31d 100644 --- a/src/components/refactored/sidebar/view/SidebarWorkspaceItem.tsx +++ b/src/components/refactored/sidebar/view/SidebarWorkspaceItem.tsx @@ -29,8 +29,8 @@ type SidebarWorkspaceItemProps = { isSavingSessionName: boolean; onEditingWorkspaceNameChange: (name: string) => void; onEditingSessionNameChange: (name: string) => void; - onToggleWorkspace: (workspacePath: string) => void; - onToggleWorkspaceStar: (workspacePath: string) => void; + onToggleWorkspace: (workspaceId: string, workspacePath: string) => void; + onToggleWorkspaceStar: (workspaceId: string) => void; onStartWorkspaceRename: (workspace: WorkspaceRecord) => void; onCancelWorkspaceRename: () => void; onSaveWorkspaceRename: () => void; @@ -95,7 +95,7 @@ export function SidebarWorkspaceItem({ !hasSelectedSession && 'border-yellow-200/30 bg-yellow-50/50 dark:border-yellow-800/30 dark:bg-yellow-900/5', )} - onClick={() => onToggleWorkspace(workspace.workspaceOriginalPath)} + onClick={() => onToggleWorkspace(workspace.workspaceId, workspace.workspaceOriginalPath)} >
@@ -179,7 +179,7 @@ export function SidebarWorkspaceItem({ )} onClick={(event) => { event.stopPropagation(); - onToggleWorkspaceStar(workspace.workspaceOriginalPath); + onToggleWorkspaceStar(workspace.workspaceId); }} title={workspace.isStarred ? 'Remove from Starred' : 'Add to Starred'} > @@ -236,7 +236,7 @@ export function SidebarWorkspaceItem({ !hasSelectedSession && 'bg-yellow-50/50 hover:bg-yellow-100/50 dark:bg-yellow-900/10 dark:hover:bg-yellow-900/20', )} - onClick={() => onToggleWorkspace(workspace.workspaceOriginalPath)} + onClick={() => onToggleWorkspace(workspace.workspaceId, workspace.workspaceOriginalPath)} >
{isExpanded ? ( @@ -318,7 +318,7 @@ export function SidebarWorkspaceItem({ )} onClick={(event) => { event.stopPropagation(); - onToggleWorkspaceStar(workspace.workspaceOriginalPath); + onToggleWorkspaceStar(workspace.workspaceId); }} title={workspace.isStarred ? 'Remove from Starred' : 'Add to Starred'} > diff --git a/src/components/refactored/sidebar/view/SidebarWorkspaceList.tsx b/src/components/refactored/sidebar/view/SidebarWorkspaceList.tsx index 35099b83..030a52bd 100644 --- a/src/components/refactored/sidebar/view/SidebarWorkspaceList.tsx +++ b/src/components/refactored/sidebar/view/SidebarWorkspaceList.tsx @@ -16,8 +16,8 @@ type SidebarWorkspaceListProps = { isSavingSessionName: boolean; onEditingWorkspaceNameChange: (name: string) => void; onEditingSessionNameChange: (name: string) => void; - onToggleWorkspace: (workspacePath: string) => void; - onToggleWorkspaceStar: (workspacePath: string) => void; + onToggleWorkspace: (workspaceId: string, workspacePath: string) => void; + onToggleWorkspaceStar: (workspaceId: string) => void; onStartWorkspaceRename: (workspace: WorkspaceRecord) => void; onCancelWorkspaceRename: () => void; onSaveWorkspaceRename: () => void;