@pixelbyte-software/pixcode 1.49.4 → 1.49.6

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.
@@ -340,6 +340,7 @@ function getOrCreateHermesApiKey(userId) {
340
340
  }
341
341
  return apiKeysDb.createApiKey(userId, 'Hermes Agent MCP', [
342
342
  'hermes:mcp',
343
+ 'hermes:gateway',
343
344
  'projects:read',
344
345
  'providers:read',
345
346
  'terminal:launch',
@@ -349,7 +350,6 @@ function buildHermesShellCommand(kind, env) {
349
350
  const configureScript = path.join(APP_ROOT, 'scripts', 'hermes', 'configure-pixcode-mcp.mjs');
350
351
  const isWindows = os.platform() === 'win32';
351
352
  const quote = isWindows ? shellQuotePowerShell : shellQuotePosix;
352
- const configure = `node ${quote(configureScript)}`;
353
353
  if (isWindows) {
354
354
  const setEnv = [
355
355
  `$env:PIXCODE_BASE_URL=${quote(env.PIXCODE_BASE_URL)}`,
@@ -386,10 +386,16 @@ function buildHermesShellCommand(kind, env) {
386
386
  'return $null;',
387
387
  '}',
388
388
  ].join(' ');
389
+ const configure = [
390
+ 'function Invoke-PixcodeHermesConfigure {',
391
+ `& node ${quote(configureScript)};`,
392
+ 'if ($LASTEXITCODE -ne 0) { Write-Warning "Pixcode MCP configure failed; starting Hermes anyway."; $global:LASTEXITCODE = 0; }',
393
+ '}',
394
+ ].join(' ');
389
395
  const installHermesIfMissing = [
390
396
  'function Install-HermesIfMissing {',
391
397
  '$script:HermesCmd = Resolve-HermesCommand;',
392
- 'if ($script:HermesCmd) { Write-Host "Hermes already installed:"; & $script:HermesCmd --version; return; }',
398
+ 'if ($script:HermesCmd) { & $script:HermesCmd --version *> $null; return; }',
393
399
  '$installer = Join-Path $env:TEMP "pixcode-hermes-install.ps1";',
394
400
  'Invoke-WebRequest -Uri "https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1" -UseBasicParsing -OutFile $installer;',
395
401
  '& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $installer -SkipSetup -Branch main;',
@@ -400,9 +406,9 @@ function buildHermesShellCommand(kind, env) {
400
406
  '}',
401
407
  ].join(' ');
402
408
  if (kind === 'pixcode:hermes:install') {
403
- return `${setEnv}; ${resolveHermesCommand}; ${installHermesIfMissing}; Install-HermesIfMissing; ${configure}`;
409
+ return `${setEnv}; ${resolveHermesCommand}; ${configure}; ${installHermesIfMissing}; Install-HermesIfMissing; Invoke-PixcodeHermesConfigure`;
404
410
  }
405
- return `${setEnv}; ${resolveHermesCommand}; ${installHermesIfMissing}; Install-HermesIfMissing; ${configure}; & $script:HermesCmd chat --toolsets "hermes-cli,mcp-pixcode"`;
411
+ return `${setEnv}; ${resolveHermesCommand}; ${configure}; ${installHermesIfMissing}; Install-HermesIfMissing; Invoke-PixcodeHermesConfigure; & $script:HermesCmd`;
406
412
  }
407
413
  const setEnv = [
408
414
  `PIXCODE_BASE_URL=${quote(env.PIXCODE_BASE_URL)}`,
@@ -425,15 +431,15 @@ function buildHermesShellCommand(kind, env) {
425
431
  const installHermesIfMissing = [
426
432
  'installHermesIfMissing() {',
427
433
  'HERMES_CMD="$(resolveHermesCommand 2>/dev/null || true)";',
428
- 'if [ -n "$HERMES_CMD" ]; then echo "Hermes already installed:"; "$HERMES_CMD" --version 2>/dev/null || true; return 0; fi;',
434
+ 'if [ -n "$HERMES_CMD" ]; then "$HERMES_CMD" --version >/dev/null 2>&1 || true; return 0; fi;',
429
435
  'echo "Hermes is not installed. Use Pixcode Settings > Hermes Agent > Install or repair, then start again." >&2;',
430
436
  'exit 127;',
431
437
  '}',
432
438
  ].join(' ');
433
439
  if (kind === 'pixcode:hermes:install') {
434
- return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && node ${shellQuotePosix(configureScript)}`)}`;
440
+ return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && { node ${shellQuotePosix(configureScript)} || echo "Pixcode MCP configure failed; continuing."; }`)}`;
435
441
  }
436
- return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && node ${shellQuotePosix(configureScript)} && "$HERMES_CMD" chat --toolsets "hermes-cli,mcp-pixcode"`)}`;
442
+ return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && { node ${shellQuotePosix(configureScript)} || echo "Pixcode MCP configure failed; starting Hermes anyway."; } && "$HERMES_CMD"`)}`;
437
443
  }
438
444
  // Single WebSocket server that handles both paths
439
445
  const wss = new WebSocketServer({
@@ -2111,6 +2117,7 @@ function handleShellConnection(ws, request) {
2111
2117
  const provider = data.provider || 'claude';
2112
2118
  let initialCommand = data.initialCommand;
2113
2119
  const hermesCommand = HERMES_SHELL_COMMANDS.has(initialCommand) ? initialCommand : null;
2120
+ const isHermesShellSession = Boolean(hermesCommand);
2114
2121
  if (hermesCommand) {
2115
2122
  const apiKey = getOrCreateHermesApiKey(request?.user?.id);
2116
2123
  if (!apiKey) {
@@ -2143,7 +2150,7 @@ function handleShellConnection(ws, request) {
2143
2150
  initialCommand.includes('auth login'));
2144
2151
  // Include command hash in session key so different commands get separate sessions
2145
2152
  const commandSuffix = isPlainShell && initialCommand
2146
- ? `_cmd_${Buffer.from(initialCommand).toString('base64').slice(0, 16)}`
2153
+ ? (isHermesShellSession ? '_hermes' : `_cmd_${Buffer.from(initialCommand).toString('base64').slice(0, 16)}`)
2147
2154
  : '';
2148
2155
  // Include provider in the key so a fresh "new session" in OpenCode
2149
2156
  // doesn't reattach to a cached Claude PTY for the same project (or
@@ -2386,7 +2393,8 @@ function handleShellConnection(ws, request) {
2386
2393
  projectPath,
2387
2394
  sessionId,
2388
2395
  provider,
2389
- isPlainShell
2396
+ isPlainShell,
2397
+ keepAliveUntilExit: isHermesShellSession,
2390
2398
  });
2391
2399
  // Handle data output
2392
2400
  shellProcess.onData((data) => {
@@ -2498,6 +2506,11 @@ function handleShellConnection(ws, request) {
2498
2506
  if (ptySessionKey) {
2499
2507
  const session = ptySessionsMap.get(ptySessionKey);
2500
2508
  if (session) {
2509
+ if (session.keepAliveUntilExit) {
2510
+ console.log('⏳ PTY session kept alive until process exit:', ptySessionKey);
2511
+ session.ws = null;
2512
+ return;
2513
+ }
2501
2514
  console.log('⏳ PTY session kept alive, will timeout in 30 minutes:', ptySessionKey);
2502
2515
  session.ws = null;
2503
2516
  session.timeoutId = setTimeout(() => {