diff --git a/package-lock.json b/package-lock.json index 58fe9d8df9..28574e9f22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix", - "version": "5.1.16-0", + "version": "5.1.17-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix", - "version": "5.1.16-0", + "version": "5.1.17-0", "hasInstallScript": true, "dependencies": { "@bugsnag/js": "^7.18.0", diff --git a/src-node/package-lock.json b/src-node/package-lock.json index c8dc2833b2..706395b31e 100644 --- a/src-node/package-lock.json +++ b/src-node/package-lock.json @@ -11,7 +11,6 @@ "license": "GNU-AGPL3.0", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.126", - "@anthropic-ai/claude-code": "^2.1.118", "@expo/sudo-prompt": "^9.3.2", "@phcode/fs": "^4.0.2", "cross-spawn": "^7.0.6", @@ -170,145 +169,6 @@ "win32" ] }, - "node_modules/@anthropic-ai/claude-code": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.1.142.tgz", - "integrity": "sha512-ErXNw9qrWaswvHkiohtW2/x0iNIzmU27pTvDraBJ55u4R7VzvZyU7U/10rBQHn7g2kndERog5dpul1IJCDNm+g==", - "hasInstallScript": true, - "license": "SEE LICENSE IN README.md", - "bin": { - "claude": "bin/claude.exe" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "@anthropic-ai/claude-code-darwin-arm64": "2.1.142", - "@anthropic-ai/claude-code-darwin-x64": "2.1.142", - "@anthropic-ai/claude-code-linux-arm64": "2.1.142", - "@anthropic-ai/claude-code-linux-arm64-musl": "2.1.142", - "@anthropic-ai/claude-code-linux-x64": "2.1.142", - "@anthropic-ai/claude-code-linux-x64-musl": "2.1.142", - "@anthropic-ai/claude-code-win32-arm64": "2.1.142", - "@anthropic-ai/claude-code-win32-x64": "2.1.142" - } - }, - "node_modules/@anthropic-ai/claude-code-darwin-arm64": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-darwin-arm64/-/claude-code-darwin-arm64-2.1.142.tgz", - "integrity": "sha512-T6GB2kbJ9eiZ2eL25lshk1lwuCkSrrwOz+7ruADfiTd6R5nqMEbB6VplMpYrj67ydt7II6ZpHdjW9/TkwTEQAw==", - "cpu": [ - "arm64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@anthropic-ai/claude-code-darwin-x64": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-darwin-x64/-/claude-code-darwin-x64-2.1.142.tgz", - "integrity": "sha512-8GNrDyJQQ1u9pR7aAeQaB8tp7nTJrBnBdaHGknwRYYPxpmfvpGMZZQz7MuSyh36emKAuJahoq+Lh2o4oVj+apg==", - "cpu": [ - "x64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@anthropic-ai/claude-code-linux-arm64": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-arm64/-/claude-code-linux-arm64-2.1.142.tgz", - "integrity": "sha512-kfVkdeZwpjrxlWYY9Ceucwv4jxpXmexs1jlHkH862qTuYJbvO+q1mqL3ynQ6WRm7/v09kRMZXUpkN8eVIZRgZQ==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@anthropic-ai/claude-code-linux-arm64-musl": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-arm64-musl/-/claude-code-linux-arm64-musl-2.1.142.tgz", - "integrity": "sha512-yQ9WmrTL+b4qe1ibSEe65qQFhS8wSdf4boIvDx8kPmQZ+K0uDgqUQHyFHVK4yYs0nXMAZmTN7rw3bxQgEB+HwQ==", - "cpu": [ - "arm64" - ], - "libc": [ - "musl" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@anthropic-ai/claude-code-linux-x64": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-x64/-/claude-code-linux-x64-2.1.142.tgz", - "integrity": "sha512-s3RY1JAAKT3NV0c7q8xAp7lxI+awfCG0GqhmzFb7D/Grv1Duh8TiTdO4gm7We9wC/RW8PdP2YHlYTzEYzK8Zrg==", - "cpu": [ - "x64" - ], - "libc": [ - "glibc" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@anthropic-ai/claude-code-linux-x64-musl": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-linux-x64-musl/-/claude-code-linux-x64-musl-2.1.142.tgz", - "integrity": "sha512-IjWjVdzJL/eRbcItWM2TK1QOkLzCfWGIdEH5WPjIB0vvGHg5OIE4SHDA7l05trqNKNA7Pgt0I12qjGiG+tlR8Q==", - "cpu": [ - "x64" - ], - "libc": [ - "musl" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@anthropic-ai/claude-code-win32-arm64": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-win32-arm64/-/claude-code-win32-arm64-2.1.142.tgz", - "integrity": "sha512-IxyTLz4XflQaR5+hfnwHvx6WqJldjSH8ZrXaJeSIWgIjsUWhELbsp9QnrBK9t1ZP8sRs0AWagRpzoj0ogwq/8g==", - "cpu": [ - "arm64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@anthropic-ai/claude-code-win32-x64": { - "version": "2.1.142", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code-win32-x64/-/claude-code-win32-x64-2.1.142.tgz", - "integrity": "sha512-TKmT3cjQWpg/Idf/FvNEESijo2W9nR9CAlNzhOAqYy8vCbU0iRA+c2x9K/l1ng0GZGkxnMTJTfhkUHDw3Xi9/g==", - "cpu": [ - "x64" - ], - "license": "SEE LICENSE IN LICENSE.md", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@anthropic-ai/sdk": { "version": "0.93.0", "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.93.0.tgz", diff --git a/src-node/package.json b/src-node/package.json index 2c78bfefb1..e3a820527f 100644 --- a/src-node/package.json +++ b/src-node/package.json @@ -21,7 +21,6 @@ "IMPORTANT!!": "Adding things here will bloat up the package size", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.126", - "@anthropic-ai/claude-code": "^2.1.118", "@expo/sudo-prompt": "^9.3.2", "@phcode/fs": "^4.0.2", "cross-spawn": "^7.0.6", diff --git a/src/extensionsIntegrated/appUpdater/update-electron.js b/src/extensionsIntegrated/appUpdater/update-electron.js index 5fe98907ff..9629b88d2b 100644 --- a/src/extensionsIntegrated/appUpdater/update-electron.js +++ b/src/extensionsIntegrated/appUpdater/update-electron.js @@ -56,7 +56,6 @@ define(function (require, exports, module) { KEY_UPDATE_AVAILABLE = "PH_UPDATE_AVAILABLE"; const PREFS_AUTO_UPDATE = "autoUpdate"; - const MAX_LOG_LINES = 500; let isAutoUpdateFlow = true; let updateScheduled = false; let cachedUpdateDetails = null; @@ -281,6 +280,10 @@ define(function (require, exports, module) { */ function launchLinuxUpdater(onOutput) { return new Promise((resolve, reject) => { + // Spawn the installer in an external terminal emulator so sudo / + // interactive prompts work natively. The external terminal IS the + // install UI — no internal dialog. Probes common terminals in + // order; first hit wins. const stageValue = Phoenix.config.environment; console.log('Stage:', stageValue); let scriptUrl = 'https://updates.phcode.io/linux/installer.sh'; @@ -288,18 +291,33 @@ define(function (require, exports, module) { scriptUrl = "https://updates.phcode.io/linux/installer-latest-experimental-build.sh"; } - // Use spawnProcess to run bash with the wget|bash command - const command = '/bin/bash'; - const args = ['-c', `wget -qO- ${scriptUrl} | bash -s -- --upgrade`]; + // Inner command run inside the spawned terminal: fetch installer + // from $UPDATE_URL and pipe to bash, print exit code, pause so the + // user can read output before close. + const innerCmd = 'wget -qO- "$UPDATE_URL" | bash -s -- --upgrade; ec=$?; echo; echo "Installer exit code: $ec"; read -rp "Press Enter to close..."'; - window.electronAppAPI.spawnProcess(command, args) + // Use UPDATE_URL env var to avoid quoting the URL through multiple + // shell layers. nohup/disown so terminals that don't daemonize + // (xterm) still let the outer spawn return immediately. + const launcherScript = ` + export UPDATE_URL='${scriptUrl}' + if command -v gnome-terminal >/dev/null 2>&1; then + nohup gnome-terminal -- bash -c '${innerCmd}' >/dev/null 2>&1 & + elif command -v konsole >/dev/null 2>&1; then + nohup konsole -e bash -c '${innerCmd}' >/dev/null 2>&1 & + elif command -v xterm >/dev/null 2>&1; then + nohup xterm -e bash -c '${innerCmd}' >/dev/null 2>&1 & + elif command -v x-terminal-emulator >/dev/null 2>&1; then + nohup x-terminal-emulator -e bash -c '${innerCmd}' >/dev/null 2>&1 & + else + echo "No supported terminal emulator found" >&2 + exit 1 + fi + disown + `; + + window.electronAppAPI.spawnProcess('/bin/bash', ['-c', launcherScript]) .then(instanceId => { - // Set up output handlers - window.electronAppAPI.onProcessStdout((id, line) => { - if (id === instanceId && onOutput) { - onOutput('stdout', line); - } - }); window.electronAppAPI.onProcessStderr((id, line) => { if (id === instanceId && onOutput) { onOutput('stderr', line); @@ -310,13 +328,13 @@ define(function (require, exports, module) { if (data.code === 0) { resolve(); } else { - reject(new Error(`Update script exited with code: ${data.code}`)); + reject(new Error(`Failed to launch installer terminal (exit ${data.code})`)); } } }); window.electronAppAPI.onProcessError((id, err) => { if (id === instanceId) { - reject(new Error(`Update process error: ${err}`)); + reject(new Error(`Terminal spawn error: ${err}`)); } }); }) @@ -330,133 +348,35 @@ define(function (require, exports, module) { } // Clear the scheduled flag in shared state await window.electronAPI.setUpdateScheduled(false); - console.log("Installing update at quit time"); - return new Promise(resolve => { - let dialog; - let logLines = []; - - function appendLogLine(text) { - // Split text into lines and add each - const lines = text.split('\n').filter(l => l.trim()); - for (const line of lines) { - logLines.push(line); - // Keep only last MAX_LOG_LINES - if (logLines.length > MAX_LOG_LINES) { - logLines.shift(); - } - } - // Update the log display - const logElement = document.getElementById('update-log-output'); - if (logElement) { - logElement.textContent = logLines.join('\n'); - logElement.scrollTop = logElement.scrollHeight; - } - } - - function failUpdateDialogAndExit(err) { - console.error("error updating: ", err); - dialog && dialog.close(); - // Build full log text for copying - const fullLogText = logLines.join('\n') + '\n\nError: ' + (err.message || err); - // Show failure dialog with log output and hover copy icon - const failContent = ` -
${Strings.UPDATE_FAILED_VISIT_SITE_MESSAGE}
-${fullLogText}
-
- ${Strings.UPDATE_FAILED_VISIT_SITE_MESSAGE}
` + + `${errDetails}`,
[{ className: Dialogs.DIALOG_BTN_CLASS_PRIMARY, id: Dialogs.DIALOG_BTN_OK, text: Strings.OK }]
- );
- // Set up hover and click handlers for copy icon
- const $container = $('#update-fail-log-container');
- const $copyBtn = $('#update-log-copy-btn');
- $container.on('mouseenter', () => $copyBtn.css('opacity', '1'));
- $container.on('mouseleave', () => $copyBtn.css('opacity', '0'));
- $copyBtn.on('click', () => {
- Phoenix.app.copyToClipboard(fullLogText);
- $copyBtn.removeClass('fa-copy').addClass('fa-check');
- setTimeout(() => {
- $copyBtn.removeClass('fa-check').addClass('fa-copy');
- }, 1500);
- });
- $copyBtn.on('mouseenter', () => $copyBtn.css({ 'background': '#333', 'color': '#fff' }));
- $copyBtn.on('mouseleave', () => $copyBtn.css({ 'background': 'transparent', 'color': '#888' }));
-
- failDialog.done(() => {
+ ).done(() => {
NativeApp.openURLInDefaultBrowser(Phoenix.config.update_download_page)
.catch(console.error)
.finally(resolve);
});
- }
-
- // Create dialog with terminal-style log output
- const dialogContent = `
- ${Strings.UPDATE_INSTALLING_MESSAGE}
- - `; - - dialog = Dialogs.showModalDialog( - DefaultDialogs.DIALOG_ID_INFO, - Strings.UPDATE_INSTALLING, - dialogContent, - [ - { - className: "forced-hidden", - id: Dialogs.DIALOG_BTN_OK, - text: Strings.OK - } - ], - false - ); - - launchLinuxUpdater((type, text) => { - appendLogLine(text); - }) - .then(resolve) - .catch(failUpdateDialogAndExit); - }); + }); + } } AppInit.appReady(async function () {