Skip to content

Commit 2fafed4

Browse files
committed
feat: enhance service management by reconciling exited PTY sessions and improve terminal session handling
1 parent da4ebd9 commit 2fafed4

3 files changed

Lines changed: 66 additions & 11 deletions

File tree

resources/installer.nsh

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1+
!ifndef BUILD_UNINSTALLER
12
!macro customPageAfterChangeDir
2-
!define MUI_PAGE_CUSTOMFUNCTION_SHOW maibotShowInstallDetails
3+
ShowInstDetails hide
34
!macroend
5+
!endif
46

57
!macro customHeader
6-
ShowInstDetails show
8+
ShowInstDetails hide
79
!ifdef BUILD_UNINSTALLER
8-
ShowUninstDetails show
10+
ShowUninstDetails hide
911
!endif
1012
!macroend
11-
12-
!macro customInstall
13-
SetDetailsView show
14-
!macroend
15-
16-
Function maibotShowInstallDetails
17-
SetDetailsView show
18-
FunctionEnd

src/main/services/service-manager.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ export class ServiceManager extends EventEmitter {
629629

630630
async refresh(): Promise<ServiceDescriptor[]> {
631631
this.attachLivePtySessions();
632+
this.reconcileExitedPtySessions();
632633

633634
for (const definition of this.definitions) {
634635
const state = this.getState(definition.id);
@@ -961,6 +962,36 @@ export class ServiceManager extends EventEmitter {
961962
}
962963
}
963964

965+
private reconcileExitedPtySessions(): void {
966+
const sessions = new Map(this.pty.list().map((session) => [session.id, session]));
967+
968+
for (const definition of this.definitions) {
969+
const state = this.getState(definition.id);
970+
if (!state.ptySessionId || state.status === "stopped" || state.status === "error") {
971+
continue;
972+
}
973+
974+
const session = sessions.get(state.ptySessionId);
975+
if (!session || session.status === "starting" || session.status === "running" || session.status === "stopping") {
976+
continue;
977+
}
978+
979+
const stoppedByRequest = state.status === "stopping" || !state.desired;
980+
this.setState(definition.id, {
981+
...state,
982+
status: stoppedByRequest ? "stopped" : "error",
983+
health: "unknown",
984+
managed: false,
985+
desired: stoppedByRequest ? false : state.desired,
986+
pid: undefined,
987+
ptySessionId: undefined,
988+
error: stoppedByRequest ? undefined : (session.error ?? `进程异常退出: ${session.exitCode ?? "未知"}`),
989+
detail: stoppedByRequest ? "已停止" : `进程异常退出: ${session.exitCode ?? "未知"}`,
990+
stoppedAt: session.endedAt ?? Date.now(),
991+
});
992+
}
993+
}
994+
964995
private handlePtyData(event: PtyDataEvent): void {
965996
const serviceId = serviceIdFromSession(event.sessionId);
966997
if (!serviceId) {
@@ -1006,6 +1037,7 @@ export class ServiceManager extends EventEmitter {
10061037
health: "unknown",
10071038
managed: false,
10081039
pid: undefined,
1040+
ptySessionId: undefined,
10091041
detail: stoppedByRequest
10101042
? "已停止"
10111043
: shouldRestart
@@ -1051,6 +1083,23 @@ export class ServiceManager extends EventEmitter {
10511083
return;
10521084
}
10531085

1086+
if (snapshot.status === "exited" || snapshot.status === "error") {
1087+
const stoppedByRequest = state.status === "stopping" || !state.desired;
1088+
this.setState(serviceId, {
1089+
...state,
1090+
status: stoppedByRequest ? "stopped" : "error",
1091+
health: "unknown",
1092+
managed: false,
1093+
desired: stoppedByRequest ? false : state.desired,
1094+
pid: undefined,
1095+
ptySessionId: undefined,
1096+
error: stoppedByRequest ? undefined : (snapshot.error ?? `进程异常退出: ${snapshot.exitCode ?? "未知"}`),
1097+
detail: stoppedByRequest ? "已停止" : `进程异常退出: ${snapshot.exitCode ?? "未知"}`,
1098+
stoppedAt: snapshot.endedAt ?? Date.now(),
1099+
});
1100+
return;
1101+
}
1102+
10541103
this.setState(serviceId, {
10551104
...state,
10561105
pid: snapshot.pid,

src/renderer/src/components/app/TerminalPanel.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ function writeSystemLine(terminal: Terminal, message: string): void {
5454
terminal.writeln(`\x1b[38;2;155;213;108m[desktop]\x1b[0m ${message}`);
5555
}
5656

57+
function canWriteToSession(session?: PtySessionSnapshot): boolean {
58+
return session?.status === "running";
59+
}
60+
5761
async function copyTerminalSelection(terminal: Terminal): Promise<void> {
5862
const selection = terminal.getSelection();
5963
if (!selection) {
@@ -156,6 +160,10 @@ export function TerminalPanel({
156160

157161
const disposables: Disposable[] = [
158162
terminal.onData((data) => {
163+
if (!canWriteToSession(sessionsRef.current.get(sessionId))) {
164+
return;
165+
}
166+
159167
void bridgeRef.current?.pty.input({ sessionId, data }).catch((error: unknown) => {
160168
writeSystemLine(terminal, error instanceof Error ? error.message : String(error));
161169
});
@@ -173,6 +181,10 @@ export function TerminalPanel({
173181
return false;
174182
}
175183

184+
if (event.type === "keydown" && !canWriteToSession(sessionsRef.current.get(sessionId))) {
185+
return false;
186+
}
187+
176188
return true;
177189
});
178190

0 commit comments

Comments
 (0)