mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-29 16:12:53 +08:00
fix: remove the hide cursor on windows logic
This commit is contained in:
@@ -1,18 +1,7 @@
|
|||||||
import os from 'node:os';
|
|
||||||
|
|
||||||
import { providerRegistry } from '@/modules/providers/provider.registry.js';
|
import { providerRegistry } from '@/modules/providers/provider.registry.js';
|
||||||
import type { LLMProvider, McpScope, ProviderMcpServer, UpsertProviderMcpServerInput } from '@/shared/types.js';
|
import type { LLMProvider, McpScope, ProviderMcpServer, UpsertProviderMcpServerInput } from '@/shared/types.js';
|
||||||
import { AppError } from '@/shared/utils.js';
|
import { AppError } from '@/shared/utils.js';
|
||||||
|
|
||||||
/** Cursor MCP is not supported on Windows hosts (no Cursor CLI integration). */
|
|
||||||
function includeProviderInGlobalMcp(providerId: LLMProvider): boolean {
|
|
||||||
if (providerId === 'cursor' && os.platform() === 'win32') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const providerMcpService = {
|
export const providerMcpService = {
|
||||||
/**
|
/**
|
||||||
@@ -75,7 +64,7 @@ export const providerMcpService = {
|
|||||||
|
|
||||||
const scope = input.scope ?? 'project';
|
const scope = input.scope ?? 'project';
|
||||||
const results: Array<{ provider: LLMProvider; created: boolean; error?: string }> = [];
|
const results: Array<{ provider: LLMProvider; created: boolean; error?: string }> = [];
|
||||||
const providers = providerRegistry.listProviders().filter((p) => includeProviderInGlobalMcp(p.id));
|
const providers = providerRegistry.listProviders();
|
||||||
for (const provider of providers) {
|
for (const provider of providers) {
|
||||||
try {
|
try {
|
||||||
await provider.mcp.upsertServer({ ...input, scope });
|
await provider.mcp.upsertServer({ ...input, scope });
|
||||||
|
|||||||
@@ -341,8 +341,7 @@ test('providerMcpService global adder writes to all providers and rejects unsupp
|
|||||||
workspacePath,
|
workspacePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
const expectCursorGlobal = process.platform !== 'win32';
|
assert.equal(globalResult.length, 5);
|
||||||
assert.equal(globalResult.length, expectCursorGlobal ? 5 : 4);
|
|
||||||
assert.ok(globalResult.every((entry) => entry.created === true));
|
assert.ok(globalResult.every((entry) => entry.created === true));
|
||||||
|
|
||||||
const claudeProject = await readJson(path.join(workspacePath, '.mcp.json'));
|
const claudeProject = await readJson(path.join(workspacePath, '.mcp.json'));
|
||||||
@@ -357,10 +356,8 @@ test('providerMcpService global adder writes to all providers and rejects unsupp
|
|||||||
const opencodeProject = await readJson(path.join(workspacePath, 'opencode.json'));
|
const opencodeProject = await readJson(path.join(workspacePath, 'opencode.json'));
|
||||||
assert.ok((opencodeProject.mcp as Record<string, unknown>)['global-http']);
|
assert.ok((opencodeProject.mcp as Record<string, unknown>)['global-http']);
|
||||||
|
|
||||||
if (expectCursorGlobal) {
|
const cursorProject = await readJson(path.join(workspacePath, '.cursor', 'mcp.json'));
|
||||||
const cursorProject = await readJson(path.join(workspacePath, '.cursor', 'mcp.json'));
|
assert.ok((cursorProject.mcpServers as Record<string, unknown>)['global-http']);
|
||||||
assert.ok((cursorProject.mcpServers as Record<string, unknown>)['global-http']);
|
|
||||||
}
|
|
||||||
|
|
||||||
await assert.rejects(
|
await assert.rejects(
|
||||||
providerMcpService.addMcpServerToAllProviders({
|
providerMcpService.addMcpServerToAllProviders({
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
|
||||||
import { apiKeysDb, credentialsDb, notificationPreferencesDb, pushSubscriptionsDb } from '../modules/database/index.js';
|
import { apiKeysDb, credentialsDb, notificationPreferencesDb, pushSubscriptionsDb } from '../modules/database/index.js';
|
||||||
import { getPublicKey } from '../services/vapid-keys.js';
|
import { getPublicKey } from '../services/vapid-keys.js';
|
||||||
import { createNotificationEvent, notifyUserIfEnabled } from '../services/notification-orchestrator.js';
|
import { createNotificationEvent, notifyUserIfEnabled } from '../services/notification-orchestrator.js';
|
||||||
@@ -273,14 +274,4 @@ router.post('/push/unsubscribe', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Host OS for UI (e.g. hide Cursor agent when the backend runs on Windows).
|
|
||||||
router.get('/server-env', async (req, res) => {
|
|
||||||
try {
|
|
||||||
res.json({ platform: process.platform });
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error reading server environment:', error);
|
|
||||||
res.status(500).json({ error: 'Failed to read server environment' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
import React, { useCallback, useMemo, useState } from "react";
|
||||||
import { Check, ChevronDown } from "lucide-react";
|
import { Check, ChevronDown } from "lucide-react";
|
||||||
import { Trans, useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { useServerPlatform } from "../../../../hooks/useServerPlatform";
|
|
||||||
import type {
|
import type {
|
||||||
ProjectSession,
|
ProjectSession,
|
||||||
LLMProvider,
|
LLMProvider,
|
||||||
@@ -120,24 +119,15 @@ export default function ProviderSelectionEmptyState({
|
|||||||
setInput,
|
setInput,
|
||||||
}: ProviderSelectionEmptyStateProps) {
|
}: ProviderSelectionEmptyStateProps) {
|
||||||
const { t } = useTranslation("chat");
|
const { t } = useTranslation("chat");
|
||||||
const { isWindowsServer } = useServerPlatform();
|
|
||||||
const [dialogOpen, setDialogOpen] = useState(false);
|
const [dialogOpen, setDialogOpen] = useState(false);
|
||||||
|
|
||||||
const visibleProviderGroups = useMemo(() => {
|
const visibleProviderGroups = useMemo<ProviderGroup[]>(() => {
|
||||||
const groups: ProviderGroup[] = PROVIDER_META.map((p) => ({
|
return PROVIDER_META.map((p) => ({
|
||||||
id: p.id,
|
id: p.id,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
models: providerModelCatalog[p.id]?.OPTIONS ?? [],
|
models: providerModelCatalog[p.id]?.OPTIONS ?? [],
|
||||||
}));
|
}));
|
||||||
return isWindowsServer ? groups.filter((p) => p.id !== "cursor") : groups;
|
}, [providerModelCatalog]);
|
||||||
}, [isWindowsServer, providerModelCatalog]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isWindowsServer && provider === "cursor") {
|
|
||||||
setProvider("claude");
|
|
||||||
localStorage.setItem("selected-provider", "claude");
|
|
||||||
}
|
|
||||||
}, [isWindowsServer, provider, setProvider]);
|
|
||||||
|
|
||||||
const nextTaskPrompt = t("tasks.nextTaskPrompt", {
|
const nextTaskPrompt = t("tasks.nextTaskPrompt", {
|
||||||
defaultValue: "Start the next task",
|
defaultValue: "Start the next task",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { useServerPlatform } from '../../../../../hooks/useServerPlatform';
|
|
||||||
import type { AgentCategory, AgentProvider } from '../../../types/types';
|
import type { AgentCategory, AgentProvider } from '../../../types/types';
|
||||||
|
|
||||||
import type { AgentContext, AgentsSettingsTabProps } from './types';
|
import type { AgentContext, AgentsSettingsTabProps } from './types';
|
||||||
@@ -23,22 +22,10 @@ export default function AgentsSettingsTab({
|
|||||||
}: AgentsSettingsTabProps) {
|
}: AgentsSettingsTabProps) {
|
||||||
const [selectedAgent, setSelectedAgent] = useState<AgentProvider>('claude');
|
const [selectedAgent, setSelectedAgent] = useState<AgentProvider>('claude');
|
||||||
const [selectedCategory, setSelectedCategory] = useState<AgentCategory>('account');
|
const [selectedCategory, setSelectedCategory] = useState<AgentCategory>('account');
|
||||||
const { isWindowsServer } = useServerPlatform();
|
|
||||||
|
|
||||||
const visibleAgents = useMemo<AgentProvider[]>(() => {
|
const visibleAgents = useMemo<AgentProvider[]>(() => {
|
||||||
const all: AgentProvider[] = ['claude', 'cursor', 'codex', 'gemini', 'opencode'];
|
return ['claude', 'cursor', 'codex', 'gemini', 'opencode'];
|
||||||
if (isWindowsServer) {
|
}, []);
|
||||||
return all.filter((id) => id !== 'cursor');
|
|
||||||
}
|
|
||||||
|
|
||||||
return all;
|
|
||||||
}, [isWindowsServer]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isWindowsServer && selectedAgent === 'cursor') {
|
|
||||||
setSelectedAgent('claude');
|
|
||||||
}
|
|
||||||
}, [isWindowsServer, selectedAgent]);
|
|
||||||
|
|
||||||
const agentContextById = useMemo<Record<AgentProvider, AgentContext>>(() => ({
|
const agentContextById = useMemo<Record<AgentProvider, AgentContext>>(() => ({
|
||||||
claude: {
|
claude: {
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
import { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
import { authenticatedFetch } from '../utils/api';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Node `process.platform` from the API host (e.g. win32, darwin, linux).
|
|
||||||
* Null until loaded or if the request fails.
|
|
||||||
*/
|
|
||||||
export function useServerPlatform(): {
|
|
||||||
serverPlatform: string | null;
|
|
||||||
isWindowsServer: boolean;
|
|
||||||
} {
|
|
||||||
const [serverPlatform, setServerPlatform] = useState<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let cancelled = false;
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
const response = await authenticatedFetch('/api/settings/server-env');
|
|
||||||
if (!response.ok) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const body = (await response.json()) as { platform?: string };
|
|
||||||
if (!cancelled && typeof body.platform === 'string') {
|
|
||||||
setServerPlatform(body.platform);
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Keep null: treat as unknown host.
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
return () => {
|
|
||||||
cancelled = true;
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return {
|
|
||||||
serverPlatform,
|
|
||||||
isWindowsServer: serverPlatform === 'win32',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user