@pixelbyte-software/pixcode 1.31.10 → 1.31.11

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-XT7dX9Q7.js"></script>
38
+ <script type="module" crossorigin src="/assets/index-DKfsThT6.js"></script>
39
39
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-D7WwDXvu.js">
40
40
  <link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-CzYAOTxS.js">
41
41
  <link rel="modulepreload" crossorigin href="/assets/vendor-xterm-CJZjLICi.js">
42
- <link rel="stylesheet" crossorigin href="/assets/index-CDpePeIN.css">
42
+ <link rel="stylesheet" crossorigin href="/assets/index-CLxSMbv1.css">
43
43
  </head>
44
44
  <body>
45
45
  <div id="root"></div>
@@ -95,7 +95,14 @@ const WATCHER_IGNORED_PATTERNS = [
95
95
  '**/*.swp',
96
96
  '**/.DS_Store'
97
97
  ];
98
- const WATCHER_DEBOUNCE_MS = 300;
98
+ // Debounce chokidar events before rescanning all provider project trees.
99
+ // During an active chat, each model writes its transcript to
100
+ // ~/.<provider>/projects/<encoded>/*.jsonl in small chunks — with a 300ms
101
+ // window every few chunks triggered a full getProjects() + broadcast to
102
+ // every open tab, which shows up as mouse/UI stutter. 1500ms collapses
103
+ // a full chat reply into ~1 scan while still feeling responsive when
104
+ // the user flips to the projects list.
105
+ const WATCHER_DEBOUNCE_MS = 1500;
99
106
  let projectsWatchers = [];
100
107
  let projectsWatcherDebounceTimer = null;
101
108
  const connectedClients = new Set();
@@ -179,8 +186,14 @@ async function setupProjectsWatcher() {
179
186
  followSymlinks: false,
180
187
  depth: 10, // Reasonable depth limit
181
188
  awaitWriteFinish: {
182
- stabilityThreshold: 100, // Wait 100ms for file to stabilize
183
- pollInterval: 50
189
+ // Raised from (100, 50) to (500, 250). The old settings
190
+ // had chokidar polling every 50ms per in-flight file; an
191
+ // active chat writes its .jsonl transcript continuously,
192
+ // so 50ms polls meant ~20 wakeups/sec per file. The new
193
+ // cadence still stabilizes reliably and cuts the wakeup
194
+ // count by 5x.
195
+ stabilityThreshold: 500,
196
+ pollInterval: 250
184
197
  }
185
198
  });
186
199
  // Set up event listeners
@@ -716,6 +729,22 @@ const expandWorkspacePath = (inputPath) => {
716
729
  return WORKSPACES_BASE;
717
730
  return normalizeWorkspacePath(inputPath);
718
731
  };
732
+ // Filesystem browser uses a home-centric expansion rather than the
733
+ // WORKSPACES_BASE-centric one above. The workspace-base treatment of `~`
734
+ // is right for NEW project creation (users say "my-app" and get it under
735
+ // ~/pixcode/projects/my-app) but wrong for browsing — users want to pick
736
+ // any folder on their disk, not be trapped inside the default base.
737
+ const expandBrowsePath = (inputPath) => {
738
+ if (!inputPath)
739
+ return os.homedir();
740
+ const trimmed = String(inputPath).trim();
741
+ if (!trimmed || trimmed === '~')
742
+ return os.homedir();
743
+ if (trimmed.startsWith('~/') || trimmed.startsWith('~\\')) {
744
+ return path.join(os.homedir(), trimmed.slice(2));
745
+ }
746
+ return path.resolve(trimmed);
747
+ };
719
748
  // Browse filesystem endpoint for project suggestions - uses existing getFileTree
