@pixelbyte-software/pixcode 1.50.7 → 1.50.8

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-CR4j4iu_.js"></script>
38
+ <script type="module" crossorigin src="/assets/index-gecaamTl.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">
@@ -118,6 +118,8 @@ let projectsWatchers = [];
118
118
  let projectsWatcherDebounceTimer = null;
119
119
  const connectedClients = new Set();
120
120
  let isGetProjectsRunning = false; // Flag to prevent reentrant calls
121
+ const STARTUP_INPUT_READY_TIMEOUT_MS = 10 * 60 * 1000;
122
+ const STARTUP_INPUT_POLL_MS = 750;
121
123
  // Broadcast progress to all connected WebSocket clients
122
124
  function broadcastProgress(progress) {
123
125
  const message = JSON.stringify({
@@ -244,6 +246,10 @@ function terminatePtySession(sessionKey, session, reason) {
244
246
  if (session.timeoutId) {
245
247
  clearTimeout(session.timeoutId);
246
248
  }
249
+ if (session.startupInputTimerId) {
250
+ clearTimeout(session.startupInputTimerId);
251
+ session.startupInputTimerId = null;
252
+ }
247
253
  try {
248
254
  if (session.pty && session.pty.kill) {
249
255
  session.pty.kill();
@@ -360,24 +366,86 @@ function appendPtySessionBuffer(session, data) {
360
366
  }
361
367
  }
362
368
  function normalizeTerminalStartupInput(input) {
363
- return `${String(input || '').replace(/(?:\r\n|\r|\n)+$/u, '')}\r`;
369
+ return `\x15${String(input || '').replace(/(?:\r\n|\r|\n)+$/u, '')}\r`;
364
370
  }
365
- function writeTerminalStartupInput(session, startupInput, reason, delayMs = 500) {
366
- if (!session?.pty || !startupInput)
371
+ function readSessionOutputForState(session, maxChars = 12000) {
372
+ return stripAnsiSequences((session?.buffer || []).join('').slice(-maxChars));
373
+ }
374
+ function shouldWaitForProviderIdle(provider) {
375
+ return provider === 'codex';
376
+ }
377
+ function isTerminalReadyForStartupInput(session) {
378
+ if (!session?.pty || session.lifecycleState !== 'running') {
379
+ return { ready: false, retry: false, terminalState: 'exited' };
380
+ }
381
+ const output = readSessionOutputForState(session);
382
+ const state = resolveProviderTerminalState(session, session.provider, output);
383
+ if (state.terminalState === 'busy') {
384
+ return { ready: false, retry: true, terminalState: state.terminalState };
385
+ }
386
+ if (state.terminalState === 'idle') {
387
+ return { ready: true, retry: false, terminalState: state.terminalState };
388
+ }
389
+ if (shouldWaitForProviderIdle(session.provider)) {
390
+ return { ready: false, retry: true, terminalState: state.terminalState };
391
+ }
392
+ return { ready: true, retry: false, terminalState: state.terminalState };
393
+ }
394
+ function processTerminalStartupInputQueue(session) {
395
+ if (!session?.pendingStartupInputs?.length) {
396
+ session.startupInputTimerId = null;
367
397
  return;
368
- const submittedInput = normalizeTerminalStartupInput(startupInput);
369
- setTimeout(() => {
370
- try {
371
- if (session.pty && session.lifecycleState === 'running') {
372
- session.pty.write(submittedInput);
373
- session.updatedAt = Date.now();
374
- console.log(`⌨️ Submitted startup input to visible PTY (${reason})`);
398
+ }
399
+ const item = session.pendingStartupInputs[0];
400
+ const readiness = isTerminalReadyForStartupInput(session);
401
+ if (!readiness.ready) {
402
+ if (!readiness.retry || Date.now() - item.queuedAt > STARTUP_INPUT_READY_TIMEOUT_MS) {
403
+ session.pendingStartupInputs.shift();
404
+ session.startupInputTimerId = null;
405
+ const message = `\r\n\x1b[33m[Pixcode] Startup input was not sent because ${session.provider} is still ${readiness.terminalState || 'unavailable'}.\x1b[0m\r\n`;
406
+ try {
407
+ session.ws?.send?.(JSON.stringify({ type: 'output', data: message }));
375
408
  }
409
+ catch { /* websocket gone */ }
410
+ if (session.pendingStartupInputs.length > 0) {
411
+ session.startupInputTimerId = setTimeout(() => processTerminalStartupInputQueue(session), STARTUP_INPUT_POLL_MS);
412
+ }
413
+ return;
376
414
  }
377
- catch (error) {
378
- console.warn('Failed to submit startup input to visible PTY:', error?.message || error);
379
- }
380
- }, delayMs);
415
+ session.startupInputTimerId = setTimeout(() => processTerminalStartupInputQueue(session), STARTUP_INPUT_POLL_MS);
416
+ return;
417
+ }
418
+ session.pendingStartupInputs.shift();
419
+ session.startupInputTimerId = null;
420
+ try {
421
+ session.pty.write(normalizeTerminalStartupInput(item.startupInput));
422
+ session.updatedAt = Date.now();
423
+ console.log(`⌨️ Submitted startup input to visible PTY (${item.reason})`);
424
+ }
425
+ catch (error) {
426
+ console.warn('Failed to submit startup input to visible PTY:', error?.message || error);
427
+ }
428
+ if (session.pendingStartupInputs.length > 0) {
429
+ session.startupInputTimerId = setTimeout(() => processTerminalStartupInputQueue(session), STARTUP_INPUT_POLL_MS);
430
+ }
431
+ }
432
+ function queueTerminalStartupInput(session, startupInput, reason, delayMs = 500) {
433
+ if (!session?.pty || !startupInput)
434
+ return;
435
+ if (!Array.isArray(session.pendingStartupInputs)) {
436
+ session.pendingStartupInputs = [];
437
+ }
438
+ session.pendingStartupInputs.push({
439
+ startupInput,
440
+ reason,
441
+ queuedAt: Date.now(),
442
+ });
443
+ if (session.startupInputTimerId)
444
+ return;
445
+ session.startupInputTimerId = setTimeout(() => processTerminalStartupInputQueue(session), delayMs);
446
+ }
447
+ function writeTerminalStartupInput(session, startupInput, reason, delayMs = 500) {
448
+ queueTerminalStartupInput(session, startupInput, reason, delayMs);
381
449
  }
382
450
  function normalizeShellPermissionMode(value) {
383
451
  return typeof value === 'string' ? value.trim() : '';
@@ -2286,6 +2354,8 @@ function handleShellConnection(ws, request) {
2286
2354
  });
2287
2355
  }
2288
2356
  existingSession.ws = ws;
2357
+ existingSession.hermesLaunchId = hermesLaunchId || existingSession.hermesLaunchId;
2358
+ existingSession.updatedAt = Date.now();
2289
2359
  if (terminalStartupInput && !isPlainShell) {
2290
2360
  writeTerminalStartupInput(existingSession, terminalStartupInput, 'reused provider session', 350);
2291
2361
  }
@@ -2501,6 +2571,8 @@ function handleShellConnection(ws, request) {
2501
2571
  exitSignal: null,
2502
2572
  completedAt: null,
2503
2573
  keepAliveUntilExit: false,
2574
+ pendingStartupInputs: [],
2575
+ startupInputTimerId: null,
2504
2576
  updatedAt: Date.now(),
2505
2577
  });
2506
2578
  const createdSession = ptySessionsMap.get(ptySessionKey);
@@ -2565,6 +2637,11 @@ function handleShellConnection(ws, request) {
2565
2637
  session.exitSignal = exitCode.signal || null;
2566
2638
  session.completedAt = new Date().toISOString();
2567
2639
  session.updatedAt = Date.now();
2640
+ if (session.startupInputTimerId) {
2641
+ clearTimeout(session.startupInputTimerId);
2642
+ session.startupInputTimerId = null;
2643
+ }
2644
+ session.pendingStartupInputs = [];
2568
2645
  session.pty = null;
2569
2646
  appendPtySessionBuffer(session, exitMessage);
2570
2647
  }