@pixelbyte-software/pixcode 1.53.13 → 1.53.15

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-CZReJ0_S.js"></script>
38
+ <script type="module" crossorigin src="/assets/index-BgMvphaU.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">
@@ -1106,6 +1106,7 @@ function appendPtySessionBuffer(session, data) {
1106
1106
  value = value.slice(-PTY_SESSION_BUFFER_MAX_BYTES);
1107
1107
  valueBytes = Buffer.byteLength(value, 'utf8');
1108
1108
  }
1109
+ session.totalOutputBytes = (session.totalOutputBytes || 0) + valueBytes;
1109
1110
  session.buffer.push(value);
1110
1111
  session.bufferBytes = (session.bufferBytes || 0) + valueBytes;
1111
1112
  while (session.buffer.length > 0 && session.bufferBytes > PTY_SESSION_BUFFER_MAX_BYTES) {
@@ -1115,9 +1116,33 @@ function appendPtySessionBuffer(session, data) {
1115
1116
  if (session.bufferBytes < 0)
1116
1117
  session.bufferBytes = 0;
1117
1118
  }
1119
+ function readPtySessionBufferedOutput(session, { maxChars = 12000, sinceCursor = null } = {}) {
1120
+ const rawBuffer = (session?.buffer || []).join('');
1121
+ const bufferBytes = session?.bufferBytes || Buffer.byteLength(rawBuffer, 'utf8');
1122
+ const outputCursor = session?.totalOutputBytes || bufferBytes;
1123
+ const bufferStartCursor = Math.max(0, outputCursor - bufferBytes);
1124
+ let rawOutput = rawBuffer;
1125
+ if (Number.isFinite(sinceCursor)) {
1126
+ const skipBytes = Math.max(0, sinceCursor - bufferStartCursor);
1127
+ if (skipBytes > 0) {
1128
+ rawOutput = Buffer.from(rawBuffer, 'utf8').slice(skipBytes).toString('utf8');
1129
+ }
1130
+ }
1131
+ if (rawOutput.length > maxChars) {
1132
+ rawOutput = rawOutput.slice(-maxChars);
1133
+ }
1134
+ return {
1135
+ rawOutput,
1136
+ outputCursor,
1137
+ bufferStartCursor,
1138
+ };
1139
+ }
1118
1140
  function normalizeTerminalStartupInput(input) {
1119
1141
  return `\x15${String(input || '').replace(/(?:\r\n|\r|\n)+$/u, '')}\r`;
1120
1142
  }
1143
+ function normalizeTerminalBufferedInput(input) {
1144
+ return `\x15${String(input || '').replace(/(?:\r\n|\r|\n)+$/u, '')}`;
1145
+ }
1121
1146
  function readSessionOutputForState(session, maxChars = 12000) {
1122
1147
  return stripAnsiSequences((session?.buffer || []).join('').slice(-maxChars));
1123
1148
  }
@@ -1439,6 +1464,8 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, requireProject
1439
1464
  const tabId = readPtyTarget(req.query.tabId);
1440
1465
  const sessionId = readPtyTarget(req.query.sessionId);
1441
1466
  const maxChars = Math.min(20000, Math.max(1000, Number.parseInt(String(req.query.maxChars || '12000'), 10) || 12000));
1467
+ const sinceCursorRaw = Number.parseInt(String(req.query.sinceCursor ?? ''), 10);
1468
+ const sinceCursor = Number.isFinite(sinceCursorRaw) ? Math.max(0, sinceCursorRaw) : null;
1442
1469
  if (!SHELL_CLI_PROVIDERS.has(provider)) {
1443
1470
  return res.status(400).json({ error: 'Unsupported provider' });
1444
1471
  }
@@ -1452,6 +1479,8 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, requireProject
1452
1479
  tabId,
1453
1480
  sessionId,
1454
1481
  output: '',
1482
+ outputCursor: 0,
1483
+ bufferStartCursor: 0,
1455
1484
  message: 'Multiple provider terminal sessions match this target. Pick a specific tab.',
1456
1485
  });
1457
1486
  }
@@ -1462,13 +1491,16 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, requireProject
1462
1491
  tabId,
1463
1492
  sessionId,
1464
1493
  output: '',
1494
+ outputCursor: 0,
1495
+ bufferStartCursor: 0,
1465
1496
  message: 'No active provider terminal session found for this project.',
1466
1497
  });
1467
1498
  }
