@pixelbyte-software/pixcode 1.53.2 → 1.53.4

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/dist/index.html CHANGED
@@ -35,7 +35,7 @@
35
35
 
36
36
  <!-- Prevent zoom on iOS -->
37
37
  <meta name="format-detection" content="telephone=no" />
38
- <script type="module" crossorigin src="/assets/index-CP2HfVKD.js"></script>
38
+ <script type="module" crossorigin src="/assets/index-DlwfTw9d.js"></script>
39
39
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-DB6V5Fl1.js">
40
40
  <link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-CIYNS698.js">
41
41
  <link rel="modulepreload" crossorigin href="/assets/vendor-xterm-C7tpxJl7.js">
@@ -231,6 +231,52 @@ function getActiveUpdateJob() {
231
231
  }
232
232
  return null;
233
233
  }
234
+ function countByProvider(items) {
235
+ return items.reduce((counts, item) => {
236
+ const provider = item?.provider || 'unknown';
237
+ counts[provider] = (counts[provider] || 0) + 1;
238
+ return counts;
239
+ }, {});
240
+ }
241
+ function getActiveProviderWorkSummary() {
242
+ const sessions = [
243
+ ...getActiveClaudeSDKSessions().map((id) => ({ id, provider: 'claude' })),
244
+ ...getActiveCursorSessions().map((session) => ({ ...session, provider: 'cursor' })),
245
+ ...getActiveCodexSessions().map((session) => ({ ...session, provider: 'codex' })),
246
+ ...getActiveGeminiSessions().map((session) => ({ ...session, provider: 'gemini' })),
247
+ ...getActiveQwenSessions().map((session) => ({ ...session, provider: 'qwen' })),
248
+ ...getActiveOpencodeSessions().map((session) => ({ ...session, provider: 'opencode' })),
249
+ ];
250
+ return {
251
+ total: sessions.length,
252
+ byProvider: countByProvider(sessions),
253
+ };
254
+ }
255
+ function getActivePtyWorkSummary() {
256
+ const activePtys = Array.from(ptySessionsMap.values())
257
+ .filter((session) => session?.pty && session.lifecycleState === 'running')
258
+ .map((session) => ({
259
+ provider: session.isPlainShell ? 'plain-shell' : (session.provider || 'unknown'),
260
+ connected: Boolean(session.ws && session.ws.readyState === WebSocket.OPEN),
261
+ }));
262
+ return {
263
+ total: activePtys.length,
264
+ connected: activePtys.filter((session) => session.connected).length,
265
+ detached: activePtys.filter((session) => !session.connected).length,
266
+ byProvider: countByProvider(activePtys),
267
+ };
268
+ }
269
+ function getActiveWorkSummary() {
270
+ const pty = getActivePtyWorkSummary();
271
+ const agents = getActiveProviderWorkSummary();
272
+ const total = pty.total + agents.total;
273
+ return {
274
+ hasActiveWork: total > 0,
275
+ total,
276
+ pty,
277
+ agents,
278
+ };
279
+ }
234
280
  async function readLatestPixcodePackageMetadata() {
235
281
  const registryRes = await fetch('https://registry.npmjs.org/@pixelbyte-software/pixcode');
236
282
  if (!registryRes.ok)
@@ -329,8 +375,13 @@ async function runCommandUpdateJob(job, updateCommand, updateCwd) {
329
375
  cwd: updateCwd,
330
376
  env: process.env,
331
377
  shell: true,
378
+ detached: true,
332
379
  stdio: ['ignore', 'pipe', 'pipe'],
333
380
  });
381
+ try {
382
+ child.unref();
383
+ }
384
+ catch { /* noop */ }
334
385
  child.stdout?.on('data', (data) => appendUpdateJobLog(job, 'stdout', data.toString()));
335
386
  child.stderr?.on('data', (data) => appendUpdateJobLog(job, 'stderr', data.toString()));
336
387
  child.on('error', reject);
@@ -1427,6 +1478,7 @@ app.get('/api/system/update-state', authenticateToken, (req, res) => {
1427
1478
  success: true,
1428
1479
  state: readSystemUpdateState(),
1429
1480
  activeJob: snapshotUpdateJob(getActiveUpdateJob()),
1481
+ activeWork: getActiveWorkSummary(),
1430
1482
  currentVersion: SERVER_VERSION,
1431
1483
  installMode,
1432
1484
  capabilities: {
@@ -1815,6 +1867,15 @@ app.post('/api/system/update', authenticateToken, requireAdmin, requireApiScope(
1815
1867
  // (systemd/pm2/daemon manager) can bring the server back on the new code.
1816
1868
  // Foreground installs without a wrapper will simply stop; the UI reports this.
1817
1869
  app.post('/api/system/restart', authenticateToken, requireAdmin, requireApiScope('system:restart'), (req, res) => {
1870
+ const forceRestart = req.body?.force === true || req.query.force === 'true';
1871
+ const activeWork = getActiveWorkSummary();
1872
+ if (!forceRestart && activeWork.hasActiveWork) {
1873
+ return res.status(409).json({
1874
+ success: false,
1875
+ error: 'Active terminal or agent sessions are running. Confirm restart to interrupt them.',
1876
+ activeWork,
1877
+ });
1878
+ }
1818
1879
  res.json({
1819
1880
  success: true,
1820
1881
  version: SERVER_VERSION,