@pixelbyte-software/pixcode 1.49.3 → 1.49.5
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/assets/{index-DexGC0hs.js → index-77u-_XIT.js} +2 -2
- package/dist/assets/index-DjKDBqln.css +32 -0
- package/dist/index.html +2 -2
- package/dist-server/server/index.js +37 -15
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/services/hermes-install-jobs.js +6 -2
- package/dist-server/server/services/hermes-install-jobs.js.map +1 -1
- package/package.json +1 -1
- package/scripts/smoke/hermes-api-install.mjs +11 -0
- package/scripts/smoke/vscode-workbench-polish.mjs +25 -0
- package/server/index.js +38 -15
- package/server/services/hermes-install-jobs.js +7 -2
- package/dist/assets/index-ntmmehps.css +0 -32
|
@@ -77,6 +77,7 @@ import { restoreBotFromConfig } from './services/telegram/bot.js';
|
|
|
77
77
|
import { ensurePortOpen } from './utils/port-access.js';
|
|
78
78
|
import { applyAllStoredCredentialsToEnv, } from './services/provider-credentials.js';
|
|
79
79
|
import { primeCliBinPath } from './services/install-jobs.js';
|
|
80
|
+
import { buildHermesPathEnv, primeHermesPath } from './services/hermes-install-jobs.js';
|
|
80
81
|
import { startEnabledPluginServers, stopAllPlugins, getPluginPort } from './utils/plugin-process-manager.js';
|
|
81
82
|
import { initializeDatabase, sessionNamesDb, applyCustomSessionNames, apiKeysDb } from './database/db.js';
|
|
82
83
|
import { setNotificationWebSocketServer } from './services/notification-orchestrator.js';
|
|
@@ -348,7 +349,6 @@ function buildHermesShellCommand(kind, env) {
|
|
|
348
349
|
const configureScript = path.join(APP_ROOT, 'scripts', 'hermes', 'configure-pixcode-mcp.mjs');
|
|
349
350
|
const isWindows = os.platform() === 'win32';
|
|
350
351
|
const quote = isWindows ? shellQuotePowerShell : shellQuotePosix;
|
|
351
|
-
const configure = `node ${quote(configureScript)}`;
|
|
352
352
|
if (isWindows) {
|
|
353
353
|
const setEnv = [
|
|
354
354
|
`$env:PIXCODE_BASE_URL=${quote(env.PIXCODE_BASE_URL)}`,
|
|
@@ -385,10 +385,16 @@ function buildHermesShellCommand(kind, env) {
|
|
|
385
385
|
'return $null;',
|
|
386
386
|
'}',
|
|
387
387
|
].join(' ');
|
|
388
|
+
const configure = [
|
|
389
|
+
'function Invoke-PixcodeHermesConfigure {',
|
|
390
|
+
`& node ${quote(configureScript)};`,
|
|
391
|
+
'if ($LASTEXITCODE -ne 0) { Write-Warning "Pixcode MCP configure failed; starting Hermes anyway."; $global:LASTEXITCODE = 0; }',
|
|
392
|
+
'}',
|
|
393
|
+
].join(' ');
|
|
388
394
|
const installHermesIfMissing = [
|
|
389
395
|
'function Install-HermesIfMissing {',
|
|
390
396
|
'$script:HermesCmd = Resolve-HermesCommand;',
|
|
391
|
-
'if ($script:HermesCmd) {
|
|
397
|
+
'if ($script:HermesCmd) { & $script:HermesCmd --version *> $null; return; }',
|
|
392
398
|
'$installer = Join-Path $env:TEMP "pixcode-hermes-install.ps1";',
|
|
393
399
|
'Invoke-WebRequest -Uri "https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1" -UseBasicParsing -OutFile $installer;',
|
|
394
400
|
'& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $installer -SkipSetup -Branch main;',
|
|
@@ -399,9 +405,9 @@ function buildHermesShellCommand(kind, env) {
|
|
|
399
405
|
'}',
|
|
400
406
|
].join(' ');
|
|
401
407
|
if (kind === 'pixcode:hermes:install') {
|
|
402
|
-
return `${setEnv}; ${resolveHermesCommand}; ${installHermesIfMissing}; Install-HermesIfMissing;
|
|
408
|
+
return `${setEnv}; ${resolveHermesCommand}; ${configure}; ${installHermesIfMissing}; Install-HermesIfMissing; Invoke-PixcodeHermesConfigure`;
|
|
403
409
|
}
|
|
404
|
-
return `${setEnv}; ${resolveHermesCommand}; ${installHermesIfMissing}; Install-HermesIfMissing;
|
|
410
|
+
return `${setEnv}; ${resolveHermesCommand}; ${configure}; ${installHermesIfMissing}; Install-HermesIfMissing; Invoke-PixcodeHermesConfigure; & $script:HermesCmd`;
|
|
405
411
|
}
|
|
406
412
|
const setEnv = [
|
|
407
413
|
`PIXCODE_BASE_URL=${quote(env.PIXCODE_BASE_URL)}`,
|
|
@@ -424,15 +430,15 @@ function buildHermesShellCommand(kind, env) {
|
|
|
424
430
|
const installHermesIfMissing = [
|
|
425
431
|
'installHermesIfMissing() {',
|
|
426
432
|
'HERMES_CMD="$(resolveHermesCommand 2>/dev/null || true)";',
|
|
427
|
-
'if [ -n "$HERMES_CMD" ]; then
|
|
433
|
+
'if [ -n "$HERMES_CMD" ]; then "$HERMES_CMD" --version >/dev/null 2>&1 || true; return 0; fi;',
|
|
428
434
|
'echo "Hermes is not installed. Use Pixcode Settings > Hermes Agent > Install or repair, then start again." >&2;',
|
|
429
435
|
'exit 127;',
|
|
430
436
|
'}',
|
|
431
437
|
].join(' ');
|
|
432
438
|
if (kind === 'pixcode:hermes:install') {
|
|
433
|
-
return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && node ${shellQuotePosix(configureScript)}`)}`;
|
|
439
|
+
return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && { node ${shellQuotePosix(configureScript)} || echo "Pixcode MCP configure failed; continuing."; }`)}`;
|
|
434
440
|
}
|
|
435
|
-
return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && node ${shellQuotePosix(configureScript)}
|
|
441
|
+
return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && { node ${shellQuotePosix(configureScript)} || echo "Pixcode MCP configure failed; starting Hermes anyway."; } && "$HERMES_CMD"`)}`;
|
|
436
442
|
}
|
|
437
443
|
// Single WebSocket server that handles both paths
|
|
438
444
|
const wss = new WebSocketServer({
|
|
@@ -2110,6 +2116,7 @@ function handleShellConnection(ws, request) {
|
|
|
2110
2116
|
const provider = data.provider || 'claude';
|
|
2111
2117
|
let initialCommand = data.initialCommand;
|
|
2112
2118
|
const hermesCommand = HERMES_SHELL_COMMANDS.has(initialCommand) ? initialCommand : null;
|
|
2119
|
+
const isHermesShellSession = Boolean(hermesCommand);
|
|
2113
2120
|
if (hermesCommand) {
|
|
2114
2121
|
const apiKey = getOrCreateHermesApiKey(request?.user?.id);
|
|
2115
2122
|
if (!apiKey) {
|
|
@@ -2142,7 +2149,7 @@ function handleShellConnection(ws, request) {
|
|
|
2142
2149
|
initialCommand.includes('auth login'));
|
|
2143
2150
|
// Include command hash in session key so different commands get separate sessions
|
|
2144
2151
|
const commandSuffix = isPlainShell && initialCommand
|
|
2145
|
-
? `_cmd_${Buffer.from(initialCommand).toString('base64').slice(0, 16)}`
|
|
2152
|
+
? (isHermesShellSession ? '_hermes' : `_cmd_${Buffer.from(initialCommand).toString('base64').slice(0, 16)}`)
|
|
2146
2153
|
: '';
|
|
2147
2154
|
// Include provider in the key so a fresh "new session" in OpenCode
|
|
2148
2155
|
// doesn't reattach to a cached Claude PTY for the same project (or
|
|
@@ -2364,17 +2371,17 @@ function handleShellConnection(ws, request) {
|
|
|
2364
2371
|
const termCols = data.cols || 80;
|
|
2365
2372
|
const termRows = data.rows || 24;
|
|
2366
2373
|
console.log('📐 Using terminal dimensions:', termCols, 'x', termRows);
|
|
2374
|
+
const shellEnv = buildHermesPathEnv(process.env, {
|
|
2375
|
+
TERM: 'xterm-256color',
|
|
2376
|
+
COLORTERM: 'truecolor',
|
|
2377
|
+
FORCE_COLOR: '3',
|
|
2378
|
+
});
|
|
2367
2379
|
shellProcess = pty.spawn(shell, shellArgs, {
|
|
2368
2380
|
name: 'xterm-256color',
|
|
2369
2381
|
cols: termCols,
|
|
2370
2382
|
rows: termRows,
|
|
2371
2383
|
cwd: resolvedProjectPath,
|
|
2372
|
-
env:
|
|
2373
|
-
...process.env,
|
|
2374
|
-
TERM: 'xterm-256color',
|
|
2375
|
-
COLORTERM: 'truecolor',
|
|
2376
|
-
FORCE_COLOR: '3'
|
|
2377
|
-
}
|
|
2384
|
+
env: shellEnv,
|
|
2378
2385
|
});
|
|
2379
2386
|
console.log('🟢 Shell process started with PTY, PID:', shellProcess.pid);
|
|
2380
2387
|
ptySessionsMap.set(ptySessionKey, {
|
|
@@ -2385,7 +2392,8 @@ function handleShellConnection(ws, request) {
|
|
|
2385
2392
|
projectPath,
|
|
2386
2393
|
sessionId,
|
|
2387
2394
|
provider,
|
|
2388
|
-
isPlainShell
|
|
2395
|
+
isPlainShell,
|
|
2396
|
+
keepAliveUntilExit: isHermesShellSession,
|
|
2389
2397
|
});
|
|
2390
2398
|
// Handle data output
|
|
2391
2399
|
shellProcess.onData((data) => {
|
|
@@ -2497,6 +2505,11 @@ function handleShellConnection(ws, request) {
|
|
|
2497
2505
|
if (ptySessionKey) {
|
|
2498
2506
|
const session = ptySessionsMap.get(ptySessionKey);
|
|
2499
2507
|
if (session) {
|
|
2508
|
+
if (session.keepAliveUntilExit) {
|
|
2509
|
+
console.log('⏳ PTY session kept alive until process exit:', ptySessionKey);
|
|
2510
|
+
session.ws = null;
|
|
2511
|
+
return;
|
|
2512
|
+
}
|
|
2500
2513
|
console.log('⏳ PTY session kept alive, will timeout in 30 minutes:', ptySessionKey);
|
|
2501
2514
|
session.ws = null;
|
|
2502
2515
|
session.timeoutId = setTimeout(() => {
|
|
@@ -3104,6 +3117,15 @@ async function startServer() {
|
|
|
3104
3117
|
catch (err) {
|
|
3105
3118
|
console.warn('[install-jobs] Failed to prime CLI bin path:', err?.message || err);
|
|
3106
3119
|
}
|
|
3120
|
+
// Prime Hermes' known install locations separately so the project
|
|
3121
|
+
// terminal can resolve `hermes` even when Windows has not refreshed the
|
|
3122
|
+
// user's PATH for the current Pixcode process.
|
|
3123
|
+
try {
|
|
3124
|
+
primeHermesPath();
|
|
3125
|
+
}
|
|
3126
|
+
catch (err) {
|
|
3127
|
+
console.warn('[install-jobs] Failed to prime Hermes bin path:', err?.message || err);
|
|
3128
|
+
}
|
|
3107
3129
|
// Restore any previously-configured Telegram bot. This is best-effort:
|
|
3108
3130
|
// a bad token or network blip should warn, not crash the server.
|
|
3109
3131
|
restoreBotFromConfig().catch((err) => {
|