1468
1499
  const matchedSession = match.session;
1469
- const rawOutput = matchedSession.buffer.join('').slice(-maxChars);
1500
+ const { rawOutput, outputCursor, bufferStartCursor, } = readPtySessionBufferedOutput(matchedSession, { maxChars, sinceCursor });
1470
1501
  const output = stripAnsiSequences(rawOutput);
1471
- const terminalState = resolveProviderTerminalState(matchedSession, provider, output);
1502
+ const fullOutput = readSessionOutputForState(matchedSession);
1503
+ const terminalState = resolveProviderTerminalState(matchedSession, provider, fullOutput);
1472
1504
  res.json({
1473
1505
  active: true,
1474
1506
  provider,
@@ -1479,6 +1511,9 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, requireProject
1479
1511
  matchStatus: match.status,
1480
1512
  ...terminalState,
1481
1513
  output,
1514
+ outputCursor,
1515
+ bufferStartCursor,
1516
+ sinceCursor,
1482
1517
  });
1483
1518
  });
1484
1519
  app.post('/api/shell/sessions/provider-input', authenticateToken, requireProjectPathAccess('useShell'), (req, res) => {
@@ -1490,6 +1525,7 @@ app.post('/api/shell/sessions/provider-input', authenticateToken, requireProject
1490
1525
  const sessionId = readPtyTarget(req.body?.sessionId);
1491
1526
  const input = typeof req.body?.input === 'string' ? req.body.input : '';
1492
1527
  const submit = req.body?.submit !== false;
1528
+ const submitMode = req.body?.submitMode === 'deferred-enter' ? 'deferred-enter' : 'inline';
1493
1529
  if (!SHELL_CLI_PROVIDERS.has(provider)) {
1494
1530
  return res.status(400).json({ error: 'Unsupported provider' });
1495
1531
  }
@@ -1525,9 +1561,33 @@ app.post('/api/shell/sessions/provider-input', authenticateToken, requireProject
1525
1561
  });
1526
1562
  }
1527
1563
  const matchedSession = match.session;
1528
- const data = submit ? normalizeTerminalStartupInput(input) : input;
1564
+ const data = submit
1565
+ ? (submitMode === 'deferred-enter' ? normalizeTerminalBufferedInput(input) : normalizeTerminalStartupInput(input))
1566
+ : input;
1567
+ const outputCursorBefore = matchedSession.totalOutputBytes || matchedSession.bufferBytes || 0;
1529
1568
  try {
1530
1569
  writeTerminalInputChunks(matchedSession.pty, data);
1570
+ if (submit && submitMode === 'deferred-enter') {
1571
+ setTimeout(() => {
1572
+ const currentSession = findProviderPtySession({
1573
+ provider,
1574
+ projectPath,
1575
+ user: req.user,
1576
+ tabId,
1577
+ sessionId,
1578
+ requireRunning: true,
1579
+ requirePty: true,
1580
+ }).session;
1581
+ try {
1582
+ writeTerminalInputChunks(currentSession?.pty, '\r');
1583
+ if (currentSession)
1584
+ currentSession.updatedAt = Date.now();
1585
+ }
1586
+ catch (error) {
1587
+ console.warn('Deferred terminal submit failed:', error?.message || error);
1588
+ }
1589
+ }, 120);
1590
+ }
1531
1591
  matchedSession.updatedAt = Date.now();
1532
1592
  res.json({
1533
1593
  ok: true,
@@ -1537,8 +1597,11 @@ app.post('/api/shell/sessions/provider-input', authenticateToken, requireProject
1537
1597
  tabId: matchedSession.tabId || null,
1538
1598
  wrote: true,
1539
1599
  submitted: submit,
1600
+ submitMode,
1540
1601
  bytes: Buffer.byteLength(data),
1541
1602
  matchStatus: match.status,
1603
+ outputCursorBefore,
1604
+ outputCursorAfter: matchedSession.totalOutputBytes || matchedSession.bufferBytes || 0,
1542
1605
  });
1543
1606
  }
1544
1607
  catch (error) {
@@ -3834,6 +3897,7 @@ function handleShellConnection(ws, request) {
3834
3897
  ws: ws,
3835
3898
  buffer: [],
3836
3899
  bufferBytes: 0,
3900
+ totalOutputBytes: 0,
3837
3901
  droppedOutputBytes: 0,
3838
3902
  timeoutId: null,
3839
3903
  userId: ownerUserId,