@pixelbyte-software/pixcode 1.49.0 → 1.49.2
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-B8TbMftk.css +32 -0
- package/dist/assets/{index-58IIiyST.js → index-BsQAPOnf.js} +172 -172
- package/dist/index.html +2 -2
- package/dist-server/server/gemini-cli.js +5 -1
- package/dist-server/server/gemini-cli.js.map +1 -1
- package/dist-server/server/index.js +119 -17
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js +128 -1
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js.map +1 -1
- package/dist-server/server/qwen-code-cli.js +5 -1
- package/dist-server/server/qwen-code-cli.js.map +1 -1
- package/dist-server/server/services/hermes-install-jobs.js +417 -0
- package/dist-server/server/services/hermes-install-jobs.js.map +1 -0
- package/package.json +1 -1
- package/scripts/smoke/hermes-api-install.mjs +29 -0
- package/scripts/smoke/pixcode-workbench-1-48.mjs +23 -0
- package/server/gemini-cli.js +7 -1
- package/server/index.js +129 -17
- package/server/modules/orchestration/hermes/hermes.routes.ts +144 -2
- package/server/qwen-code-cli.js +7 -1
- package/server/services/hermes-install-jobs.js +467 -0
- package/dist/assets/index-BpUexHb8.css +0 -32
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { EventEmitter } from 'node:events';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import spawn from 'cross-spawn';
|
|
7
|
+
import { buildCliSpawnEnv, findExecutableOnPath } from './install-jobs.js';
|
|
8
|
+
const POSIX_INSTALLER_URL = 'https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh';
|
|
9
|
+
const WINDOWS_INSTALLER_URL = 'https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1';
|
|
10
|
+
const FINISHED_TTL_MS = 10 * 60 * 1000;
|
|
11
|
+
const HARD_TIMEOUT_MS = 20 * 60 * 1000;
|
|
12
|
+
const jobs = new Map();
|
|
13
|
+
function pathSeparator() {
|
|
14
|
+
return process.platform === 'win32' ? ';' : ':';
|
|
15
|
+
}
|
|
16
|
+
function splitPathList(value) {
|
|
17
|
+
return String(value || '').split(pathSeparator()).map((entry) => entry.trim()).filter(Boolean);
|
|
18
|
+
}
|
|
19
|
+
function mergePathEntries(env, preferredEntries) {
|
|
20
|
+
const existing = splitPathList(env.PATH || env.Path || '');
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
const merged = [];
|
|
23
|
+
for (const entry of [...preferredEntries, ...existing]) {
|
|
24
|
+
if (!entry)
|
|
25
|
+
continue;
|
|
26
|
+
const key = path.resolve(entry);
|
|
27
|
+
if (seen.has(key))
|
|
28
|
+
continue;
|
|
29
|
+
seen.add(key);
|
|
30
|
+
merged.push(entry);
|
|
31
|
+
}
|
|
32
|
+
const nextPath = merged.join(pathSeparator());
|
|
33
|
+
env.PATH = nextPath;
|
|
34
|
+
if ('Path' in env || process.platform === 'win32')
|
|
35
|
+
env.Path = nextPath;
|
|
36
|
+
return env;
|
|
37
|
+
}
|
|
38
|
+
function knownHermesBinDirs(env = process.env) {
|
|
39
|
+
const home = os.homedir();
|
|
40
|
+
if (process.platform === 'win32') {
|
|
41
|
+
const localAppData = env.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
|
|
42
|
+
return [
|
|
43
|
+
...(env.HERMES_INSTALL_DIR ? [
|
|
44
|
+
path.join(env.HERMES_INSTALL_DIR, 'venv', 'Scripts'),
|
|
45
|
+
path.join(env.HERMES_INSTALL_DIR, '.venv', 'Scripts'),
|
|
46
|
+
env.HERMES_INSTALL_DIR,
|
|
47
|
+
] : []),
|
|
48
|
+
...(env.HERMES_HOME ? [
|
|
49
|
+
path.join(env.HERMES_HOME, 'hermes-agent', 'venv', 'Scripts'),
|
|
50
|
+
path.join(env.HERMES_HOME, 'hermes-agent', '.venv', 'Scripts'),
|
|
51
|
+
path.join(env.HERMES_HOME, 'hermes-agent'),
|
|
52
|
+
] : []),
|
|
53
|
+
path.join(localAppData, 'hermes', 'bin'),
|
|
54
|
+
path.join(localAppData, 'hermes', 'hermes-agent'),
|
|
55
|
+
path.join(localAppData, 'hermes', 'hermes-agent', 'venv', 'Scripts'),
|
|
56
|
+
path.join(localAppData, 'hermes', 'hermes-agent', '.venv', 'Scripts'),
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
return [
|
|
60
|
+
...(env.HERMES_INSTALL_DIR ? [
|
|
61
|
+
path.join(env.HERMES_INSTALL_DIR, 'venv', 'bin'),
|
|
62
|
+
path.join(env.HERMES_INSTALL_DIR, '.venv', 'bin'),
|
|
63
|
+
] : []),
|
|
64
|
+
...(env.HERMES_HOME ? [
|
|
65
|
+
path.join(env.HERMES_HOME, 'hermes-agent', 'venv', 'bin'),
|
|
66
|
+
path.join(env.HERMES_HOME, 'hermes-agent', '.venv', 'bin'),
|
|
67
|
+
] : []),
|
|
68
|
+
path.join(home, '.local', 'bin'),
|
|
69
|
+
path.join(home, '.hermes', 'hermes-agent', 'venv', 'bin'),
|
|
70
|
+
path.join(home, '.hermes', 'hermes-agent', '.venv', 'bin'),
|
|
71
|
+
'/usr/local/bin',
|
|
72
|
+
'/usr/local/lib/hermes-agent/venv/bin',
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
function buildHermesEnv(baseEnv = process.env, extras = {}) {
|
|
76
|
+
const env = mergePathEntries(buildCliSpawnEnv(baseEnv), knownHermesBinDirs(baseEnv));
|
|
77
|
+
for (const [key, value] of Object.entries(extras)) {
|
|
78
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
79
|
+
env[key] = value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
delete env.PYTHONPATH;
|
|
83
|
+
delete env.PYTHONHOME;
|
|
84
|
+
return env;
|
|
85
|
+
}
|
|
86
|
+
export function primeHermesPath(env = process.env) {
|
|
87
|
+
const next = buildHermesEnv(env);
|
|
88
|
+
env.PATH = next.PATH;
|
|
89
|
+
if ('Path' in env || next.Path)
|
|
90
|
+
env.Path = next.Path || next.PATH;
|
|
91
|
+
}
|
|
92
|
+
export function hermesCommandCandidates(env = process.env) {
|
|
93
|
+
const candidates = [];
|
|
94
|
+
const hermesEnv = buildHermesEnv(env);
|
|
95
|
+
const resolved = findExecutableOnPath('hermes', hermesEnv);
|
|
96
|
+
if (env.HERMES_CLI_PATH)
|
|
97
|
+
candidates.push(env.HERMES_CLI_PATH);
|
|
98
|
+
if (resolved)
|
|
99
|
+
candidates.push(resolved);
|
|
100
|
+
candidates.push('hermes');
|
|
101
|
+
if (process.platform === 'win32') {
|
|
102
|
+
const localAppData = env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
103
|
+
candidates.push(...(env.HERMES_INSTALL_DIR ? [
|
|
104
|
+
path.join(env.HERMES_INSTALL_DIR, 'venv', 'Scripts', 'hermes.exe'),
|
|
105
|
+
path.join(env.HERMES_INSTALL_DIR, '.venv', 'Scripts', 'hermes.exe'),
|
|
106
|
+
path.join(env.HERMES_INSTALL_DIR, 'hermes.exe'),
|
|
107
|
+
] : []), ...(env.HERMES_HOME ? [
|
|
108
|
+
path.join(env.HERMES_HOME, 'hermes-agent', 'venv', 'Scripts', 'hermes.exe'),
|
|
109
|
+
path.join(env.HERMES_HOME, 'hermes-agent', '.venv', 'Scripts', 'hermes.exe'),
|
|
110
|
+
path.join(env.HERMES_HOME, 'hermes-agent', 'hermes.exe'),
|
|
111
|
+
] : []), path.join(localAppData, 'hermes', 'hermes-agent', 'venv', 'Scripts', 'hermes.exe'), path.join(localAppData, 'hermes', 'hermes-agent', '.venv', 'Scripts', 'hermes.exe'), path.join(localAppData, 'hermes', 'hermes-agent', 'hermes.exe'));
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
candidates.push(...(env.HERMES_INSTALL_DIR ? [
|
|
115
|
+
path.join(env.HERMES_INSTALL_DIR, 'venv', 'bin', 'hermes'),
|
|
116
|
+
path.join(env.HERMES_INSTALL_DIR, '.venv', 'bin', 'hermes'),
|
|
117
|
+
] : []), ...(env.HERMES_HOME ? [
|
|
118
|
+
path.join(env.HERMES_HOME, 'hermes-agent', 'venv', 'bin', 'hermes'),
|
|
119
|
+
path.join(env.HERMES_HOME, 'hermes-agent', '.venv', 'bin', 'hermes'),
|
|
120
|
+
] : []), path.join(os.homedir(), '.local', 'bin', 'hermes'), path.join(os.homedir(), '.hermes', 'hermes-agent', 'venv', 'bin', 'hermes'), path.join(os.homedir(), '.hermes', 'hermes-agent', '.venv', 'bin', 'hermes'), '/usr/local/bin/hermes', '/usr/local/lib/hermes-agent/venv/bin/hermes');
|
|
121
|
+
}
|
|
122
|
+
return [...new Set(candidates.filter(Boolean))];
|
|
123
|
+
}
|
|
124
|
+
export function readHermesInstallStatus(env = process.env) {
|
|
125
|
+
const hermesEnv = buildHermesEnv(env);
|
|
126
|
+
for (const candidate of hermesCommandCandidates(hermesEnv)) {
|
|
127
|
+
const isBareCommand = candidate === 'hermes';
|
|
128
|
+
if (!isBareCommand && !fs.existsSync(candidate)) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const result = spawn.sync(candidate, ['--version'], {
|
|
132
|
+
encoding: 'utf8',
|
|
133
|
+
env: hermesEnv,
|
|
134
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
135
|
+
timeout: 5000,
|
|
136
|
+
windowsHide: true,
|
|
137
|
+
});
|
|
138
|
+
if (!result.error && result.status === 0) {
|
|
139
|
+
const version = `${result.stdout || result.stderr || ''}`.trim() || null;
|
|
140
|
+
return {
|
|
141
|
+
installed: true,
|
|
142
|
+
command: candidate,
|
|
143
|
+
version,
|
|
144
|
+
error: null,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
installed: false,
|
|
150
|
+
command: null,
|
|
151
|
+
version: null,
|
|
152
|
+
error: 'Hermes Agent CLI is not installed or is not on PATH.',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async function downloadHermesInstaller(url, targetPath, appendLog) {
|
|
156
|
+
appendLog('meta', `Downloading ${url}\n`);
|
|
157
|
+
try {
|
|
158
|
+
const response = await fetch(url);
|
|
159
|
+
if (!response.ok) {
|
|
160
|
+
throw new Error(`HTTP ${response.status}`);
|
|
161
|
+
}
|
|
162
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
163
|
+
await fs.promises.writeFile(targetPath, bytes, { mode: 0o700 });
|
|
164
|
+
appendLog('meta', `Downloaded installer to ${targetPath}\n`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
appendLog('stderr', `Node download failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
169
|
+
appendLog('meta', 'Retrying installer download with the system download tool...\n');
|
|
170
|
+
}
|
|
171
|
+
await downloadHermesInstallerWithNativeTool(url, targetPath, appendLog);
|
|
172
|
+
if (process.platform !== 'win32') {
|
|
173
|
+
await fs.promises.chmod(targetPath, 0o700);
|
|
174
|
+
}
|
|
175
|
+
appendLog('meta', `Downloaded installer to ${targetPath}\n`);
|
|
176
|
+
}
|
|
177
|
+
function downloadHermesInstallerWithNativeTool(url, targetPath, appendLog) {
|
|
178
|
+
const isWindows = process.platform === 'win32';
|
|
179
|
+
const command = isWindows ? 'powershell.exe' : 'curl';
|
|
180
|
+
const args = isWindows
|
|
181
|
+
? [
|
|
182
|
+
'-NoProfile',
|
|
183
|
+
'-ExecutionPolicy',
|
|
184
|
+
'Bypass',
|
|
185
|
+
'-Command',
|
|
186
|
+
`$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri ${JSON.stringify(url)} -UseBasicParsing -OutFile ${JSON.stringify(targetPath)}`,
|
|
187
|
+
]
|
|
188
|
+
: ['-fL', '--retry', '2', '--connect-timeout', '20', '-o', targetPath, url];
|
|
189
|
+
appendLog('meta', `$ ${command} ${args.join(' ')}\n`);
|
|
190
|
+
return new Promise((resolve, reject) => {
|
|
191
|
+
const child = spawn(command, args, {
|
|
192
|
+
env: buildHermesEnv(process.env),
|
|
193
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
194
|
+
windowsHide: true,
|
|
195
|
+
});
|
|
196
|
+
child.stdout.on('data', (buf) => appendLog('stdout', buf.toString()));
|
|
197
|
+
child.stderr.on('data', (buf) => appendLog('stderr', buf.toString()));
|
|
198
|
+
child.on('error', reject);
|
|
199
|
+
child.on('close', (code, signal) => {
|
|
200
|
+
if (signal) {
|
|
201
|
+
reject(new Error(`${command} killed by ${signal}`));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (code !== 0) {
|
|
205
|
+
reject(new Error(`${command} exited with code ${code}`));
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
resolve();
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
function createJob(options) {
|
|
213
|
+
const id = randomUUID();
|
|
214
|
+
const emitter = new EventEmitter();
|
|
215
|
+
emitter.setMaxListeners(20);
|
|
216
|
+
return {
|
|
217
|
+
id,
|
|
218
|
+
provider: 'hermes',
|
|
219
|
+
status: 'running',
|
|
220
|
+
startedAt: new Date().toISOString(),
|
|
221
|
+
finishedAt: null,
|
|
222
|
+
exitCode: null,
|
|
223
|
+
error: null,
|
|
224
|
+
logs: [],
|
|
225
|
+
emitter,
|
|
226
|
+
child: null,
|
|
227
|
+
timer: null,
|
|
228
|
+
binaryPath: null,
|
|
229
|
+
options,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function appendLog(job, stream, chunk) {
|
|
233
|
+
const entry = { stream, chunk, at: Date.now() };
|
|
234
|
+
job.logs.push(entry);
|
|
235
|
+
if (job.logs.length > 2500) {
|
|
236
|
+
job.logs.splice(0, job.logs.length - 2500);
|
|
237
|
+
}
|
|
238
|
+
job.emitter.emit('log', entry);
|
|
239
|
+
}
|
|
240
|
+
function finishJob(job, status, payload = {}) {
|
|
241
|
+
if (job.status !== 'running')
|
|
242
|
+
return;
|
|
243
|
+
job.status = status;
|
|
244
|
+
job.finishedAt = new Date().toISOString();
|
|
245
|
+
if (typeof payload.exitCode === 'number')
|
|
246
|
+
job.exitCode = payload.exitCode;
|
|
247
|
+
if (payload.error)
|
|
248
|
+
job.error = payload.error;
|
|
249
|
+
if (payload.binaryPath)
|
|
250
|
+
job.binaryPath = payload.binaryPath;
|
|
251
|
+
job.emitter.emit('done', snapshotHermesInstallDonePayload(job));
|
|
252
|
+
scheduleCleanup(job);
|
|
253
|
+
}
|
|
254
|
+
function scheduleCleanup(job) {
|
|
255
|
+
if (job.timer) {
|
|
256
|
+
clearTimeout(job.timer);
|
|
257
|
+
job.timer = null;
|
|
258
|
+
}
|
|
259
|
+
setTimeout(() => {
|
|
260
|
+
jobs.delete(job.id);
|
|
261
|
+
}, FINISHED_TTL_MS);
|
|
262
|
+
}
|
|
263
|
+
function spawnLogged(job, command, args, options) {
|
|
264
|
+
appendLog(job, 'meta', `$ ${command} ${args.join(' ')}\n`);
|
|
265
|
+
const child = spawn(command, args, {
|
|
266
|
+
...options,
|
|
267
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
268
|
+
windowsHide: true,
|
|
269
|
+
});
|
|
270
|
+
job.child = child;
|
|
271
|
+
child.stdout.on('data', (buf) => appendLog(job, 'stdout', buf.toString()));
|
|
272
|
+
child.stderr.on('data', (buf) => appendLog(job, 'stderr', buf.toString()));
|
|
273
|
+
return new Promise((resolve, reject) => {
|
|
274
|
+
child.on('error', reject);
|
|
275
|
+
child.on('close', (code, signal) => {
|
|
276
|
+
if (signal) {
|
|
277
|
+
reject(new Error(`${command} killed by ${signal}`));
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
resolve(code ?? 0);
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
async function runConfigureScript(job, env, appRoot) {
|
|
285
|
+
const configureScript = path.join(appRoot, 'scripts', 'hermes', 'configure-pixcode-mcp.mjs');
|
|
286
|
+
if (!fs.existsSync(configureScript)) {
|
|
287
|
+
appendLog(job, 'stderr', `Pixcode MCP configure script was not found: ${configureScript}\n`);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const code = await spawnLogged(job, process.execPath, [configureScript], {
|
|
291
|
+
cwd: appRoot,
|
|
292
|
+
env,
|
|
293
|
+
});
|
|
294
|
+
if (code !== 0) {
|
|
295
|
+
throw new Error(`Pixcode MCP configuration exited with code ${code}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function installerCommand(installerPath, { hermesHome, installDir, skipBrowser }) {
|
|
299
|
+
if (process.platform === 'win32') {
|
|
300
|
+
return {
|
|
301
|
+
command: 'powershell.exe',
|
|
302
|
+
args: [
|
|
303
|
+
'-NoProfile',
|
|
304
|
+
'-ExecutionPolicy',
|
|
305
|
+
'Bypass',
|
|
306
|
+
'-File',
|
|
307
|
+
installerPath,
|
|
308
|
+
'-SkipSetup',
|
|
309
|
+
'-NonInteractive',
|
|
310
|
+
'-Branch',
|
|
311
|
+
'main',
|
|
312
|
+
...(hermesHome ? ['-HermesHome', hermesHome] : []),
|
|
313
|
+
...(installDir ? ['-InstallDir', installDir] : []),
|
|
314
|
+
],
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
return {
|
|
318
|
+
command: 'bash',
|
|
319
|
+
args: [
|
|
320
|
+
installerPath,
|
|
321
|
+
'--skip-setup',
|
|
322
|
+
'--branch',
|
|
323
|
+
'main',
|
|
324
|
+
...(installDir ? ['--dir', installDir] : []),
|
|
325
|
+
...(hermesHome ? ['--hermes-home', hermesHome] : []),
|
|
326
|
+
...(skipBrowser ? ['--skip-browser'] : []),
|
|
327
|
+
],
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
async function runHermesInstall(job) {
|
|
331
|
+
const { appRoot, force = false, hermesHome, installDir, pixcodeApiKey, pixcodeBaseUrl, skipBrowser = true, } = job.options;
|
|
332
|
+
const env = buildHermesEnv(process.env, {
|
|
333
|
+
PIXCODE_API_KEY: pixcodeApiKey,
|
|
334
|
+
PIXCODE_BASE_URL: pixcodeBaseUrl,
|
|
335
|
+
PIXCODE_APP_ROOT: appRoot,
|
|
336
|
+
HERMES_HOME: hermesHome,
|
|
337
|
+
HERMES_INSTALL_DIR: installDir,
|
|
338
|
+
});
|
|
339
|
+
appendLog(job, 'meta', `Hermes install mode: ${process.platform}\n`);
|
|
340
|
+
appendLog(job, 'meta', `Pixcode base URL: ${pixcodeBaseUrl}\n`);
|
|
341
|
+
const before = readHermesInstallStatus(env);
|
|
342
|
+
if (before.installed && !force) {
|
|
343
|
+
appendLog(job, 'meta', `Hermes already installed: ${before.version || before.command}\n`);
|
|
344
|
+
await runConfigureScript(job, env, appRoot);
|
|
345
|
+
finishJob(job, 'done', { binaryPath: before.command });
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const installerPath = path.join(os.tmpdir(), `pixcode-hermes-install-${job.id}${process.platform === 'win32' ? '.ps1' : '.sh'}`);
|
|
349
|
+
await downloadHermesInstaller(process.platform === 'win32' ? WINDOWS_INSTALLER_URL : POSIX_INSTALLER_URL, installerPath, (stream, chunk) => {
|
|
350
|
+
appendLog(job, stream, chunk);
|
|
351
|
+
});
|
|
352
|
+
const install = installerCommand(installerPath, { hermesHome, installDir, skipBrowser });
|
|
353
|
+
const installCode = await spawnLogged(job, install.command, install.args, {
|
|
354
|
+
cwd: os.homedir(),
|
|
355
|
+
env,
|
|
356
|
+
});
|
|
357
|
+
if (installCode !== 0) {
|
|
358
|
+
throw new Error(`Hermes installer exited with code ${installCode}`);
|
|
359
|
+
}
|
|
360
|
+
primeHermesPath();
|
|
361
|
+
const after = readHermesInstallStatus(env);
|
|
362
|
+
if (!after.installed) {
|
|
363
|
+
throw new Error(after.error || 'Hermes installer finished but hermes was not found.');
|
|
364
|
+
}
|
|
365
|
+
appendLog(job, 'meta', `Hermes ready: ${after.version || after.command}\n`);
|
|
366
|
+
await runConfigureScript(job, env, appRoot);
|
|
367
|
+
finishJob(job, 'done', { binaryPath: after.command });
|
|
368
|
+
}
|
|
369
|
+
export function createHermesInstallJob(options) {
|
|
370
|
+
const job = createJob(options);
|
|
371
|
+
jobs.set(job.id, job);
|
|
372
|
+
job.timer = setTimeout(() => {
|
|
373
|
+
if (job.status !== 'running')
|
|
374
|
+
return;
|
|
375
|
+
try {
|
|
376
|
+
job.child?.kill('SIGKILL');
|
|
377
|
+
}
|
|
378
|
+
catch { /* noop */ }
|
|
379
|
+
finishJob(job, 'error', { error: 'Hermes install timed out after 20 minutes' });
|
|
380
|
+
}, HARD_TIMEOUT_MS);
|
|
381
|
+
runHermesInstall(job).catch((error) => {
|
|
382
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
383
|
+
appendLog(job, 'stderr', `${message}\n`);
|
|
384
|
+
finishJob(job, 'error', { error: message });
|
|
385
|
+
});
|
|
386
|
+
return job;
|
|
387
|
+
}
|
|
388
|
+
export function getHermesInstallJob(id) {
|
|
389
|
+
return jobs.get(id) || null;
|
|
390
|
+
}
|
|
391
|
+
export function cancelHermesInstallJob(id) {
|
|
392
|
+
const job = jobs.get(id);
|
|
393
|
+
if (!job || job.status !== 'running')
|
|
394
|
+
return false;
|
|
395
|
+
try {
|
|
396
|
+
job.child?.kill();
|
|
397
|
+
}
|
|
398
|
+
catch { /* noop */ }
|
|
399
|
+
finishJob(job, 'error', { error: 'Hermes install cancelled' });
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
export function snapshotHermesInstallDonePayload(job) {
|
|
403
|
+
if (job.status === 'done') {
|
|
404
|
+
return {
|
|
405
|
+
success: true,
|
|
406
|
+
exitCode: job.exitCode,
|
|
407
|
+
binaryPath: job.binaryPath,
|
|
408
|
+
message: 'Hermes Agent is installed and Pixcode MCP is configured.',
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
return {
|
|
412
|
+
success: false,
|
|
413
|
+
exitCode: job.exitCode,
|
|
414
|
+
error: job.error || 'Hermes install failed',
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
//# sourceMappingURL=hermes-install-jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-install-jobs.js","sourceRoot":"","sources":["../../../server/services/hermes-install-jobs.js"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixelbyte-software/pixcode",
|
|
3
|
-
"version": "1.49.
|
|
3
|
+
"version": "1.49.2",
|
|
4
4
|
"description": "Self-hosted AI coding agent control room for Claude Code, Cursor CLI, OpenAI Codex, Gemini CLI, Qwen Code, and OpenCode with chat, files, shell, Git, orchestration, API keys, Telegram, MCP, plugins, themes, and desktop/server deployment.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist-server/server/index.js",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
7
|
+
|
|
8
|
+
const read = (relativePath) => fs.readFileSync(path.join(repoRoot, relativePath), 'utf8');
|
|
9
|
+
|
|
10
|
+
const hermesRoutes = read('server/modules/orchestration/hermes/hermes.routes.ts');
|
|
11
|
+
const hermesInstallJobs = fs.existsSync(path.join(repoRoot, 'server/services/hermes-install-jobs.js'))
|
|
12
|
+
? read('server/services/hermes-install-jobs.js')
|
|
13
|
+
: '';
|
|
14
|
+
const workbench = read('src/components/vscode-workbench/view/VSCodeWorkbench.tsx');
|
|
15
|
+
const smoke = read('scripts/smoke/pixcode-workbench-1-48.mjs');
|
|
16
|
+
|
|
17
|
+
assert.match(hermesRoutes, /createHermesInstallJob/, 'Hermes API should start backend install jobs.');
|
|
18
|
+
assert.match(hermesRoutes, /router\.post\('\/install'/, 'Hermes should expose POST /api/orchestration/hermes/install.');
|
|
19
|
+
assert.match(hermesRoutes, /router\.get\('\/install\/:jobId\/stream'/, 'Hermes install jobs should expose an EventSource stream.');
|
|
20
|
+
assert.match(hermesRoutes, /router\.delete\('\/install\/:jobId'/, 'Hermes install jobs should be cancellable.');
|
|
21
|
+
assert.match(hermesInstallJobs, /downloadHermesInstaller/, 'Hermes installer should be downloaded by backend code, not pasted into the terminal.');
|
|
22
|
+
assert.match(hermesInstallJobs, /--skip-setup/, 'POSIX Hermes API install should skip the interactive setup wizard.');
|
|
23
|
+
assert.match(hermesInstallJobs, /--skip-browser/, 'Hermes API install should skip browser downloads by default for reliable headless installs.');
|
|
24
|
+
assert.doesNotMatch(hermesInstallJobs, /curl -fsSL .* \| bash/, 'Hermes API install must not pipe curl directly into bash.');
|
|
25
|
+
assert.match(workbench, /\/api\/orchestration\/hermes\/install/, 'Workbench Hermes install button should call the Hermes install API.');
|
|
26
|
+
assert.doesNotMatch(workbench, /HERMES_AGENT_INSTALL_COMMAND/, 'Workbench should not launch Hermes install through a terminal command.');
|
|
27
|
+
assert.match(smoke, /hermes-api-install\.mjs/, 'Main workbench smoke should mention the dedicated Hermes API install smoke.');
|
|
28
|
+
|
|
29
|
+
console.log('hermes API install smoke passed');
|
|
@@ -17,6 +17,10 @@ const app = read('src/App.tsx');
|
|
|
17
17
|
const serverIndex = read('server/index.js');
|
|
18
18
|
const hermesRoutes = read('server/modules/orchestration/hermes/hermes.routes.ts');
|
|
19
19
|
const shellTerminal = read('src/components/shell/hooks/useShellTerminal.ts');
|
|
20
|
+
const shellConnection = read('src/components/shell/hooks/useShellConnection.ts');
|
|
21
|
+
const geminiCli = read('server/gemini-cli.js');
|
|
22
|
+
const qwenCli = read('server/qwen-code-cli.js');
|
|
23
|
+
const agentSettings = read('src/components/settings/view/tabs/agents-settings/AgentsSettingsTab.tsx');
|
|
20
24
|
const gitPanelHeader = read('src/components/git-panel/view/GitPanelHeader.tsx');
|
|
21
25
|
const themeContext = read('src/contexts/ThemeContext.jsx');
|
|
22
26
|
|
|
@@ -58,6 +62,7 @@ assert.match(workbench, /isBottomTerminalMinimized/, 'Bottom terminal should sup
|
|
|
58
62
|
assert.match(workbench, /isPlainShell/, 'Bottom terminal should open the selected project folder without starting the selected AI CLI.');
|
|
59
63
|
assert.match(workbench, /HERMES_AGENT_START_COMMAND/, 'Hermes Agent should launch from the bottom terminal through a server-side sentinel.');
|
|
60
64
|
assert.doesNotMatch(workbench, /Project-scoped agent terminal\. Installs Hermes when missing/, 'Right CLI panel should not show the old Hermes card.');
|
|
65
|
+
assert.doesNotMatch(workbench, /vscodeWorkbench\.hermes\.docsShort|HERMES_AGENT_DOCS_URL/, 'Hermes terminal header should not include a docs shortcut.');
|
|
61
66
|
assert.match(workbench, /shrinkCliPanel/, 'Right CLI panel should expose a shrink action.');
|
|
62
67
|
assert.match(workbench, /expandCliPanel/, 'Right CLI panel should expose an expand action.');
|
|
63
68
|
assert.match(workbench, /vscodeWorkbench\.welcome\.openProject/, 'Workbench welcome should expose a simple Open Project action.');
|
|
@@ -72,6 +77,10 @@ assert.match(serverIndex, /\/api\/shell\/sessions\/terminate/, 'Backend should e
|
|
|
72
77
|
assert.match(serverIndex, /isPlainShell && !initialCommand/, 'Backend should spawn an interactive plain shell when no terminal command is provided.');
|
|
73
78
|
assert.match(serverIndex, /pixcode:hermes:start/, 'Backend should expand Hermes terminal sentinels on the server host.');
|
|
74
79
|
assert.doesNotMatch(serverIndex, /iex \(irm https:\/\/raw\.githubusercontent\.com\/NousResearch\/hermes-agent\/main\/scripts\/install\.ps1\)/, 'Windows Hermes install should avoid the old inline iex pattern.');
|
|
80
|
+
assert.doesNotMatch(serverIndex, /scriptblock\]::Create\(\(irm https:\/\/raw\.githubusercontent\.com\/NousResearch\/hermes-agent\/main\/scripts\/install\.ps1\)\)/, 'Windows Hermes install should avoid scriptblock Invoke-RestMethod eval patterns.');
|
|
81
|
+
assert.match(serverIndex, /Invoke-WebRequest[\s\S]+install\.ps1[\s\S]+-OutFile/, 'Windows Hermes install should download the installer to a file before running it.');
|
|
82
|
+
assert.match(serverIndex, /Resolve-HermesCommand|resolveHermesCommand/, 'Hermes start/install should resolve an existing hermes binary before installing.');
|
|
83
|
+
assert.match(serverIndex, /buildProviderShellCommand/, 'Provider terminal launch should centralize provider-specific permission flags.');
|
|
75
84
|
assert.doesNotMatch(shellTerminal, /new WebglAddon\(\)/, 'Workbench terminal should use the stable xterm renderer.');
|
|
76
85
|
assert.match(workbench, /setActivityPanel\('explorer'\)/, 'Selecting a project should return the side panel to Explorer.');
|
|
77
86
|
assert.match(gitPanelHeader, /compact/, 'Workbench Source Control should have compact icon-only controls.');
|
|
@@ -94,7 +103,21 @@ assert.match(serverIndex, /app\.use\('\/hermes', createHermesTaskRouter\(\)\)/,
|
|
|
94
103
|
assert.doesNotMatch(serverIndex, /app\.use\('\/a2a'/, 'Server should not expose the old A2A route.');
|
|
95
104
|
assert.match(hermesRoutes, /createHermesRouter/, 'Hermes should have a dedicated orchestration API router.');
|
|
96
105
|
assert.match(hermesRoutes, /terminal-launches/, 'Hermes MCP should be able to request visible Pixcode CLI terminal launches.');
|
|
106
|
+
assert.match(hermesRoutes, /install-status/, 'Hermes settings and terminal UI should have an install-status endpoint.');
|
|
107
|
+
assert.match(hermesRoutes, /router\.post\('\/install'/, 'Hermes should install through the backend API instead of terminal command paste.');
|
|
108
|
+
assert.match(read('scripts/smoke/hermes-api-install.mjs'), /hermes API install smoke passed/, 'Hermes API install behavior should have a focused smoke test.');
|
|
97
109
|
assert.match(serverIndex, /forceNewSession/, 'Shell backend should support explicit fresh-session launches from the workbench.');
|
|
98
110
|
assert.match(serverIndex, /killProviderPtySessions/, 'Shell backend should terminate old provider PTYs when a fresh CLI session is requested.');
|
|
99
111
|
|
|
112
|
+
assert.match(settingsTypes, /'hermes'/, 'Settings Agents should support Hermes Agent as a first-class agent.');
|
|
113
|
+
assert.match(agentSettings, /'hermes'/, 'Settings Agents should list Hermes Agent.');
|
|
114
|
+
assert.match(workbench, /hermesInstallStatus/, 'Workbench should hide Hermes install actions when Hermes is already installed.');
|
|
115
|
+
assert.match(shellConnection, /cursor-tools-settings/, 'Cursor shell launches should read Cursor permission settings, not Claude settings.');
|
|
116
|
+
assert.match(shellConnection, /permissionMode/, 'Shell websocket init should send provider permission mode to the backend.');
|
|
117
|
+
assert.match(serverIndex, /--dangerously-bypass-approvals-and-sandbox/, 'Codex terminal bypass mode should use the Codex CLI bypass flag.');
|
|
118
|
+
assert.match(serverIndex, /--yolo/, 'Gemini and Qwen terminal bypass mode should use --yolo.');
|
|
119
|
+
assert.match(serverIndex, /--dangerously-skip-permissions/, 'Claude/OpenCode terminal bypass mode should pass the provider bypass flag.');
|
|
120
|
+
assert.match(geminiCli, /permissionMode === 'bypassPermissions'[\s\S]+--yolo|--yolo[\s\S]+permissionMode === 'bypassPermissions'/, 'Gemini chat route should map Pixcode bypassPermissions to --yolo.');
|
|
121
|
+
assert.match(qwenCli, /permissionMode === 'bypassPermissions'[\s\S]+--yolo|--yolo[\s\S]+permissionMode === 'bypassPermissions'/, 'Qwen chat route should map Pixcode bypassPermissions to --yolo.');
|
|
122
|
+
|
|
100
123
|
console.log('pixcode workbench 1.48 smoke passed');
|
package/server/gemini-cli.js
CHANGED
|
@@ -190,7 +190,13 @@ async function spawnGemini(command, options = {}, ws) {
|
|
|
190
190
|
args.push('--output-format', 'stream-json');
|
|
191
191
|
|
|
192
192
|
// Handle approval modes and allowed tools
|
|
193
|
-
if (
|
|
193
|
+
if (
|
|
194
|
+
settings.skipPermissions ||
|
|
195
|
+
options.skipPermissions ||
|
|
196
|
+
permissionMode === 'yolo' ||
|
|
197
|
+
permissionMode === 'bypassPermissions' ||
|
|
198
|
+
permissionMode === 'acceptEdits'
|
|
199
|
+
) {
|
|
194
200
|
args.push('--yolo');
|
|
195
201
|
} else if (permissionMode === 'auto_edit') {
|
|
196
202
|
args.push('--approval-mode', 'auto_edit');
|