mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Persist exit codes without tmux pane_dead_status
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
listPanes,
|
||||
findWindowByName,
|
||||
capturePaneContent,
|
||||
extractExitCodeMarkerFromOutput,
|
||||
sendText as tmuxSendText,
|
||||
sendKeys as tmuxSendKeys,
|
||||
renameWindow,
|
||||
@@ -382,7 +383,9 @@ export class TerminalManager {
|
||||
// Use stored values for dead panes, current values for live ones
|
||||
const workingDirectory = await getStoredWorkingDirectory(window.id, paneId);
|
||||
const currentCommand = await getStoredCommand(window.id, paneId);
|
||||
const lastLines = await capturePaneContent(paneId, 5, false);
|
||||
const rawLastLines = await capturePaneContent(paneId, 5, false);
|
||||
const lastLinesExtracted = extractExitCodeMarkerFromOutput(rawLastLines);
|
||||
const lastLines = lastLinesExtracted.output;
|
||||
|
||||
let exitCode: number | null = null;
|
||||
if (isDead) {
|
||||
@@ -394,7 +397,7 @@ export class TerminalManager {
|
||||
"#{pane_dead_status}",
|
||||
]);
|
||||
const parsed = parseInt(exitCodeStr, 10);
|
||||
exitCode = Number.isFinite(parsed) ? parsed : null;
|
||||
exitCode = Number.isFinite(parsed) ? parsed : lastLinesExtracted.exitCode;
|
||||
}
|
||||
|
||||
commands.push({
|
||||
@@ -427,9 +430,11 @@ export class TerminalManager {
|
||||
throw new Error(`Session '${this.sessionName}' not found.`);
|
||||
}
|
||||
|
||||
const paneId = `${commandId}.0`;
|
||||
const paneId = `${commandId}.0`;
|
||||
|
||||
const output = await capturePaneContent(paneId, lines, false);
|
||||
const rawOutput = await capturePaneContent(paneId, lines, false);
|
||||
const extracted = extractExitCodeMarkerFromOutput(rawOutput);
|
||||
const output = extracted.output;
|
||||
|
||||
const deadStatus = await executeTmux([
|
||||
"display-message",
|
||||
@@ -450,7 +455,7 @@ export class TerminalManager {
|
||||
"#{pane_dead_status}",
|
||||
]);
|
||||
const parsed = parseInt(exitCodeStr, 10);
|
||||
exitCode = Number.isFinite(parsed) ? parsed : null;
|
||||
exitCode = Number.isFinite(parsed) ? parsed : extracted.exitCode;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -49,6 +49,8 @@ let shellConfig: { type: ShellType } = { type: "bash" };
|
||||
const ANSI_ESCAPE_REGEX =
|
||||
/\u001B[\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
|
||||
|
||||
const EXIT_CODE_MARKER = "__PASEO_EXIT_CODE__:";
|
||||
|
||||
function stripAnsiSequences(value: string): string {
|
||||
if (!value) {
|
||||
return "";
|
||||
@@ -56,6 +58,33 @@ function stripAnsiSequences(value: string): string {
|
||||
return value.replace(ANSI_ESCAPE_REGEX, "");
|
||||
}
|
||||
|
||||
export function extractExitCodeMarkerFromOutput(output: string): {
|
||||
exitCode: number | null;
|
||||
output: string;
|
||||
} {
|
||||
if (!output) {
|
||||
return { exitCode: null, output };
|
||||
}
|
||||
|
||||
let exitCode: number | null = null;
|
||||
const kept: string[] = [];
|
||||
|
||||
for (const line of output.split("\n")) {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed.startsWith(EXIT_CODE_MARKER)) {
|
||||
const codeStr = trimmed.slice(EXIT_CODE_MARKER.length).trim();
|
||||
const parsed = parseInt(codeStr, 10);
|
||||
if (Number.isFinite(parsed)) {
|
||||
exitCode = parsed;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
kept.push(line);
|
||||
}
|
||||
|
||||
return { exitCode, output: kept.join("\n").trimEnd() };
|
||||
}
|
||||
|
||||
export function setShellConfig(config: { type: string }): void {
|
||||
// Validate shell type
|
||||
const validShells: ShellType[] = ["bash", "zsh", "fish"];
|
||||
@@ -559,7 +588,7 @@ export async function executeCommand({
|
||||
|
||||
// Execute command via respawn-pane with bash -c wrapper
|
||||
// This ensures all bash features work (pipes, operators, etc.)
|
||||
const wrappedCommand = `bash -c 'cd "${expandedPath}" && ${command.replace(/'/g, "'\\''")} 2>&1; exit $?'`;
|
||||
const wrappedCommand = `bash -c 'cd "${expandedPath}" && ${command.replace(/'/g, "'\\''")} 2>&1; code=$?; echo ${EXIT_CODE_MARKER}$code; exit $code'`;
|
||||
await executeTmux(["respawn-pane", "-t", pane.id, "-k", wrappedCommand]);
|
||||
|
||||
// Wait for command to finish or reach stability
|
||||
@@ -584,6 +613,8 @@ export async function executeCommand({
|
||||
if (isDead) {
|
||||
// Command finished - capture output and exit code
|
||||
output = await capturePaneContent(pane.id, 1000, false);
|
||||
const extracted = extractExitCodeMarkerFromOutput(output);
|
||||
output = extracted.output;
|
||||
const exitCodeStr = await executeTmux([
|
||||
"display-message",
|
||||
"-p",
|
||||
@@ -592,7 +623,7 @@ export async function executeCommand({
|
||||
"#{pane_dead_status}",
|
||||
]);
|
||||
const parsed = parseInt(exitCodeStr, 10);
|
||||
exitCode = Number.isFinite(parsed) ? parsed : null;
|
||||
exitCode = Number.isFinite(parsed) ? parsed : extracted.exitCode;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user