mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-04-17 02:51:35 +00:00
Compare commits
5 Commits
v1.29.2
...
fix/replac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c85ddc807 | ||
|
|
8ff5f35c05 | ||
|
|
641304242d | ||
|
|
3bbd56e8e9 | ||
|
|
11733918e5 |
@@ -1,12 +1,8 @@
|
|||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import crossSpawn from 'cross-spawn';
|
|
||||||
import { notifyRunFailed, notifyRunStopped } from './services/notification-orchestrator.js';
|
import { notifyRunFailed, notifyRunStopped } from './services/notification-orchestrator.js';
|
||||||
import { cursorAdapter } from './providers/cursor/adapter.js';
|
import { cursorAdapter } from './providers/cursor/adapter.js';
|
||||||
import { createNormalizedMessage } from './providers/types.js';
|
import { createNormalizedMessage } from './providers/types.js';
|
||||||
|
|
||||||
// Use cross-spawn on Windows for better command execution
|
|
||||||
const spawnFunction = process.platform === 'win32' ? crossSpawn : spawn;
|
|
||||||
|
|
||||||
let activeCursorProcesses = new Map(); // Track active processes by session ID
|
let activeCursorProcesses = new Map(); // Track active processes by session ID
|
||||||
|
|
||||||
const WORKSPACE_TRUST_PATTERNS = [
|
const WORKSPACE_TRUST_PATTERNS = [
|
||||||
@@ -122,7 +118,7 @@ async function spawnCursor(command, options = {}, ws) {
|
|||||||
console.log('Working directory:', workingDir);
|
console.log('Working directory:', workingDir);
|
||||||
console.log('Session info - Input sessionId:', sessionId, 'Resume:', resume);
|
console.log('Session info - Input sessionId:', sessionId, 'Resume:', resume);
|
||||||
|
|
||||||
const cursorProcess = spawnFunction('cursor-agent', args, {
|
const cursorProcess = spawn('cursor-agent', args, {
|
||||||
cwd: workingDir,
|
cwd: workingDir,
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
env: { ...process.env } // Inherit all environment variables
|
env: { ...process.env } // Inherit all environment variables
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import crossSpawn from 'cross-spawn';
|
|
||||||
|
|
||||||
// Use cross-spawn on Windows for correct .cmd resolution (same pattern as cursor-cli.js)
|
|
||||||
const spawnFunction = process.platform === 'win32' ? crossSpawn : spawn;
|
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
@@ -168,7 +164,7 @@ async function spawnGemini(command, options = {}, ws) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const geminiProcess = spawnFunction(spawnCmd, spawnArgs, {
|
const geminiProcess = spawn(spawnCmd, spawnArgs, {
|
||||||
cwd: workingDir,
|
cwd: workingDir,
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
env: { ...process.env } // Inherit all environment variables
|
env: { ...process.env } // Inherit all environment variables
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import os from 'os';
|
|||||||
import http from 'http';
|
import http from 'http';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { promises as fsPromises } from 'fs';
|
import { promises as fsPromises } from 'fs';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import pty from 'node-pty';
|
import pty from 'node-pty';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import mime from 'mime-types';
|
import mime from 'mime-types';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import express from 'express';
|
|||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import sqlite3 from 'sqlite3';
|
import sqlite3 from 'sqlite3';
|
||||||
import { open } from 'sqlite';
|
import { open } from 'sqlite';
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { extractProjectDirectory } from '../projects.js';
|
import { extractProjectDirectory } from '../projects.js';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import path from 'path';
|
|||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { dirname } from 'path';
|
import { dirname } from 'path';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { addProjectManually } from '../projects.js';
|
import { addProjectManually } from '../projects.js';
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import express from 'express';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { promises as fsPromises } from 'fs';
|
import { promises as fsPromises } from 'fs';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { dirname } from 'path';
|
import { dirname } from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import express from 'express';
|
|||||||
import { userDb } from '../database/db.js';
|
import { userDb } from '../database/db.js';
|
||||||
import { authenticateToken } from '../middleware/auth.js';
|
import { authenticateToken } from '../middleware/auth.js';
|
||||||
import { getSystemGitConfig } from '../utils/gitConfig.js';
|
import { getSystemGitConfig } from '../utils/gitConfig.js';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
|
|
||||||
function spawnAsync(command, args) {
|
function spawnAsync(command, args) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
|
|
||||||
const PLUGINS_DIR = path.join(os.homedir(), '.claude-code-ui', 'plugins');
|
const PLUGINS_DIR = path.join(os.homedir(), '.claude-code-ui', 'plugins');
|
||||||
const PLUGINS_CONFIG_PATH = path.join(os.homedir(), '.claude-code-ui', 'plugins.json');
|
const PLUGINS_CONFIG_PATH = path.join(os.homedir(), '.claude-code-ui', 'plugins.json');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { spawn } from 'child_process';
|
import { spawn } from 'cross-spawn';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { scanPlugins, getPluginsConfig, getPluginDir } from './plugin-loader.js';
|
import { scanPlugins, getPluginsConfig, getPluginDir } from './plugin-loader.js';
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ export const CLAUDE_MODELS = {
|
|||||||
{ value: "haiku", label: "Haiku" },
|
{ value: "haiku", label: "Haiku" },
|
||||||
{ value: "opusplan", label: "Opus Plan" },
|
{ value: "opusplan", label: "Opus Plan" },
|
||||||
{ value: "sonnet[1m]", label: "Sonnet [1M]" },
|
{ value: "sonnet[1m]", label: "Sonnet [1M]" },
|
||||||
|
{ value: "opus[1m]", label: "Opus [1M]" },
|
||||||
],
|
],
|
||||||
|
|
||||||
DEFAULT: "sonnet",
|
DEFAULT: "opus",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,6 +59,7 @@ export const CURSOR_MODELS = {
|
|||||||
export const CODEX_MODELS = {
|
export const CODEX_MODELS = {
|
||||||
OPTIONS: [
|
OPTIONS: [
|
||||||
{ value: "gpt-5.4", label: "GPT-5.4" },
|
{ value: "gpt-5.4", label: "GPT-5.4" },
|
||||||
|
{ value: "gpt-5.4-mini", label: "GPT-5.4 mini" },
|
||||||
{ value: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
|
{ value: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
|
||||||
{ value: "gpt-5.2-codex", label: "GPT-5.2 Codex" },
|
{ value: "gpt-5.2-codex", label: "GPT-5.2 Codex" },
|
||||||
{ value: "gpt-5.2", label: "GPT-5.2" },
|
{ value: "gpt-5.2", label: "GPT-5.2" },
|
||||||
@@ -88,5 +90,5 @@ export const GEMINI_MODELS = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
DEFAULT: "gemini-2.5-flash",
|
DEFAULT: "gemini-3.1-pro-preview",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { authenticatedFetch } from "../../../utils/api";
|
import { authenticatedFetch } from "../../../utils/api";
|
||||||
import { ReleaseInfo } from "../../../types/sharedTypes";
|
import { ReleaseInfo } from "../../../types/sharedTypes";
|
||||||
@@ -15,6 +15,8 @@ interface VersionUpgradeModalProps {
|
|||||||
installMode: InstallMode;
|
installMode: InstallMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RELOAD_COUNTDOWN_START = 30;
|
||||||
|
|
||||||
export function VersionUpgradeModal({
|
export function VersionUpgradeModal({
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
@@ -32,10 +34,30 @@ export function VersionUpgradeModal({
|
|||||||
const [isUpdating, setIsUpdating] = useState(false);
|
const [isUpdating, setIsUpdating] = useState(false);
|
||||||
const [updateOutput, setUpdateOutput] = useState('');
|
const [updateOutput, setUpdateOutput] = useState('');
|
||||||
const [updateError, setUpdateError] = useState('');
|
const [updateError, setUpdateError] = useState('');
|
||||||
|
const [reloadCountdown, setReloadCountdown] = useState<number | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!IS_PLATFORM || reloadCountdown === null || reloadCountdown <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeoutId = window.setTimeout(() => {
|
||||||
|
setReloadCountdown((previousCountdown) => {
|
||||||
|
if (previousCountdown === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(previousCountdown - 1, 0);
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => window.clearTimeout(timeoutId);
|
||||||
|
}, [reloadCountdown]);
|
||||||
|
|
||||||
const handleUpdateNow = useCallback(async () => {
|
const handleUpdateNow = useCallback(async () => {
|
||||||
setIsUpdating(true);
|
setIsUpdating(true);
|
||||||
setUpdateOutput('Starting update...\n');
|
setUpdateOutput('Starting update...\n');
|
||||||
|
setReloadCountdown(IS_PLATFORM ? RELOAD_COUNTDOWN_START : null);
|
||||||
setUpdateError('');
|
setUpdateError('');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -49,8 +71,7 @@ export function VersionUpgradeModal({
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setUpdateOutput(prev => prev + data.output + '\n');
|
setUpdateOutput(prev => prev + data.output + '\n');
|
||||||
setUpdateOutput(prev => prev + '\n✅ Update completed successfully!\n');
|
setUpdateOutput(prev => prev + '\n✅ Update completed successfully!\n');
|
||||||
const text = IS_PLATFORM ? 'Please refresh the page after 5 seconds to load the new version. If that doesn\'t work, RESTART the environment.' : 'Please restart the server to apply changes.';
|
setUpdateOutput(prev => prev + 'Please restart the server to apply changes.' + '\n');
|
||||||
setUpdateOutput(prev => prev + text + '\n');
|
|
||||||
} else {
|
} else {
|
||||||
setUpdateError(data.error || 'Update failed');
|
setUpdateError(data.error || 'Update failed');
|
||||||
setUpdateOutput(prev => prev + '\n❌ Update failed: ' + (data.error || 'Unknown error') + '\n');
|
setUpdateOutput(prev => prev + '\n❌ Update failed: ' + (data.error || 'Unknown error') + '\n');
|
||||||
@@ -147,6 +168,13 @@ export function VersionUpgradeModal({
|
|||||||
<div className="max-h-48 overflow-y-auto rounded-lg border border-gray-700 bg-gray-900 p-4 dark:bg-gray-950">
|
<div className="max-h-48 overflow-y-auto rounded-lg border border-gray-700 bg-gray-900 p-4 dark:bg-gray-950">
|
||||||
<pre className="whitespace-pre-wrap font-mono text-xs text-green-400">{updateOutput}</pre>
|
<pre className="whitespace-pre-wrap font-mono text-xs text-green-400">{updateOutput}</pre>
|
||||||
</div>
|
</div>
|
||||||
|
{IS_PLATFORM && reloadCountdown !== null && (
|
||||||
|
<div className="rounded-md border border-blue-200 bg-blue-50 px-3 py-2 text-xs text-blue-700 dark:border-blue-900/40 dark:bg-blue-900/20 dark:text-blue-200">
|
||||||
|
{reloadCountdown === 0
|
||||||
|
? 'Refresh the page now. If that doesn\'t work, RESTART the environment.'
|
||||||
|
: `Refresh the page in ${reloadCountdown} ${reloadCountdown === 1 ? 'second' : 'seconds'}. If that doesn\'t work, RESTART the environment.`}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{updateError && (
|
{updateError && (
|
||||||
<div className="rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700 dark:border-red-900/40 dark:bg-red-900/20 dark:text-red-200">
|
<div className="rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs text-red-700 dark:border-red-900/40 dark:bg-red-900/20 dark:text-red-200">
|
||||||
{updateError}
|
{updateError}
|
||||||
|
|||||||
Reference in New Issue
Block a user