Compare commits

..

7 Commits

Author SHA1 Message Date
simosmik
4f6ff9260d Release 1.20.1 2026-02-23 22:23:33 +00:00
viper151
49061bc7a3 Update DEFAULT model version to gpt-5.3-codex (#426) 2026-02-23 23:13:50 +01:00
simosmik
50e097d4ac feat: migrate legacy database to new location and improve last login update handling 2026-02-23 22:12:00 +00:00
simosmik
f986004319 feat: implement install mode detection and update commands in version upgrade process 2026-02-23 21:55:53 +00:00
simosmik
f488a346ef Release 1.19.1 2026-02-23 21:29:06 +00:00
simosmik
82efac4704 fix: add prepublishOnly script to build before publishing 2026-02-23 21:27:45 +00:00
viper151
81697d0e73 Update DEFAULT model version to gpt-5.3-codex (#417) 2026-02-23 16:51:29 +01:00
16 changed files with 91 additions and 18 deletions

View File

@@ -3,6 +3,19 @@
All notable changes to CloudCLI UI will be documented in this file. All notable changes to CloudCLI UI will be documented in this file.
## [1.20.1](https://github.com/siteboon/claudecodeui/compare/v1.19.1...v1.20.1) (2026-02-23)
### New Features
* implement install mode detection and update commands in version upgrade process ([f986004](https://github.com/siteboon/claudecodeui/commit/f986004319207b068431f9f6adf338a8ce8decfc))
* migrate legacy database to new location and improve last login update handling ([50e097d](https://github.com/siteboon/claudecodeui/commit/50e097d4ac498aa9f1803ef3564843721833dc19))
## [1.19.1](https://github.com/siteboon/claudecodeui/compare/v1.19.0...v1.19.1) (2026-02-23)
### Bug Fixes
* add prepublishOnly script to build before publishing ([82efac4](https://github.com/siteboon/claudecodeui/commit/82efac4704cab11ed8d1a05fe84f41312140b223))
## [1.19.0](https://github.com/siteboon/claudecodeui/compare/v1.18.2...v1.19.0) (2026-02-23) ## [1.19.0](https://github.com/siteboon/claudecodeui/compare/v1.18.2...v1.19.0) (2026-02-23)
### New Features ### New Features

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@siteboon/claude-code-ui", "name": "@siteboon/claude-code-ui",
"version": "1.19.0", "version": "1.20.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@siteboon/claude-code-ui", "name": "@siteboon/claude-code-ui",
"version": "1.19.0", "version": "1.20.1",
"hasInstallScript": true, "hasInstallScript": true,
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@siteboon/claude-code-ui", "name": "@siteboon/claude-code-ui",
"version": "1.19.0", "version": "1.20.1",
"description": "A web-based UI for Claude Code CLI", "description": "A web-based UI for Claude Code CLI",
"type": "module", "type": "module",
"main": "server/index.js", "main": "server/index.js",
@@ -32,6 +32,7 @@
"typecheck": "tsc --noEmit -p tsconfig.json", "typecheck": "tsc --noEmit -p tsconfig.json",
"start": "npm run build && npm run server", "start": "npm run build && npm run server",
"release": "./release.sh", "release": "./release.sh",
"prepublishOnly": "npm run build",
"postinstall": "node scripts/fix-node-pty.js" "postinstall": "node scripts/fix-node-pty.js"
}, },
"keywords": [ "keywords": [

View File

@@ -40,6 +40,22 @@ if (process.env.DATABASE_PATH) {
} }
} }
// As part of 1.19.2 we are introducing a new location for auth.db. The below handles exisitng moving legacy database from install directory to new location
const LEGACY_DB_PATH = path.join(__dirname, 'auth.db');
if (DB_PATH !== LEGACY_DB_PATH && !fs.existsSync(DB_PATH) && fs.existsSync(LEGACY_DB_PATH)) {
try {
fs.copyFileSync(LEGACY_DB_PATH, DB_PATH);
console.log(`[MIGRATION] Copied database from ${LEGACY_DB_PATH} to ${DB_PATH}`);
for (const suffix of ['-wal', '-shm']) {
if (fs.existsSync(LEGACY_DB_PATH + suffix)) {
fs.copyFileSync(LEGACY_DB_PATH + suffix, DB_PATH + suffix);
}
}
} catch (err) {
console.warn(`[MIGRATION] Could not copy legacy database: ${err.message}`);
}
}
// Create database connection // Create database connection
const db = new Database(DB_PATH); const db = new Database(DB_PATH);
@@ -128,12 +144,12 @@ const userDb = {
} }
}, },
// Update last login time // Update last login time (non-fatal — logged but not thrown)
updateLastLogin: (userId) => { updateLastLogin: (userId) => {
try { try {
db.prepare('UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?').run(userId); db.prepare('UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?').run(userId);
} catch (err) { } catch (err) {
throw err; console.warn('Failed to update last login:', err.message);
} }
}, },

View File

@@ -9,6 +9,8 @@ import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename); const __dirname = dirname(__filename);
const installMode = fs.existsSync(path.join(__dirname, '..', '.git')) ? 'git' : 'npm';
// ANSI color codes for terminal output // ANSI color codes for terminal output
const colors = { const colors = {
reset: '\x1b[0m', reset: '\x1b[0m',
@@ -333,7 +335,8 @@ app.use(express.urlencoded({ limit: '50mb', extended: true }));
app.get('/health', (req, res) => { app.get('/health', (req, res) => {
res.json({ res.json({
status: 'ok', status: 'ok',
timestamp: new Date().toISOString() timestamp: new Date().toISOString(),
installMode
}); });
}); });
@@ -410,11 +413,13 @@ app.post('/api/system/update', authenticateToken, async (req, res) => {
console.log('Starting system update from directory:', projectRoot); console.log('Starting system update from directory:', projectRoot);
// Run the update command // Run the update command based on install mode
const updateCommand = 'git checkout main && git pull && npm install'; const updateCommand = installMode === 'git'
? 'git checkout main && git pull && npm install'
: 'npm install -g @siteboon/claude-code-ui@latest';
const child = spawn('sh', ['-c', updateCommand], { const child = spawn('sh', ['-c', updateCommand], {
cwd: projectRoot, cwd: installMode === 'git' ? projectRoot : os.homedir(),
env: process.env env: process.env
}); });

View File

@@ -1,5 +1,6 @@
// Load environment variables from .env before other imports execute. // Load environment variables from .env before other imports execute.
import fs from 'fs'; import fs from 'fs';
import os from 'os';
import path from 'path'; import path from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import { dirname } from 'path'; import { dirname } from 'path';
@@ -22,3 +23,7 @@ try {
} catch (e) { } catch (e) {
console.log('No .env file found or error reading it:', e.message); console.log('No .env file found or error reading it:', e.message);
} }
if (!process.env.DATABASE_PATH) {
process.env.DATABASE_PATH = path.join(os.homedir(), '.cloudcli', 'auth.db');
}

View File

@@ -53,11 +53,11 @@ router.post('/register', async (req, res) => {
// Generate token // Generate token
const token = generateToken(user); const token = generateToken(user);
// Update last login db.prepare('COMMIT').run();
// Update last login (non-fatal, outside transaction)
userDb.updateLastLogin(user.id); userDb.updateLastLogin(user.id);
db.prepare('COMMIT').run();
res.json({ res.json({
success: true, success: true,
user: { id: user.id, username: user.username }, user: { id: user.id, username: user.username },

View File

@@ -63,5 +63,5 @@ export const CODEX_MODELS = {
{ value: 'o4-mini', label: 'O4-mini' } { value: 'o4-mini', label: 'O4-mini' }
], ],
DEFAULT: 'gpt-5.2' DEFAULT: 'gpt-5.3-codex'
}; };

View File

@@ -2,6 +2,7 @@ import { useCallback, 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";
import type { InstallMode } from "../../hooks/useVersionCheck";
interface VersionUpgradeModalProps { interface VersionUpgradeModalProps {
isOpen: boolean; isOpen: boolean;
@@ -9,6 +10,7 @@ interface VersionUpgradeModalProps {
releaseInfo: ReleaseInfo | null; releaseInfo: ReleaseInfo | null;
currentVersion: string; currentVersion: string;
latestVersion: string | null; latestVersion: string | null;
installMode: InstallMode;
} }
export default function VersionUpgradeModal({ export default function VersionUpgradeModal({
@@ -16,9 +18,13 @@ export default function VersionUpgradeModal({
onClose, onClose,
releaseInfo, releaseInfo,
currentVersion, currentVersion,
latestVersion latestVersion,
installMode
}: VersionUpgradeModalProps) { }: VersionUpgradeModalProps) {
const { t } = useTranslation('common'); const { t } = useTranslation('common');
const upgradeCommand = installMode === 'npm'
? t('versionUpdate.npmUpgradeCommand')
: 'git checkout main && git pull && npm install';
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('');
@@ -150,7 +156,7 @@ export default function VersionUpgradeModal({
<h3 className="text-sm font-medium text-gray-900 dark:text-white">{t('versionUpdate.manualUpgrade')}</h3> <h3 className="text-sm font-medium text-gray-900 dark:text-white">{t('versionUpdate.manualUpgrade')}</h3>
<div className="bg-gray-100 dark:bg-gray-800 rounded-lg p-3 border"> <div className="bg-gray-100 dark:bg-gray-800 rounded-lg p-3 border">
<code className="text-sm text-gray-800 dark:text-gray-200 font-mono"> <code className="text-sm text-gray-800 dark:text-gray-200 font-mono">
git checkout main && git pull && npm install {upgradeCommand}
</code> </code>
</div> </div>
<p className="text-xs text-gray-600 dark:text-gray-400"> <p className="text-xs text-gray-600 dark:text-gray-400">
@@ -171,7 +177,7 @@ export default function VersionUpgradeModal({
<> <>
<button <button
onClick={() => { onClick={() => {
navigator.clipboard.writeText('git checkout main && git pull && npm install'); navigator.clipboard.writeText(upgradeCommand);
}} }}
className="flex-1 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-md transition-colors" className="flex-1 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-md transition-colors"
> >

View File

@@ -38,7 +38,7 @@ function Sidebar({
}: SidebarProps) { }: SidebarProps) {
const { t } = useTranslation(['sidebar', 'common']); const { t } = useTranslation(['sidebar', 'common']);
const { isPWA } = useDeviceSettings({ trackMobile: false }); const { isPWA } = useDeviceSettings({ trackMobile: false });
const { updateAvailable, latestVersion, currentVersion, releaseInfo } = useVersionCheck( const { updateAvailable, latestVersion, currentVersion, releaseInfo, installMode } = useVersionCheck(
'siteboon', 'siteboon',
'claudecodeui', 'claudecodeui',
); );
@@ -200,6 +200,7 @@ function Sidebar({
releaseInfo={releaseInfo} releaseInfo={releaseInfo}
currentVersion={currentVersion} currentVersion={currentVersion}
latestVersion={latestVersion} latestVersion={latestVersion}
installMode={installMode}
t={t} t={t}
/> />

View File

@@ -8,6 +8,7 @@ import Settings from '../../../Settings';
import VersionUpgradeModal from '../../../modals/VersionUpgradeModal'; import VersionUpgradeModal from '../../../modals/VersionUpgradeModal';
import type { Project } from '../../../../types/app'; import type { Project } from '../../../../types/app';
import type { ReleaseInfo } from '../../../../types/sharedTypes'; import type { ReleaseInfo } from '../../../../types/sharedTypes';
import type { InstallMode } from '../../../../hooks/useVersionCheck';
import { normalizeProjectForSettings } from '../../utils/utils'; import { normalizeProjectForSettings } from '../../utils/utils';
import type { DeleteProjectConfirmation, SessionDeleteConfirmation, SettingsProject } from '../../types/types'; import type { DeleteProjectConfirmation, SessionDeleteConfirmation, SettingsProject } from '../../types/types';
@@ -30,6 +31,7 @@ type SidebarModalsProps = {
releaseInfo: ReleaseInfo | null; releaseInfo: ReleaseInfo | null;
currentVersion: string; currentVersion: string;
latestVersion: string | null; latestVersion: string | null;
installMode: InstallMode;
t: TFunction; t: TFunction;
}; };
@@ -65,6 +67,7 @@ export default function SidebarModals({
releaseInfo, releaseInfo,
currentVersion, currentVersion,
latestVersion, latestVersion,
installMode,
t, t,
}: SidebarModalsProps) { }: SidebarModalsProps) {
// Settings expects project identity/path fields to be present for dropdown labels and local-scope MCP config. // Settings expects project identity/path fields to be present for dropdown labels and local-scope MCP config.
@@ -199,6 +202,7 @@ export default function SidebarModals({
releaseInfo={releaseInfo} releaseInfo={releaseInfo}
currentVersion={currentVersion} currentVersion={currentVersion}
latestVersion={latestVersion} latestVersion={latestVersion}
installMode={installMode}
/> />
</> </>
); );

View File

@@ -21,10 +21,28 @@ const compareVersions = (v1: string, v2: string) => {
return 0; return 0;
}; };
export type InstallMode = 'git' | 'npm';
export const useVersionCheck = (owner: string, repo: string) => { export const useVersionCheck = (owner: string, repo: string) => {
const [updateAvailable, setUpdateAvailable] = useState(false); const [updateAvailable, setUpdateAvailable] = useState(false);
const [latestVersion, setLatestVersion] = useState<string | null>(null); const [latestVersion, setLatestVersion] = useState<string | null>(null);
const [releaseInfo, setReleaseInfo] = useState<ReleaseInfo | null>(null); const [releaseInfo, setReleaseInfo] = useState<ReleaseInfo | null>(null);
const [installMode, setInstallMode] = useState<InstallMode>('git');
useEffect(() => {
const fetchInstallMode = async () => {
try {
const response = await fetch('/health');
const data = await response.json();
if (data.installMode === 'npm' || data.installMode === 'git') {
setInstallMode(data.installMode);
}
} catch {
// Default to git on error
}
};
fetchInstallMode();
}, []);
useEffect(() => { useEffect(() => {
const checkVersion = async () => { const checkVersion = async () => {
@@ -66,5 +84,5 @@ export const useVersionCheck = (owner: string, repo: string) => {
return () => clearInterval(interval); return () => clearInterval(interval);
}, [owner, repo]); }, [owner, repo]);
return { updateAvailable, latestVersion, currentVersion: version, releaseInfo }; return { updateAvailable, latestVersion, currentVersion: version, releaseInfo, installMode };
}; };

View File

@@ -200,6 +200,7 @@
"viewFullRelease": "View full release", "viewFullRelease": "View full release",
"updateProgress": "Update Progress:", "updateProgress": "Update Progress:",
"manualUpgrade": "Manual upgrade:", "manualUpgrade": "Manual upgrade:",
"npmUpgradeCommand": "npm install -g @siteboon/claude-code-ui@latest",
"manualUpgradeHint": "Or click \"Update Now\" to run the update automatically.", "manualUpgradeHint": "Or click \"Update Now\" to run the update automatically.",
"updateCompleted": "Update completed successfully!", "updateCompleted": "Update completed successfully!",
"restartServer": "Please restart the server to apply changes.", "restartServer": "Please restart the server to apply changes.",

View File

@@ -200,6 +200,7 @@
"viewFullRelease": "リリース全文を見る", "viewFullRelease": "リリース全文を見る",
"updateProgress": "アップデートの進捗:", "updateProgress": "アップデートの進捗:",
"manualUpgrade": "手動アップグレード:", "manualUpgrade": "手動アップグレード:",
"npmUpgradeCommand": "npm install -g @siteboon/claude-code-ui@latest",
"manualUpgradeHint": "または「今すぐ更新」をクリックして自動的にアップデートを実行できます。", "manualUpgradeHint": "または「今すぐ更新」をクリックして自動的にアップデートを実行できます。",
"updateCompleted": "アップデートが完了しました!", "updateCompleted": "アップデートが完了しました!",
"restartServer": "変更を適用するにはサーバーを再起動してください。", "restartServer": "変更を適用するにはサーバーを再起動してください。",

View File

@@ -200,6 +200,7 @@
"viewFullRelease": "전체 릴리스 보기", "viewFullRelease": "전체 릴리스 보기",
"updateProgress": "업데이트 진행 상황:", "updateProgress": "업데이트 진행 상황:",
"manualUpgrade": "수동 업그레이드:", "manualUpgrade": "수동 업그레이드:",
"npmUpgradeCommand": "npm install -g @siteboon/claude-code-ui@latest",
"manualUpgradeHint": "또는 \"지금 업데이트\"를 클릭하여 자동으로 업데이트합니다.", "manualUpgradeHint": "또는 \"지금 업데이트\"를 클릭하여 자동으로 업데이트합니다.",
"updateCompleted": "업데이트가 완료되었습니다!", "updateCompleted": "업데이트가 완료되었습니다!",
"restartServer": "변경사항을 적용하려면 서버를 재시작하세요.", "restartServer": "변경사항을 적용하려면 서버를 재시작하세요.",

View File

@@ -200,6 +200,7 @@
"viewFullRelease": "查看完整发布", "viewFullRelease": "查看完整发布",
"updateProgress": "更新进度:", "updateProgress": "更新进度:",
"manualUpgrade": "手动升级:", "manualUpgrade": "手动升级:",
"npmUpgradeCommand": "npm install -g @siteboon/claude-code-ui@latest",
"manualUpgradeHint": "或点击'立即更新'以自动运行更新。", "manualUpgradeHint": "或点击'立即更新'以自动运行更新。",
"updateCompleted": "更新成功完成!", "updateCompleted": "更新成功完成!",
"restartServer": "请重启服务器以应用更改。", "restartServer": "请重启服务器以应用更改。",