feat: remove legacy OpenCode runtime
Cut product flows over to Coding/Pi and retain only the migration-owned v1 boundary. Promote supported native optional packages because electron-builder omitted pnpm transitive optional closure from the packaged ASAR.
This commit is contained in:
@@ -9,7 +9,7 @@ import { Sidebar } from './Sidebar';
|
||||
import { TitleBar } from './TitleBar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { getAiModuleForPath } from '@/lib/ai-modules';
|
||||
import { useOpencodeStore } from '@/stores/opencode';
|
||||
import { useCodingWorkspaceStore } from '@/stores/coding-workspace';
|
||||
import { useProjectConfigStore } from '@/stores/project-config';
|
||||
import { useSettingsStore } from '@/stores/settings';
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -18,7 +18,7 @@ import type { SidebarPeekSource } from './sidebar-peek';
|
||||
const SIDEBAR_PEEK_CLOSE_DELAY_MS = 180;
|
||||
|
||||
export function MainLayout() {
|
||||
const activeProject = useOpencodeStore((state) => state.activeProject);
|
||||
const activeProject = useCodingWorkspaceStore((state) => state.activeProject);
|
||||
const sidebarCollapsed = useSettingsStore((state) => state.sidebarCollapsed);
|
||||
const config = useProjectConfigStore((state) => activeProject ? state.configsByProjectId[activeProject.id] : undefined);
|
||||
const load = useProjectConfigStore((state) => state.load);
|
||||
@@ -36,7 +36,7 @@ export function MainLayout() {
|
||||
const isProgrammingModule = activeModule === 'programming';
|
||||
const isPaintingModule = activeModule === 'painting';
|
||||
const isPromptMuseum = location.pathname === '/image-prompts' || location.pathname.startsWith('/image-prompts/');
|
||||
const isChatWorkspace = location.pathname === '/opencode-chat';
|
||||
const isChatWorkspace = location.pathname === '/chat';
|
||||
const isInitializationSafeRoute = location.pathname === '/project-config' || !isProgrammingModule;
|
||||
|
||||
const handleSidebarPeekChange = useCallback((open: boolean, source: SidebarPeekSource) => {
|
||||
|
||||
@@ -46,9 +46,9 @@ import { getAccountInitial } from '@/components/profile/user-avatar-utils';
|
||||
import { UserProfileDialog } from '@/components/profile/UserProfileDialog';
|
||||
import { useSettingsStore } from '@/stores/settings';
|
||||
import { useAuthStore, type AuthUser } from '@/stores/auth';
|
||||
import { useOpencodeStore, type ProjectDirectoryMode } from '@/stores/opencode';
|
||||
import { useCodingWorkspaceStore } from '@/stores/coding-workspace';
|
||||
import { useProviderStore } from '@/stores/providers';
|
||||
import type { OpencodeProject } from '@/types/opencode';
|
||||
import type { CodingProjectSummary } from '@/types/coding-project';
|
||||
import { useProjectConfigStore } from '@/stores/project-config';
|
||||
import type { ProjectType } from '../../../shared/project-config';
|
||||
import { toast } from 'sonner';
|
||||
@@ -65,10 +65,12 @@ type TokenUsageState = {
|
||||
};
|
||||
|
||||
type ProjectEntryError = {
|
||||
project: OpencodeProject;
|
||||
project: CodingProjectSummary;
|
||||
message: string;
|
||||
};
|
||||
|
||||
type ProjectDirectoryMode = 'use-selected-directory' | 'create-child-directory';
|
||||
|
||||
function getFolderName(pathValue: string): string {
|
||||
const trimmed = pathValue.trim();
|
||||
const withoutTrailingSeparators = trimmed.replace(/[\\/]+$/u, '');
|
||||
@@ -133,13 +135,12 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
|
||||
const { t } = useTranslation('common');
|
||||
const sidebarPinnedCollapsed = useSettingsStore((state) => state.sidebarCollapsed);
|
||||
const sidebarCollapsed = sidebarPinnedCollapsed && !sidebarPeekOpen;
|
||||
const opencodeProjects = useOpencodeStore((state) => state.projects);
|
||||
const activeProject = useOpencodeStore((state) => state.activeProject);
|
||||
const loadProjectList = useOpencodeStore((state) => state.loadProjectList);
|
||||
const activateProjectLocally = useOpencodeStore((state) => state.activateProjectLocally);
|
||||
const setActiveProject = useOpencodeStore((state) => state.setActiveProject);
|
||||
const removeProject = useOpencodeStore((state) => state.removeProject);
|
||||
const createProject = useOpencodeStore((state) => state.createProject);
|
||||
const projects = useCodingWorkspaceStore((state) => state.projects);
|
||||
const activeProject = useCodingWorkspaceStore((state) => state.activeProject);
|
||||
const loadProjectList = useCodingWorkspaceStore((state) => state.load);
|
||||
const setActiveProject = useCodingWorkspaceStore((state) => state.setActiveProject);
|
||||
const removeProject = useCodingWorkspaceStore((state) => state.removeProject);
|
||||
const createProject = useCodingWorkspaceStore((state) => state.createProject);
|
||||
const projectConfigs = useProjectConfigStore((state) => state.configsByProjectId);
|
||||
const loadProjectConfig = useProjectConfigStore((state) => state.load);
|
||||
const removeProjectConfig = useProjectConfigStore((state) => state.remove);
|
||||
@@ -166,7 +167,7 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
|
||||
const [createProjectError, setCreateProjectError] = useState<string | null>(null);
|
||||
const [creatingProject, setCreatingProject] = useState(false);
|
||||
const [projectEntryError, setProjectEntryError] = useState<ProjectEntryError | null>(null);
|
||||
const [removeProjectCandidate, setRemoveProjectCandidate] = useState<OpencodeProject | null>(null);
|
||||
const [removeProjectCandidate, setRemoveProjectCandidate] = useState<CodingProjectSummary | null>(null);
|
||||
const [robotOverview, setRobotOverview] = useState<AiHardwareOverview | null>(null);
|
||||
const [robotOverviewLoading, setRobotOverviewLoading] = useState(false);
|
||||
const [robotSelectedAgentId, setRobotSelectedAgentId] = useState<string | null>(() => readAiHardwareAgentId());
|
||||
@@ -182,7 +183,7 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
|
||||
const isRobotModule = activeModule === 'robot';
|
||||
const isPromptMuseum = location.pathname === '/image-prompts' || location.pathname.startsWith('/image-prompts/');
|
||||
const projectConfigPath = '/project-config';
|
||||
const visibleProjects = opencodeProjects;
|
||||
const visibleProjects = projects;
|
||||
const selectedProjectFolderName = getFolderName(newProjectSelectedPath);
|
||||
const accountName = userProfile?.displayName?.trim() || getAuthUserDisplayName(authUser) || '未登录用户';
|
||||
const accountFullName = accountName;
|
||||
@@ -416,24 +417,23 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
|
||||
setCreateProjectError(null);
|
||||
};
|
||||
|
||||
const showProjectEntryError = (project: OpencodeProject, message: string) => {
|
||||
const showProjectEntryError = (project: CodingProjectSummary, message: string) => {
|
||||
setProjectEntryError({ project, message });
|
||||
};
|
||||
|
||||
const enterProject = async (project: OpencodeProject) => {
|
||||
const enterProject = async (project: CodingProjectSummary) => {
|
||||
const result = await loadProjectConfig(project.id);
|
||||
if (result.status !== 'valid' || !result.config) {
|
||||
showProjectEntryError(project, result.status === 'missing' ? '项目缺少 .niancode/project.json' : result.error ?? '项目配置无效');
|
||||
return;
|
||||
}
|
||||
activateProjectLocally(project);
|
||||
await setActiveProject(project.id);
|
||||
navigate(result.config.initialized
|
||||
? '/opencode-chat'
|
||||
? '/chat'
|
||||
: projectConfigPath);
|
||||
void setActiveProject(project.id).catch(() => undefined);
|
||||
};
|
||||
|
||||
const readAndEnterProject = async (project: OpencodeProject) => {
|
||||
const readAndEnterProject = async (project: CodingProjectSummary) => {
|
||||
setProjectEntryError(null);
|
||||
try {
|
||||
await enterProject(project);
|
||||
@@ -459,10 +459,10 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
|
||||
setCreateProjectError(null);
|
||||
try {
|
||||
const project = await createProject({
|
||||
directoryMode: newProjectDirectoryMode,
|
||||
selectedPath,
|
||||
projectType: newProjectType,
|
||||
...(newProjectDirectoryMode === 'create-child-directory' ? { projectName } : {}),
|
||||
...(newProjectDirectoryMode === 'create-child-directory'
|
||||
? { parentPath: selectedPath, projectName }
|
||||
: { projectPath: selectedPath }),
|
||||
});
|
||||
setCreateDialogOpen(false);
|
||||
await enterProject(project);
|
||||
@@ -473,7 +473,7 @@ export function Sidebar({ workspaceLayout = false, sidebarPeekOpen = false, onSi
|
||||
}
|
||||
};
|
||||
|
||||
const openProject = async (project: OpencodeProject) => {
|
||||
const openProject = async (project: CodingProjectSummary) => {
|
||||
await readAndEnterProject(project);
|
||||
};
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import { createPortal } from 'react-dom';
|
||||
import { Copy, FolderOpen, Minus, PanelLeft, PanelLeftClose, Square, X } from 'lucide-react';
|
||||
import { invokeIpc } from '@/lib/api-client';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useCodingWorkspaceStore } from '@/stores/coding-workspace';
|
||||
import { useSettingsStore } from '@/stores/settings';
|
||||
import { useOpencodeStore } from '@/stores/opencode';
|
||||
import logoWordmarkSource from '@/assets/makelore-wordmark-source.png';
|
||||
import type { SidebarPeekSource } from './sidebar-peek';
|
||||
|
||||
@@ -61,7 +61,7 @@ function ProductTitleBar({
|
||||
onSidebarPeekChange?: SidebarPeekChange;
|
||||
}) {
|
||||
const sidebarCollapsed = useSettingsStore((state) => state.sidebarCollapsed);
|
||||
const activeProject = useOpencodeStore((state) => state.activeProject);
|
||||
const activeProject = useCodingWorkspaceStore((state) => state.activeProject);
|
||||
const toolbarButtonClass = 'no-drag motion-press flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-surface-subtle hover:text-foreground';
|
||||
const setSidebarCollapsed = useSettingsStore((state) => state.setSidebarCollapsed);
|
||||
const toggleSidebar = () => setSidebarCollapsed(!sidebarCollapsed);
|
||||
|
||||
Reference in New Issue
Block a user