720
749
  app.get('/api/browse-filesystem', authenticateToken, async (req, res) => {
721
750
  try {
@@ -723,9 +752,11 @@ app.get('/api/browse-filesystem', authenticateToken, async (req, res) => {
723
752
  console.log('[API] Browse filesystem request for path:', dirPath);
724
753
  console.log('[API] WORKSPACES_ROOT is:', WORKSPACES_ROOT);
725
754
  console.log('[API] WORKSPACES_BASE is:', WORKSPACES_BASE);
726
- // Default to home directory if no path provided
727
- const defaultRoot = WORKSPACES_BASE;
728
- let targetPath = dirPath ? expandWorkspacePath(dirPath) : defaultRoot;
755
+ // Default to the user's home directory so the picker feels natural
756
+ // users can reach arbitrary drives/folders from there. The
757
+ // ~/pixcode/projects shortcut stays available as a suggestion.
758
+ const defaultRoot = os.homedir();
759
+ let targetPath = dirPath ? expandBrowsePath(dirPath) : defaultRoot;
729
760
  // Security check - ensure path is within allowed workspace root
730
761
  let validation = await validateWorkspacePath(targetPath);
731
762
  if (!validation.valid) {
@@ -1505,39 +1536,31 @@ function handleChatConnection(ws, request) {
1505
1536
  ws.on('message', async (message) => {
1506
1537
  try {
1507
1538
  const data = JSON.parse(message);
1539
+ // Per-submission logs removed from hot paths — gate behind
1540
+ // CHAT_DEBUG so production stdout stays clean. Each keypress
1541
+ // that triggers a submit was costing 4 synchronous writes.
1542
+ const chatDebug = process.env.CHAT_DEBUG
1543
+ ? (provider, d) => console.log(`[${provider}]`, d.command?.slice(0, 60) || '[resume]', d.options?.projectPath || d.options?.cwd || '', d.options?.sessionId ? 'resume' : 'new')
1544
+ : () => { };
1508
1545
  if (data.type === 'claude-command') {
1509
- console.log('[DEBUG] User message:', data.command || '[Continue/Resume]');
1510
- console.log('📁 Project:', data.options?.projectPath || 'Unknown');
1511
- console.log('🔄 Session:', data.options?.sessionId ? 'Resume' : 'New');
1546
+ chatDebug('claude', data);
1512
1547
  // Use Claude Agents SDK
1513
1548
  await queryClaudeSDK(data.command, data.options, writer);
1514
1549
  }
1515
1550
  else if (data.type === 'cursor-command') {
1516
- console.log('[DEBUG] Cursor message:', data.command || '[Continue/Resume]');
1517
- console.log('📁 Project:', data.options?.cwd || 'Unknown');
1518
- console.log('🔄 Session:', data.options?.sessionId ? 'Resume' : 'New');
1519
- console.log('🤖 Model:', data.options?.model || 'default');
1551
+ chatDebug('cursor', data);
1520
1552
  await spawnCursor(data.command, data.options, writer);
1521
1553
  }
1522
1554
  else if (data.type === 'codex-command') {
1523
- console.log('[DEBUG] Codex message:', data.command || '[Continue/Resume]');
1524
- console.log('📁 Project:', data.options?.projectPath || data.options?.cwd || 'Unknown');
1525
- console.log('🔄 Session:', data.options?.sessionId ? 'Resume' : 'New');
1526
- console.log('🤖 Model:', data.options?.model || 'default');
1555
+ chatDebug('codex', data);
1527
1556
  await queryCodex(data.command, data.options, writer);
1528
1557
  }
1529
1558
  else if (data.type === 'gemini-command') {
1530
- console.log('[DEBUG] Gemini message:', data.command || '[Continue/Resume]');
1531
- console.log('📁 Project:', data.options?.projectPath || data.options?.cwd || 'Unknown');
1532
- console.log('🔄 Session:', data.options?.sessionId ? 'Resume' : 'New');
1533
- console.log('🤖 Model:', data.options?.model || 'default');
1559
+ chatDebug('gemini', data);
1534
1560
  await spawnGemini(data.command, data.options, writer);
1535
1561
  }
1536
1562
  else if (data.type === 'qwen-command') {
1537
- console.log('[DEBUG] Qwen Code message:', data.command || '[Continue/Resume]');
1538
- console.log('📁 Project:', data.options?.projectPath || data.options?.cwd || 'Unknown');
1539
- console.log('🔄 Session:', data.options?.sessionId ? 'Resume' : 'New');
1540
- console.log('🤖 Model:', data.options?.model || 'default');
1563
+ chatDebug('qwen', data);
1541
1564
  await spawnQwen(data.command, data.options, writer);
1542
1565
  }
1543
1566
  else if (data.type === 'cursor-resume') {
@@ -1673,9 +1696,22 @@ function handleShellConnection(ws) {
1673
1696
  ws.on('message', async (message) => {
1674
1697
  try {
1675
1698
  const data = JSON.parse(message);
1676
- console.log('📨 Shell message received:', data.type);
1699
+ // Per-message log would fire once per keystroke — gate behind
1700
+ // SHELL_DEBUG so stdout isn't flooded during normal typing.
1701
+ if (process.env.SHELL_DEBUG) {
1702
+ console.log('[shell]', data.type);
1703
+ }
1677
1704
  if (data.type === 'init') {
1678
- const projectPath = data.projectPath || process.cwd();
1705
+ // Fallback to the user's home directory (not process.cwd()).
1706
+ // In the Electron wrapper, process.cwd() is the runtime dir
1707
+ // under %APPDATA%\pixcode-desktop\pixcode-runtime — spawning a
1708
+ // login terminal there shows the user a confusing path and
1709
+ // sometimes trips up CLIs that expect a "normal" location
1710
+ // (e.g. codex login exited 1 because the runtime dir is
1711
+ // read-only-feeling / non-writable for cache paths). home
1712
+ // is writable, has a git-friendly cwd, and matches where
1713
+ // every provider already stores its config (~/.codex etc.).
1714
+ const projectPath = data.projectPath || os.homedir();
1679
1715
  const sessionId = data.sessionId;
1680
1716
  const hasSession = data.hasSession;
1681
1717
  const provider = data.provider || 'claude';
@@ -1683,9 +1719,16 @@ function handleShellConnection(ws) {
1683
1719
  const isPlainShell = data.isPlainShell || (!!initialCommand && !hasSession) || provider === 'plain-shell';
1684
1720
  urlDetectionBuffer = '';
1685
1721
  announcedAuthUrls.clear();
1686
- // Login commands (Claude/Cursor auth) should never reuse cached sessions
1722
+ // Login commands should never reuse cached sessions — each login
1723
+ // is a fresh OAuth handshake with a new callback URL. Missing
1724
+ // entries here used to cause "Process exited with code 1" on
1725
+ // the second login attempt because the cached PTY from the
1726
+ // first attempt was still alive and the CLI refused to
1727
+ // re-bind its localhost callback port.
1687
1728
  const isLoginCommand = initialCommand && (initialCommand.includes('setup-token') ||
1688
1729
  initialCommand.includes('cursor-agent login') ||
1730
+ initialCommand.includes('codex login') ||
1731
+ initialCommand.includes('qwen auth') ||
1689
1732
  initialCommand.includes('auth login'));
1690
1733
  // Include command hash in session key so different commands get separate sessions
1691
1734
  const commandSuffix = isPlainShell && initialCommand