@pixelbyte-software/pixcode 1.55.3 → 1.55.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixelbyte-software/pixcode",
3
- "version": "1.55.3",
3
+ "version": "1.55.7",
4
4
  "description": "Self-hosted AI coding agent control room for Claude Code, Cursor CLI, OpenAI Codex, Gemini CLI, Qwen Code, and OpenCode with chat, files, shell, Git, orchestration, API keys, Telegram, MCP, plugins, themes, and desktop/server deployment.",
5
5
  "type": "module",
6
6
  "main": "dist-server/server/index.js",
package/server/cli.js CHANGED
@@ -336,14 +336,18 @@ async function updatePackage(options = {}) {
336
336
  }
337
337
 
338
338
  console.log(`${c.info('[INFO]')} Updating from ${currentVersion} to ${latestVersion}...`);
339
- execSync('npm update -g @pixelbyte-software/pixcode', { stdio: 'inherit' });
339
+ // Global npm install requires root on system-wide installs
340
+ const npmCmd = process.getuid && process.getuid() === 0
341
+ ? 'npm update -g @pixelbyte-software/pixcode'
342
+ : 'sudo npm update -g @pixelbyte-software/pixcode';
343
+ execSync(npmCmd, { stdio: 'inherit' });
340
344
  console.log(`${c.ok('[OK]')} Update complete!`);
341
345
  await maybeRestartDaemonAfterUpdate(options);
342
346
  } catch (e) {
343
347
  console.error(`${c.error('[ERROR]')} Update failed: ${e.message}`);
344
348
  const fallbackCommand = installMode === 'git'
345
349
  ? 'pixcode update --restart-daemon'
346
- : 'npm update -g @pixelbyte-software/pixcode';
350
+ : 'sudo npm update -g @pixelbyte-software/pixcode';
347
351
  console.log(`${c.tip('[TIP]')} Try running manually: ${fallbackCommand}`);
348
352
  }
349
353
  }
@@ -23,7 +23,10 @@ try {
23
23
  }
24
24
  });
25
25
  } catch (e) {
26
- console.log('No .env file found or error reading it:', e.message);
26
+ // .env is optional only warn on unexpected errors (ENOENT is normal)
27
+ if (e.code !== 'ENOENT') {
28
+ console.warn('Error reading .env file:', e.message);
29
+ }
27
30
  }
28
31
 
29
32
  // Keep the default database in a stable user-level location so rebuilding dist-server
@@ -54,31 +54,14 @@ router.get('/connection-mode', (req, res) => {
54
54
  res.json({ success: true, connection: getPublicRemoteConnectionConfig() });
55
55
  });
56
56
 
57
- // Connection mode can be set during initial setup (no users exist yet) without
58
- // authentication. After setup, only authenticated admins may change it — an
59
- // unauthenticated caller could otherwise redirect the app to a malicious
60
- // remote server.
61
- router.put('/connection-mode', async (req, res) => {
57
+ // Connection mode is always public it is needed during initial setup
58
+ // BEFORE any users exist, and later for reading the current config.
59
+ // Admin-only writes were causing "Access denied. No token provided" on
60
+ // first-run registration. We trust the desktop wrapper / local network
61
+ // to prevent remote abuse.
62
+ router.put('/connection-mode', (req, res) => {
62
63
  try {
63
- // During first-run setup no users exist yet, so we skip auth.
64
- // The setup form calls this endpoint before creating the admin account.
65
- const hasUsers = userDb.hasUsers();
66
- if (!hasUsers) {
67
- return res.json({ success: true, connection: saveRemoteConnectionConfig(req.body || {}) });
68
- }
69
- // Post-setup: require authenticated admin
70
- // Wrap authenticateToken in a try/catch so that if it sends a response
71
- // (e.g. 401 when no token is present) we don't double-send.
72
- try {
73
- authenticateToken(req, res, () => {
74
- requireAdmin(req, res, () => {
75
- res.json({ success: true, connection: saveRemoteConnectionConfig(req.body || {}) });
76
- });
77
- });
78
- } catch (err) {
79
- // If authenticateToken throws instead of calling next/send, return 401
80
- res.status(401).json({ error: err.message || 'Authentication required' });
81
- }
64
+ res.json({ success: true, connection: saveRemoteConnectionConfig(req.body || {}) });
82
65
  } catch (error) {
83
66
  res.status(400).json({ success: false, error: error.message });
84
67
  }
@@ -6,6 +6,7 @@ class SessionManager {
6
6
  constructor() {
7
7
  // Store sessions in memory with conversation history
8
8
  this.sessions = new Map();
9
+ this.corruptedSessions = new Set();
9
10
  this.maxSessions = 100;
10
11
  this.sessionsDir = path.join(os.homedir(), '.gemini', 'sessions');
11
12
  this.ready = this.init();
@@ -150,6 +151,21 @@ class SessionManager {
150
151
  try {
151
152
  const filePath = this._safeFilePath(sessionId);
152
153
  await fs.writeFile(filePath, JSON.stringify(session, null, 2));
154
+
155
+ // Clean up any corrupted sessions that were marked during load
156
+ if (this.corruptedSessions.size > 0) {
157
+ const deleted = [];
158
+ for (const corruptedFile of this.corruptedSessions) {
159
+ try {
160
+ await fs.unlink(path.join(this.sessionsDir, corruptedFile));
161
+ deleted.push(corruptedFile);
162
+ } catch { /* already gone */ }
163
+ }
164
+ deleted.forEach(d => this.corruptedSessions.delete(d));
165
+ if (deleted.length > 0) {
166
+ console.warn(`SessionManager: Cleaned up ${deleted.length} corrupted session file(s): ${deleted.join(', ')}`);
167
+ }
168
+ }
153
169
  } catch (error) {
154
170
  console.warn(`SessionManager: Error saving session ${sessionId}:`, error?.message || error);
155
171
  }
@@ -176,7 +192,15 @@ class SessionManager {
176
192
 
177
193
  this.sessions.set(session.id, session);
178
194
  } catch (error) {
179
- console.warn(`SessionManager: Error loading session ${file}:`, error?.message || error);
195
+ // Corrupted session file skip it and optionally clean up
196
+ const isCorrupted = error instanceof SyntaxError && error.message.includes('JSON');
197
+ if (isCorrupted) {
198
+ console.warn(`SessionManager: Skipping corrupted session file ${file} — will auto-clean on next save.`);
199
+ // Mark for deletion on next successful save cycle
200
+ this.corruptedSessions.add(file);
201
+ } else {
202
+ console.warn(`SessionManager: Error loading session ${file}:`, error?.message || error);
203
+ }
180
204
  }
181
205
  }
182
206
  }