@pixelbyte-software/pixcode 1.49.7 → 1.49.9
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-Bw6PxVkB.css +32 -0
- package/dist/assets/{index-BqgTbW4j.js → index-DzGkH0cd.js} +138 -138
- package/dist/index.html +2 -2
- package/dist-server/server/index.js +5 -124
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js +128 -7
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js.map +1 -1
- package/dist-server/server/services/hermes-gateway.js +226 -1
- package/dist-server/server/services/hermes-gateway.js.map +1 -1
- package/package.json +1 -1
- package/scripts/smoke/hermes-api-install.mjs +5 -13
- package/scripts/smoke/hermes-rest-chat-api.mjs +109 -0
- package/scripts/smoke/hermes-rest-chat-live.mjs +41 -0
- package/scripts/smoke/hermes-rest-gateway.mjs +5 -0
- package/scripts/smoke/pixcode-workbench-1-48.mjs +15 -9
- package/scripts/smoke/vscode-workbench-polish.mjs +8 -2
- package/server/index.js +5 -129
- package/server/modules/orchestration/hermes/hermes.routes.ts +128 -6
- package/server/services/hermes-gateway.js +245 -1
- package/dist/assets/index-DjKDBqln.css +0 -32
package/dist/index.html
CHANGED
|
@@ -35,11 +35,11 @@
|
|
|
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-
|
|
38
|
+
<script type="module" crossorigin src="/assets/index-DzGkH0cd.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">
|
|
42
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
42
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Bw6PxVkB.css">
|
|
43
43
|
</head>
|
|
44
44
|
<body>
|
|
45
45
|
<div id="root"></div>
|
|
@@ -27,10 +27,6 @@ const SERVER_VERSION = (() => {
|
|
|
27
27
|
return '0.0.0';
|
|
28
28
|
}
|
|
29
29
|
})();
|
|
30
|
-
const HERMES_SHELL_COMMANDS = new Set([
|
|
31
|
-
'pixcode:hermes:start',
|
|
32
|
-
'pixcode:hermes:install',
|
|
33
|
-
]);
|
|
34
30
|
const DAEMON_COMMAND_CONTEXT = {
|
|
35
31
|
appRoot: APP_ROOT,
|
|
36
32
|
cliEntry: path.join(APP_ROOT, 'server', 'cli.js'),
|
|
@@ -268,12 +264,6 @@ function killProviderPtySessions(projectPath, provider) {
|
|
|
268
264
|
}
|
|
269
265
|
return killed;
|
|
270
266
|
}
|
|
271
|
-
function shellQuotePosix(value) {
|
|
272
|
-
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
273
|
-
}
|
|
274
|
-
function shellQuotePowerShell(value) {
|
|
275
|
-
return `'${String(value).replace(/'/g, "''")}'`;
|
|
276
|
-
}
|
|
277
267
|
function normalizeShellPermissionMode(value) {
|
|
278
268
|
return typeof value === 'string' ? value.trim() : '';
|
|
279
269
|
}
|
|
@@ -346,101 +336,6 @@ function getOrCreateHermesApiKey(userId) {
|
|
|
346
336
|
'terminal:launch',
|
|
347
337
|
]).apiKey;
|
|
348
338
|
}
|
|
349
|
-
function buildHermesShellCommand(kind, env) {
|
|
350
|
-
const configureScript = path.join(APP_ROOT, 'scripts', 'hermes', 'configure-pixcode-mcp.mjs');
|
|
351
|
-
const isWindows = os.platform() === 'win32';
|
|
352
|
-
const quote = isWindows ? shellQuotePowerShell : shellQuotePosix;
|
|
353
|
-
if (isWindows) {
|
|
354
|
-
const setEnv = [
|
|
355
|
-
`$env:PIXCODE_BASE_URL=${quote(env.PIXCODE_BASE_URL)}`,
|
|
356
|
-
`$env:PIXCODE_API_KEY=${quote(env.PIXCODE_API_KEY)}`,
|
|
357
|
-
`$env:PIXCODE_APP_ROOT=${quote(env.PIXCODE_APP_ROOT)}`,
|
|
358
|
-
].join('; ');
|
|
359
|
-
const resolveHermesCommand = [
|
|
360
|
-
'function Test-HermesCommand($candidate) {',
|
|
361
|
-
'if (-not $candidate) { return $false; }',
|
|
362
|
-
'try {',
|
|
363
|
-
'& $candidate --version *> $null;',
|
|
364
|
-
'return $LASTEXITCODE -eq 0;',
|
|
365
|
-
'} catch { return $false; }',
|
|
366
|
-
'}',
|
|
367
|
-
'function Resolve-HermesCommand {',
|
|
368
|
-
'$candidates = @(',
|
|
369
|
-
'$env:HERMES_CLI_PATH,',
|
|
370
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\bin\\hermes.cmd"),',
|
|
371
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\bin\\hermes.bat"),',
|
|
372
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\bin\\hermes.exe"),',
|
|
373
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\venv\\Scripts\\hermes.cmd"),',
|
|
374
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\venv\\Scripts\\hermes.bat"),',
|
|
375
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\venv\\Scripts\\hermes.exe"),',
|
|
376
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\.venv\\Scripts\\hermes.cmd"),',
|
|
377
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\.venv\\Scripts\\hermes.bat"),',
|
|
378
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\.venv\\Scripts\\hermes.exe"),',
|
|
379
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\hermes.cmd"),',
|
|
380
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\hermes.bat"),',
|
|
381
|
-
'(Join-Path $env:LOCALAPPDATA "hermes\\hermes-agent\\hermes.exe")',
|
|
382
|
-
');',
|
|
383
|
-
'foreach ($candidate in $candidates) { if ($candidate -and (Test-Path $candidate) -and (Test-HermesCommand $candidate)) { return $candidate; } }',
|
|
384
|
-
'$cmd = Get-Command hermes -ErrorAction SilentlyContinue;',
|
|
385
|
-
'if ($cmd -and (Test-HermesCommand $cmd.Source)) { return $cmd.Source; }',
|
|
386
|
-
'return $null;',
|
|
387
|
-
'}',
|
|
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(' ');
|
|
395
|
-
const installHermesIfMissing = [
|
|
396
|
-
'function Install-HermesIfMissing {',
|
|
397
|
-
'$script:HermesCmd = Resolve-HermesCommand;',
|
|
398
|
-
'if ($script:HermesCmd) { & $script:HermesCmd --version *> $null; return; }',
|
|
399
|
-
'$installer = Join-Path $env:TEMP "pixcode-hermes-install.ps1";',
|
|
400
|
-
'Invoke-WebRequest -Uri "https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1" -UseBasicParsing -OutFile $installer;',
|
|
401
|
-
'& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $installer -SkipSetup -Branch main;',
|
|
402
|
-
'if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE; }',
|
|
403
|
-
'$env:Path = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + $env:Path;',
|
|
404
|
-
'$script:HermesCmd = Resolve-HermesCommand;',
|
|
405
|
-
'if (-not $script:HermesCmd) { throw "Hermes installed, but the hermes command could not be found. Restart Pixcode or add Hermes to PATH."; }',
|
|
406
|
-
'}',
|
|
407
|
-
].join(' ');
|
|
408
|
-
if (kind === 'pixcode:hermes:install') {
|
|
409
|
-
return `${setEnv}; ${resolveHermesCommand}; ${configure}; ${installHermesIfMissing}; Install-HermesIfMissing; Invoke-PixcodeHermesConfigure`;
|
|
410
|
-
}
|
|
411
|
-
return `${setEnv}; ${resolveHermesCommand}; ${configure}; ${installHermesIfMissing}; Install-HermesIfMissing; Write-Host "Hermes Agent is starting..."; Invoke-PixcodeHermesConfigure; & $script:HermesCmd chat`;
|
|
412
|
-
}
|
|
413
|
-
const setEnv = [
|
|
414
|
-
`PIXCODE_BASE_URL=${quote(env.PIXCODE_BASE_URL)}`,
|
|
415
|
-
`PIXCODE_API_KEY=${quote(env.PIXCODE_API_KEY)}`,
|
|
416
|
-
`PIXCODE_APP_ROOT=${quote(env.PIXCODE_APP_ROOT)}`,
|
|
417
|
-
].join(' ');
|
|
418
|
-
const resolveHermesCommand = [
|
|
419
|
-
'testHermesCommand() {',
|
|
420
|
-
'[ -n "$1" ] && [ -x "$1" ] && "$1" --version >/dev/null 2>&1;',
|
|
421
|
-
'}',
|
|
422
|
-
'resolveHermesCommand() {',
|
|
423
|
-
'for candidate in "${HERMES_CLI_PATH:-}" "$HOME/.local/bin/hermes" "$HOME/.hermes/hermes-agent/venv/bin/hermes" "$HOME/.hermes/hermes-agent/.venv/bin/hermes" "/usr/local/bin/hermes" "/usr/local/lib/hermes-agent/venv/bin/hermes"; do',
|
|
424
|
-
'if testHermesCommand "$candidate"; then printf "%s\\n" "$candidate"; return 0; fi;',
|
|
425
|
-
'done;',
|
|
426
|
-
'candidate="$(command -v hermes 2>/dev/null || true)";',
|
|
427
|
-
'if testHermesCommand "$candidate"; then printf "%s\\n" "$candidate"; return 0; fi;',
|
|
428
|
-
'return 1;',
|
|
429
|
-
'}',
|
|
430
|
-
].join(' ');
|
|
431
|
-
const installHermesIfMissing = [
|
|
432
|
-
'installHermesIfMissing() {',
|
|
433
|
-
'HERMES_CMD="$(resolveHermesCommand 2>/dev/null || true)";',
|
|
434
|
-
'if [ -n "$HERMES_CMD" ]; then "$HERMES_CMD" --version >/dev/null 2>&1 || true; return 0; fi;',
|
|
435
|
-
'echo "Hermes is not installed. Use Pixcode Settings > Hermes Agent > Install or repair, then start again." >&2;',
|
|
436
|
-
'exit 127;',
|
|
437
|
-
'}',
|
|
438
|
-
].join(' ');
|
|
439
|
-
if (kind === 'pixcode:hermes:install') {
|
|
440
|
-
return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && { node ${shellQuotePosix(configureScript)} || echo "Pixcode MCP configure failed; continuing."; }`)}`;
|
|
441
|
-
}
|
|
442
|
-
return `${setEnv} sh -lc ${quote(`${resolveHermesCommand} ${installHermesIfMissing} installHermesIfMissing && printf "Hermes Agent is starting...\\n" && { node ${shellQuotePosix(configureScript)} || echo "Pixcode MCP configure failed; starting Hermes anyway."; } && exec "$HERMES_CMD" chat`)}`;
|
|
443
|
-
}
|
|
444
339
|
// Single WebSocket server that handles both paths
|
|
445
340
|
const wss = new WebSocketServer({
|
|
446
341
|
server,
|
|
@@ -2115,21 +2010,7 @@ function handleShellConnection(ws, request) {
|
|
|
2115
2010
|
const sessionId = data.sessionId;
|
|
2116
2011
|
const hasSession = data.hasSession;
|
|
2117
2012
|
const provider = data.provider || 'claude';
|
|
2118
|
-
|
|
2119
|
-
const hermesCommand = HERMES_SHELL_COMMANDS.has(initialCommand) ? initialCommand : null;
|
|
2120
|
-
const isHermesShellSession = Boolean(hermesCommand);
|
|
2121
|
-
if (hermesCommand) {
|
|
2122
|
-
const apiKey = getOrCreateHermesApiKey(request?.user?.id);
|
|
2123
|
-
if (!apiKey) {
|
|
2124
|
-
ws.send(JSON.stringify({ type: 'error', message: 'Hermes MCP could not create a Pixcode API key for this user.' }));
|
|
2125
|
-
return;
|
|
2126
|
-
}
|
|
2127
|
-
initialCommand = buildHermesShellCommand(hermesCommand, {
|
|
2128
|
-
PIXCODE_BASE_URL: resolvePublicBaseUrl(request),
|
|
2129
|
-
PIXCODE_API_KEY: apiKey,
|
|
2130
|
-
PIXCODE_APP_ROOT: APP_ROOT,
|
|
2131
|
-
});
|
|
2132
|
-
}
|
|
2013
|
+
const initialCommand = data.initialCommand;
|
|
2133
2014
|
const isPlainShell = data.isPlainShell || (!!initialCommand && !hasSession) || provider === 'plain-shell';
|
|
2134
2015
|
const forceNewSession = Boolean(data.forceNewSession);
|
|
2135
2016
|
const shellPermissionMode = normalizeShellPermissionMode(data.permissionMode);
|
|
@@ -2150,7 +2031,7 @@ function handleShellConnection(ws, request) {
|
|
|
2150
2031
|
initialCommand.includes('auth login'));
|
|
2151
2032
|
// Include command hash in session key so different commands get separate sessions
|
|
2152
2033
|
const commandSuffix = isPlainShell && initialCommand
|
|
2153
|
-
?
|
|
2034
|
+
? `_cmd_${Buffer.from(initialCommand).toString('base64').slice(0, 16)}`
|
|
2154
2035
|
: '';
|
|
2155
2036
|
// Include provider in the key so a fresh "new session" in OpenCode
|
|
2156
2037
|
// doesn't reattach to a cached Claude PTY for the same project (or
|
|
@@ -2205,7 +2086,7 @@ function handleShellConnection(ws, request) {
|
|
|
2205
2086
|
console.log('📋 Session info:', hasSession ? `Resume session ${sessionId}` : (isPlainShell ? 'Plain shell mode' : 'New session'));
|
|
2206
2087
|
console.log('🤖 Provider:', isPlainShell ? 'plain-shell' : provider);
|
|
2207
2088
|
if (initialCommand) {
|
|
2208
|
-
console.log('⚡ Initial command:',
|
|
2089
|
+
console.log('⚡ Initial command:', initialCommand || 'interactive shell');
|
|
2209
2090
|
}
|
|
2210
2091
|
// First send a welcome message
|
|
2211
2092
|
let welcomeMsg;
|
|
@@ -2362,7 +2243,7 @@ function handleShellConnection(ws, request) {
|
|
|
2362
2243
|
shellCommand = command;
|
|
2363
2244
|
}
|
|
2364
2245
|
}
|
|
2365
|
-
console.log('🔧 Executing shell command:',
|
|
2246
|
+
console.log('🔧 Executing shell command:', shellCommand || 'interactive shell');
|
|
2366
2247
|
// Use appropriate shell based on platform
|
|
2367
2248
|
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';
|
|
2368
2249
|
const shellArgs = isPlainShell && !initialCommand
|
|
@@ -2394,7 +2275,7 @@ function handleShellConnection(ws, request) {
|
|
|
2394
2275
|
sessionId,
|
|
2395
2276
|
provider,
|
|
2396
2277
|
isPlainShell,
|
|
2397
|
-
keepAliveUntilExit:
|
|
2278
|
+
keepAliveUntilExit: false,
|
|
2398
2279
|
});
|
|
2399
2280
|
// Handle data output
|
|
2400
2281
|
shellProcess.onData((data) => {
|