@pixelbyte-software/pixcode 1.48.2 → 1.48.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,11 +35,11 @@
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-BFCPlLdw.js"></script>
38
+ <script type="module" crossorigin src="/assets/index--CoGCNtl.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
- <link rel="modulepreload" crossorigin href="/assets/vendor-xterm-CJZjLICi.js">
42
- <link rel="stylesheet" crossorigin href="/assets/index-Dr-4mhE7.css">
41
+ <link rel="modulepreload" crossorigin href="/assets/vendor-xterm-C7tpxJl7.js">
42
+ <link rel="stylesheet" crossorigin href="/assets/index-ipxWr2Zo.css">
43
43
  </head>
44
44
  <body>
45
45
  <div id="root"></div>
@@ -232,7 +232,37 @@ const server = http.createServer(app);
232
232
  const ptySessionsMap = new Map();
233
233
  const PTY_SESSION_TIMEOUT = 30 * 60 * 1000;
234
234
  const SHELL_URL_PARSE_BUFFER_LIMIT = 32768;
235
+ const SHELL_CLI_PROVIDERS = new Set(['claude', 'codex', 'cursor', 'gemini', 'qwen', 'opencode']);
235
236
  import { stripAnsiSequences, normalizeDetectedUrl, extractUrlsFromText, shouldAutoOpenUrlFromOutput } from './utils/url-detection.js';
237
+ function terminatePtySession(sessionKey, session, reason) {
238
+ if (!session)
239
+ return false;
240
+ console.log(`🧹 Terminating PTY session (${reason}):`, sessionKey);
241
+ if (session.timeoutId) {
242
+ clearTimeout(session.timeoutId);
243
+ }
244
+ try {
245
+ if (session.pty && session.pty.kill) {
246
+ session.pty.kill();
247
+ }
248
+ }
249
+ catch (error) {
250
+ console.warn('Failed to kill PTY session:', error.message);
251
+ }
252
+ ptySessionsMap.delete(sessionKey);
253
+ return true;
254
+ }
255
+ function killProviderPtySessions(projectPath, provider) {
256
+ let killed = 0;
257
+ for (const [sessionKey, session] of ptySessionsMap.entries()) {
258
+ if (session?.projectPath === projectPath &&
259
+ session?.provider === provider &&
260
+ !session?.isPlainShell) {
261
+ killed += terminatePtySession(sessionKey, session, 'fresh provider session') ? 1 : 0;
262
+ }
263
+ }
264
+ return killed;
265
+ }
236
266
  // Single WebSocket server that handles both paths
237
267
  const wss = new WebSocketServer({
238
268
  server,
@@ -295,6 +325,15 @@ app.get('/health', (req, res) => {
295
325
  });
296
326
  // Optional API key validation (if configured)
297
327
  app.use('/api', validateApiKey);
328
+ app.post('/api/shell/sessions/terminate', authenticateToken, (req, res) => {
329
+ const provider = req.body?.provider || 'claude';
330
+ const projectPath = req.body?.projectPath || os.homedir();
331
+ if (!SHELL_CLI_PROVIDERS.has(provider)) {
332
+ return res.status(400).json({ error: 'Unsupported provider' });
333
+ }
334
+ const killedSessions = killProviderPtySessions(projectPath, provider);
335
+ res.json({ success: true, killedSessions });
336
+ });
298
337
  // Authentication routes (public)
299
338
  app.use('/api/auth', authRoutes);
300
339
  // Projects API Routes (protected)
@@ -1896,6 +1935,7 @@ function handleShellConnection(ws) {
1896
1935
  const provider = data.provider || 'claude';
1897
1936
  const initialCommand = data.initialCommand;
1898
1937
  const isPlainShell = data.isPlainShell || (!!initialCommand && !hasSession) || provider === 'plain-shell';
1938
+ const forceNewSession = Boolean(data.forceNewSession && !isPlainShell);
1899
1939
  urlDetectionBuffer = '';
1900
1940
  announcedAuthUrls.clear();
1901
1941
  // Login commands should never reuse cached sessions — each login
@@ -1924,15 +1964,16 @@ function handleShellConnection(ws) {
1924
1964
  if (isLoginCommand) {
1925
1965
  const oldSession = ptySessionsMap.get(ptySessionKey);
1926
1966
  if (oldSession) {
1927
- console.log('🧹 Cleaning up existing login session:', ptySessionKey);
1928
- if (oldSession.timeoutId)
1929
- clearTimeout(oldSession.timeoutId);
1930
- if (oldSession.pty && oldSession.pty.kill)
1931
- oldSession.pty.kill();
1932
- ptySessionsMap.delete(ptySessionKey);
1967
+ terminatePtySession(ptySessionKey, oldSession, 'fresh login');
1968
+ }
1969
+ }
1970
+ else if (forceNewSession) {
1971
+ const killedSessions = killProviderPtySessions(projectPath, provider);
1972
+ if (killedSessions > 0) {
1973
+ console.log(`🧹 Fresh ${provider} session requested; terminated ${killedSessions} cached PTY session(s).`);
1933
1974
  }
1934
1975
  }
1935
- const existingSession = isLoginCommand ? null : ptySessionsMap.get(ptySessionKey);
1976
+ const existingSession = (isLoginCommand || forceNewSession) ? null : ptySessionsMap.get(ptySessionKey);
1936
1977
  if (existingSession) {
1937
1978
  console.log('♻️ Reconnecting to existing PTY session:', ptySessionKey);
1938
1979
  shellProcess = existingSession.pty;
@@ -2139,7 +2180,9 @@ function handleShellConnection(ws) {
2139
2180
  buffer: [],
2140
2181
  timeoutId: null,
2141
2182
  projectPath,
2142
- sessionId
2183
+ sessionId,
2184
+ provider,
2185
+ isPlainShell
2143
2186
  });
2144
2187
  // Handle data output
2145
2188
  shellProcess.onData((data) => {