@pixelbyte-software/pixcode 1.50.6 → 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-DVEXTVKy.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();
@@ -359,6 +365,88 @@ function appendPtySessionBuffer(session, data) {
359
365
  session.buffer.push(data);
360
366
  }
361
367
  }
368
+ function normalizeTerminalStartupInput(input) {
369
+ return `\x15${String(input || '').replace(/(?:\r\n|\r|\n)+$/u, '')}\r`;
370
+ }
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;
397
+ return;
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 }));
408
+ }
409
+ catch { /* websocket gone */ }
410
+ if (session.pendingStartupInputs.length > 0) {
411
+ session.startupInputTimerId = setTimeout(() => processTerminalStartupInputQueue(session), STARTUP_INPUT_POLL_MS);
412
+ }
413
+ return;
414
+ }
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);
449
+ }
362
450
  function normalizeShellPermissionMode(value) {
363
451
  return typeof value === 'string' ? value.trim() : '';
364
452
  }
@@ -2183,6 +2271,9 @@ function handleShellConnection(ws, request) {
2183
2271
  const startupInput = typeof data.startupInput === 'string' && data.startupInput.trim()
2184
2272
  ? data.startupInput.trim()
2185
2273
  : null;
2274
+ const startupInputDelivery = data.startupInputDelivery === 'terminal' ? 'terminal' : 'command';
2275
+ const commandStartupInput = startupInputDelivery === 'command' ? startupInput : null;
2276
+ const terminalStartupInput = startupInputDelivery === 'terminal' ? startupInput : null;
2186
2277
  const hermesLaunchId = Number.isFinite(Number(data.hermesLaunchId)) && Number(data.hermesLaunchId) > 0
2187
2278
  ? Number(data.hermesLaunchId)
2188
2279
  : null;
@@ -2263,6 +2354,11 @@ function handleShellConnection(ws, request) {
2263
2354
  });
2264
2355
  }
2265
2356
  existingSession.ws = ws;
2357
+ existingSession.hermesLaunchId = hermesLaunchId || existingSession.hermesLaunchId;
2358
+ existingSession.updatedAt = Date.now();
2359
+ if (terminalStartupInput && !isPlainShell) {
2360
+ writeTerminalStartupInput(existingSession, terminalStartupInput, 'reused provider session', 350);
2361
+ }
2266
2362
  return;
2267
2363
  }
2268
2364
  }
@@ -2340,8 +2436,8 @@ function handleShellConnection(ws, request) {
2340
2436
  shellCommand = `${command} resume "${sessionId}" || ${command}`;
2341
2437
  }
2342
2438
  }
2343
- else if (startupInput) {
2344
- shellCommand = `${command} ${quoteShellArgForPlatform(startupInput)}`;
2439
+ else if (commandStartupInput) {
2440
+ shellCommand = `${command} ${quoteShellArgForPlatform(commandStartupInput)}`;
2345
2441
  }
2346
2442
  else {
2347
2443
  shellCommand = command;
@@ -2475,8 +2571,14 @@ function handleShellConnection(ws, request) {
2475
2571
  exitSignal: null,
2476
2572
  completedAt: null,
2477
2573
  keepAliveUntilExit: false,
2574
+ pendingStartupInputs: [],
2575
+ startupInputTimerId: null,
2478
2576
  updatedAt: Date.now(),
2479
2577
  });
2578
+ const createdSession = ptySessionsMap.get(ptySessionKey);
2579
+ if (terminalStartupInput && !isPlainShell) {
2580
+ writeTerminalStartupInput(createdSession, terminalStartupInput, 'new provider session', 4500);
2581
+ }
2480
2582
  // Handle data output
2481
2583
  shellProcess.onData((data) => {
2482
2584
  const session = ptySessionsMap.get(ptySessionKey);
@@ -2535,6 +2637,11 @@ function handleShellConnection(ws, request) {
2535
2637
  session.exitSignal = exitCode.signal || null;
2536
2638
  session.completedAt = new Date().toISOString();
2537
2639
  session.updatedAt = Date.now();
2640
+ if (session.startupInputTimerId) {
2641
+ clearTimeout(session.startupInputTimerId);
2642
+ session.startupInputTimerId = null;
2643
+ }
2644
+ session.pendingStartupInputs = [];
2538
2645
  session.pty = null;
2539
2646
  appendPtySessionBuffer(session, exitMessage);
2540
2647
  }