@pixelbyte-software/pixcode 1.50.3 → 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/assets/{index-DpdiWohD.js → index-DYQjBZrd.js} +91 -91
- package/dist/index.html +1 -1
- package/dist-server/server/index.js +69 -2
- package/dist-server/server/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/hermes/pixcode-mcp-server.mjs +103 -14
- package/scripts/smoke/hermes-mcp-pixcode-roundtrip.mjs +61 -2
- package/scripts/smoke/hermes-rest-codex-launch.mjs +14 -0
- package/scripts/smoke/hermes-settings-commands.mjs +30 -0
- package/server/index.js +85 -2
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-
|
|
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
|
}
|
|
@@ -439,6 +494,8 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
|
|
|
439
494
|
const projectPath = typeof req.query.projectPath === 'string' && req.query.projectPath.trim()
|
|
440
495
|
? req.query.projectPath.trim()
|
|
441
496
|
: null;
|
|
497
|
+
const launchId = Number.parseInt(String(req.query.launchId || ''), 10);
|
|
498
|
+
const requestedLaunchId = Number.isFinite(launchId) && launchId > 0 ? launchId : null;
|
|
442
499
|
const maxChars = Math.min(20000, Math.max(1000, Number.parseInt(String(req.query.maxChars || '12000'), 10) || 12000));
|
|
443
500
|
if (!SHELL_CLI_PROVIDERS.has(provider)) {
|
|
444
501
|
return res.status(400).json({ error: 'Unsupported provider' });
|
|
@@ -448,7 +505,8 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
|
|
|
448
505
|
for (const session of ptySessionsMap.values()) {
|
|
449
506
|
if (session?.provider === provider &&
|
|
450
507
|
!session?.isPlainShell &&
|
|
451
|
-
(!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath)
|
|
508
|
+
(!requestedProjectPath || path.resolve(session.projectPath || os.homedir()) === requestedProjectPath) &&
|
|
509
|
+
(!requestedLaunchId || session.hermesLaunchId === requestedLaunchId)) {
|
|
452
510
|
if (!matchedSession || (session.updatedAt || 0) > (matchedSession.updatedAt || 0)) {
|
|
453
511
|
matchedSession = session;
|
|
454
512
|
}
|
|
@@ -459,18 +517,23 @@ app.get('/api/shell/sessions/provider-output', authenticateToken, (req, res) =>
|
|
|
459
517
|
active: false,
|
|
460
518
|
provider,
|
|
461
519
|
projectPath: requestedProjectPath,
|
|
520
|
+
launchId: requestedLaunchId,
|
|
462
521
|
output: '',
|
|
463
522
|
message: 'No active provider terminal session found for this project.',
|
|
464
523
|
});
|
|
465
524
|
}
|
|
466
525
|
const rawOutput = matchedSession.buffer.join('').slice(-maxChars);
|
|
526
|
+
const output = stripAnsiSequences(rawOutput);
|
|
527
|
+
const terminalState = detectProviderTerminalState(provider, output);
|
|
467
528
|
res.json({
|
|
468
529
|
active: true,
|
|
469
530
|
provider,
|
|
470
531
|
projectPath: path.resolve(matchedSession.projectPath || os.homedir()),
|
|
471
532
|
sessionId: matchedSession.sessionId || null,
|
|
533
|
+
launchId: matchedSession.hermesLaunchId || null,
|
|
472
534
|
updatedAt: matchedSession.updatedAt || null,
|
|
473
|
-
|
|
535
|
+
...terminalState,
|
|
536
|
+
output,
|
|
474
537
|
});
|
|
475
538
|
});
|
|
476
539
|
// Authentication routes (public)
|
|
@@ -2080,6 +2143,9 @@ function handleShellConnection(ws, request) {
|
|
|
2080
2143
|
const startupInput = typeof data.startupInput === 'string' && data.startupInput.trim()
|
|
2081
2144
|
? data.startupInput.trim()
|
|
2082
2145
|
: null;
|
|
2146
|
+
const hermesLaunchId = Number.isFinite(Number(data.hermesLaunchId)) && Number(data.hermesLaunchId) > 0
|
|
2147
|
+
? Number(data.hermesLaunchId)
|
|
2148
|
+
: null;
|
|
2083
2149
|
const isPlainShell = data.isPlainShell || (!!initialCommand && !hasSession) || provider === 'plain-shell';
|
|
2084
2150
|
const isHermesCliLaunch = isPlainShell && isHermesCliCommand(initialCommand);
|
|
2085
2151
|
const forceNewSession = Boolean(data.forceNewSession);
|
|
@@ -2356,6 +2422,7 @@ function handleShellConnection(ws, request) {
|
|
|
2356
2422
|
timeoutId: null,
|
|
2357
2423
|
projectPath,
|
|
2358
2424
|
sessionId,
|
|
2425
|
+
hermesLaunchId,
|
|
2359
2426
|
provider,
|
|
2360
2427
|
isPlainShell,
|
|
2361
2428
|
keepAliveUntilExit: false,
|