@pixelbyte-software/pixcode 1.50.3 → 1.50.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,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-DpdiWohD.js"></script>
38
+ <script type="module" crossorigin src="/assets/index-DYQjBZrd.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">
@@ -264,6 +264,61 @@ function killProviderPtySessions(projectPath, provider) {
264
264
  }
265
265
  return killed;
266
266
  }
267
+ function getLastRegexMatchIndex(text, pattern) {
268
+ let lastIndex = -1;
269
+ for (const match of text.matchAll(pattern)) {
270
+ lastIndex = match.index ?? lastIndex;
271
+ }
272
+ return lastIndex;
273
+ }
274
+ function detectProviderTerminalState(provider, output) {
275
+ const cleanOutput = String(output || '');
276
+ if (!cleanOutput.trim()) {
277
+ return {
278
+ terminalState: 'unknown',
279
+ isBusy: false,
280
+ terminalStateReason: 'empty_output',
281
+ };
282
+ }
283
+ if (/Process exited with code/iu.test(cleanOutput)) {
284
+ return {
285
+ terminalState: 'exited',
286
+ isBusy: false,
287
+ terminalStateReason: 'process_exit',
288
+ };
289
+ }
290
+ const lastBusy = Math.max(getLastRegexMatchIndex(cleanOutput, /(?:^|\n)\s*[•*]\s*(?:Working|Running|Thinking)\b/giu), getLastRegexMatchIndex(cleanOutput, /\bWorking\s*\([^)]*esc to interrupt[^)]*\)/giu), getLastRegexMatchIndex(cleanOutput, /\bmsg=interrupt\b/giu));
291
+ if (provider === 'codex') {
292
+ const lastPrompt = Math.max(getLastRegexMatchIndex(cleanOutput, /(?:^|\n)\s*›(?:\s|$)/gu), getLastRegexMatchIndex(cleanOutput, /(?:^|\n)\s*❯(?:\s|$)/gu));
293
+ if (lastBusy >= 0) {
294
+ const isBusy = lastPrompt <= lastBusy;
295
+ return {
296
+ terminalState: isBusy ? 'busy' : 'idle',
297
+ isBusy,
298
+ terminalStateReason: isBusy ? 'codex_busy_marker_after_prompt' : 'codex_prompt_after_busy_marker',
299
+ };
300
+ }
301
+ if (lastPrompt >= 0 && /(?:Initialized|Baseline check passed|I did not modify files|Use \/skills)/iu.test(cleanOutput)) {
302
+ return {
303
+ terminalState: 'idle',
304
+ isBusy: false,
305
+ terminalStateReason: 'codex_idle_prompt',
306
+ };
307
+ }
308
+ }
309
+ if (lastBusy >= 0) {
310
+ return {
311
+ terminalState: 'busy',
312
+ isBusy: true,
313
+ terminalStateReason: 'generic_busy_marker',
314
+ };
315
+ }
316
+ return {
317
+ terminalState: 'unknown',
318
+ isBusy: false,
319
+ terminalStateReason: 'no_known_marker',
320
+ };
321
+ }
267
322
  function normalizeShellPermissionMode(value) {
268
323
  return typeof value === 'string' ? value.trim() : '';
269
324
  }
@@ -439,6 +494,8 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
439
494
  const projectPath = typeof req.query.projectPath === 'string' && req.query.projectPath.trim()
440
495
  ? req.query.projectPath.trim()
441
496
  : null;
497
+ const launchId = Number.parseInt(String(req.query.launchId || ''), 10);
498
+ const requestedLaunchId = Number.isFinite(launchId) && launchId > 0 ? launchId : null;
442
499
  const maxChars = Math.min(20000, Math.max(1000, Number.parseInt(String(req.query.maxChars || '12000'), 10) || 12000));
443
500
  if (!SHELL_CLI_PROVIDERS.has(provider)) {
444
501
  return res.status(400).json({ error: 'Unsupported provider' });
@@ -448,7 +505,8 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
448
505
  for (const session of ptySessionsMap.values()) {
449
506
  if (session?.provider === provider &&
450
507
  !session?.isPlainShell &&
451
- (!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath)) {
508
+ (!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath) &&
509
+ (!requestedLaunchId || session.hermesLaunchId === requestedLaunchId)) {
452
510
  if (!matchedSession || (session.updatedAt || 0) > (matchedSession.updatedAt || 0)) {
453
511
  matchedSession = session;
454
512
  }
@@ -459,18 +517,23 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
459
517
  active: false,
460
518
  provider,
461
519
  projectPath: requestedProjectPath,
520
+ launchId: requestedLaunchId,
462
521
  output: '',
463
522
  message: 'No active provider terminal session found for this project.',
464
523
  });
465
524
  }
466
525
  const rawOutput = matchedSession.buffer.join('').slice(-maxChars);
526
+ const output = stripAnsiSequences(rawOutput);
527
+ const terminalState = detectProviderTerminalState(provider, output);
467
528
  res.json({
468
529
  active: true,
469
530
  provider,
470
531
  projectPath: path.resolve(matchedSession.projectPath || os.homedir()),
471
532
  sessionId: matchedSession.sessionId || null,
533
+ launchId: matchedSession.hermesLaunchId || null,
472
534
  updatedAt: matchedSession.updatedAt || null,
473
- output: stripAnsiSequences(rawOutput),
535
+ ...terminalState,
536
+ output,
474
537
  });
475
538
  });
476
539
  // Authentication routes (public)
@@ -2080,6 +2143,9 @@ function handleShellConnection(ws, request) {
2080
2143
  const startupInput = typeof data.startupInput === 'string' && data.startupInput.trim()
2081
2144
  ? data.startupInput.trim()
2082
2145
  : null;
2146
+ const hermesLaunchId = Number.isFinite(Number(data.hermesLaunchId)) && Number(data.hermesLaunchId) > 0
2147
+ ? Number(data.hermesLaunchId)
2148
+ : null;
2083
2149
  const isPlainShell = data.isPlainShell || (!!initialCommand && !hasSession) || provider === 'plain-shell';
2084
2150
  const isHermesCliLaunch = isPlainShell && isHermesCliCommand(initialCommand);
2085
2151
  const forceNewSession = Boolean(data.forceNewSession);
@@ -2356,6 +2422,7 @@ function handleShellConnection(ws, request) {
2356
2422
  timeoutId: null,
2357
2423
  projectPath,
2358
2424
  sessionId,
2425
+ hermesLaunchId,
2359
2426
  provider,
2360
2427
  isPlainShell,
2361
2428
  keepAliveUntilExit: false,