@pixelbyte-software/pixcode 1.50.2 → 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-cXJ8K8Bi.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
  }
@@ -331,6 +386,9 @@ function quoteBashArg(value) {
331
386
  function quotePowerShellArg(value) {
332
387
  return `"${String(value).replace(/`/g, '``').replace(/\$/g, '`$').replace(/"/g, '`"')}"`;
333
388
  }
389
+ function quoteShellArgForPlatform(value) {
390
+ return os.platform() === 'win32' ? quotePowerShellArg(value) : quoteBashArg(value);
391
+ }
334
392
  const HERMES_CLI_COMMAND_PATTERN = /^hermes(?:\s+[A-Za-z0-9._:/=@+-]+)*\s*$/;
335
393
  function isHermesCliCommand(command) {
336
394
  return typeof command === 'string' && HERMES_CLI_COMMAND_PATTERN.test(command.trim());
@@ -436,6 +494,8 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
436
494
  const projectPath = typeof req.query.projectPath === 'string' && req.query.projectPath.trim()
437
495
  ? req.query.projectPath.trim()
438
496
  : null;
497
+ const launchId = Number.parseInt(String(req.query.launchId || ''), 10);
498
+ const requestedLaunchId = Number.isFinite(launchId) && launchId > 0 ? launchId : null;
439
499
  const maxChars = Math.min(20000, Math.max(1000, Number.parseInt(String(req.query.maxChars || '12000'), 10) || 12000));
440
500
  if (!SHELL_CLI_PROVIDERS.has(provider)) {
441
501
  return res.status(400).json({ error: 'Unsupported provider' });
@@ -445,7 +505,8 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
445
505
  for (const session of ptySessionsMap.values()) {
446
506
  if (session?.provider === provider &&
447
507
  !session?.isPlainShell &&
448
- (!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath)) {
508
+ (!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath) &&
509
+ (!requestedLaunchId || session.hermesLaunchId === requestedLaunchId)) {
449
510
  if (!matchedSession || (session.updatedAt || 0) > (matchedSession.updatedAt || 0)) {
450
511
  matchedSession = session;
451
512
  }
@@ -456,18 +517,23 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
456
517
  active: false,
457
518
  provider,
458
519
  projectPath: requestedProjectPath,
520
+ launchId: requestedLaunchId,
459
521
  output: '',
460
522
  message: 'No active provider terminal session found for this project.',
461
523
  });
462
524
  }
463
525
  const rawOutput = matchedSession.buffer.join('').slice(-maxChars);
526
+ const output = stripAnsiSequences(rawOutput);
527
+ const terminalState = detectProviderTerminalState(provider, output);
464
528
  res.json({
465
529
  active: true,
466
530
  provider,
467
531
  projectPath: path.resolve(matchedSession.projectPath || os.homedir()),
468
532
  sessionId: matchedSession.sessionId || null,
533
+ launchId: matchedSession.hermesLaunchId || null,
469
534
  updatedAt: matchedSession.updatedAt || null,
470
- output: stripAnsiSequences(rawOutput),
535
+ ...terminalState,
536
+ output,
471
537
  });
472
538
  });
473
539
  // Authentication routes (public)
@@ -2074,6 +2140,12 @@ function handleShellConnection(ws, request) {
2074
2140
  const hasSession = data.hasSession;
2075
2141
  const provider = data.provider || 'claude';
2076
2142
  const initialCommand = data.initialCommand;
2143
+ const startupInput = typeof data.startupInput === 'string' && data.startupInput.trim()
2144
+ ? data.startupInput.trim()
2145
+ : null;
2146
+ const hermesLaunchId = Number.isFinite(Number(data.hermesLaunchId)) && Number(data.hermesLaunchId) > 0
2147
+ ? Number(data.hermesLaunchId)
2148
+ : null;
2077
2149
  const isPlainShell = data.isPlainShell || (!!initialCommand && !hasSession) || provider === 'plain-shell';
2078
2150
  const isHermesCliLaunch = isPlainShell && isHermesCliCommand(initialCommand);
2079
2151
  const forceNewSession = Boolean(data.forceNewSession);
@@ -2223,6 +2295,9 @@ function handleShellConnection(ws, request) {
2223
2295
  shellCommand = `${command} resume "${sessionId}" || ${command}`;
2224
2296
  }
2225
2297
  }
2298
+ else if (startupInput) {
2299
+ shellCommand = `${command} ${quoteShellArgForPlatform(startupInput)}`;
2300
+ }
2226
2301
  else {
2227
2302
  shellCommand = command;
2228
2303
  }
@@ -2347,6 +2422,7 @@ function handleShellConnection(ws, request) {
2347
2422
  timeoutId: null,
2348
2423
  projectPath,
2349
2424
  sessionId,
2425
+ hermesLaunchId,
2350
2426
  provider,
2351
2427
  isPlainShell,
2352
2428
  keepAliveUntilExit: false,