@midscene/shared 1.5.5-beta-20260316093244.0 → 1.5.6

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.
@@ -75,7 +75,15 @@ class BaseMCPServer {
75
75
  console.error(`Failed to connect MCP stdio transport: ${message}`);
76
76
  throw new Error(`Failed to initialize MCP stdio transport: ${message}`);
77
77
  }
78
+ let isShuttingDown = false;
79
+ const cleanup = ()=>{
80
+ if (isShuttingDown) return;
81
+ isShuttingDown = true;
82
+ console.error(`${this.config.name} shutting down...`);
83
+ this.performCleanup().finally(()=>process.exit(0));
84
+ };
78
85
  process.on('uncaughtException', (error)=>{
86
+ if ('EPIPE' === error.code || 'ERR_STREAM_DESTROYED' === error.code) return void cleanup();
79
87
  console.error(`[${this.config.name}] Uncaught Exception:`, error);
80
88
  console.error('Stack:', error.stack);
81
89
  });
@@ -83,15 +91,12 @@ class BaseMCPServer {
83
91
  console.error(`[${this.config.name}] Unhandled Rejection:`, reason);
84
92
  if (reason instanceof Error) console.error('Stack:', reason.stack);
85
93
  });
86
- process.stdin.on('close', ()=>{
87
- this.performCleanup().finally(()=>process.exit(0));
88
- });
89
- const cleanup = ()=>{
90
- console.error(`${this.config.name} shutting down...`);
91
- this.performCleanup().finally(()=>process.exit(0));
92
- };
94
+ process.stdin.on('close', cleanup);
95
+ process.stdin.on('end', cleanup);
96
+ process.stdout.on('error', cleanup);
93
97
  process.once('SIGINT', cleanup);
94
98
  process.once('SIGTERM', cleanup);
99
+ process.once('SIGHUP', cleanup);
95
100
  return {
96
101
  close: async ()=>{
97
102
  this.performCleanup();
@@ -115,7 +115,15 @@ class BaseMCPServer {
115
115
  console.error(`Failed to connect MCP stdio transport: ${message}`);
116
116
  throw new Error(`Failed to initialize MCP stdio transport: ${message}`);
117
117
  }
118
+ let isShuttingDown = false;
119
+ const cleanup = ()=>{
120
+ if (isShuttingDown) return;
121
+ isShuttingDown = true;
122
+ console.error(`${this.config.name} shutting down...`);
123
+ this.performCleanup().finally(()=>process.exit(0));
124
+ };
118
125
  process.on('uncaughtException', (error)=>{
126
+ if ('EPIPE' === error.code || 'ERR_STREAM_DESTROYED' === error.code) return void cleanup();
119
127
  console.error(`[${this.config.name}] Uncaught Exception:`, error);
120
128
  console.error('Stack:', error.stack);
121
129
  });
@@ -123,15 +131,12 @@ class BaseMCPServer {
123
131
  console.error(`[${this.config.name}] Unhandled Rejection:`, reason);
124
132
  if (reason instanceof Error) console.error('Stack:', reason.stack);
125
133
  });
126
- process.stdin.on('close', ()=>{
127
- this.performCleanup().finally(()=>process.exit(0));
128
- });
129
- const cleanup = ()=>{
130
- console.error(`${this.config.name} shutting down...`);
131
- this.performCleanup().finally(()=>process.exit(0));
132
- };
134
+ process.stdin.on('close', cleanup);
135
+ process.stdin.on('end', cleanup);
136
+ process.stdout.on('error', cleanup);
133
137
  process.once('SIGINT', cleanup);
134
138
  process.once('SIGTERM', cleanup);
139
+ process.once('SIGHUP', cleanup);
135
140
  return {
136
141
  close: async ()=>{
137
142
  this.performCleanup();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/shared",
3
- "version": "1.5.5-beta-20260316093244.0",
3
+ "version": "1.5.6",
4
4
  "repository": "https://github.com/web-infra-dev/midscene",
5
5
  "homepage": "https://midscenejs.com/",
6
6
  "types": "./dist/types/index.d.ts",
@@ -165,11 +165,24 @@ export abstract class BaseMCPServer {
165
165
  throw new Error(`Failed to initialize MCP stdio transport: ${message}`);
166
166
  }
167
167
 
168
+ // Setup signal handlers for graceful shutdown
169
+ let isShuttingDown = false;
170
+ const cleanup = () => {
171
+ if (isShuttingDown) return;
172
+ isShuttingDown = true;
173
+ console.error(`${this.config.name} shutting down...`);
174
+ this.performCleanup().finally(() => process.exit(0));
175
+ };
176
+
168
177
  // Setup process-level error handlers to prevent crashes
169
- process.on('uncaughtException', (error: Error) => {
178
+ process.on('uncaughtException', (error: Error & { code?: string }) => {
179
+ // Exit on pipe errors — parent process is gone
180
+ if (error.code === 'EPIPE' || error.code === 'ERR_STREAM_DESTROYED') {
181
+ cleanup();
182
+ return;
183
+ }
170
184
  console.error(`[${this.config.name}] Uncaught Exception:`, error);
171
185
  console.error('Stack:', error.stack);
172
- // Don't exit - try to recover
173
186
  });
174
187
 
175
188
  process.on('unhandledRejection', (reason: unknown) => {
@@ -177,22 +190,18 @@ export abstract class BaseMCPServer {
177
190
  if (reason instanceof Error) {
178
191
  console.error('Stack:', reason.stack);
179
192
  }
180
- // Don't exit - try to recover
181
193
  });
182
194
 
183
- // Setup cleanup handlers
184
- process.stdin.on('close', () => {
185
- this.performCleanup().finally(() => process.exit(0));
186
- });
195
+ // Exit when stdin closes (parent process gone) or reaches EOF
196
+ process.stdin.on('close', cleanup);
197
+ process.stdin.on('end', cleanup);
187
198
 
188
- // Setup signal handlers for graceful shutdown
189
- const cleanup = () => {
190
- console.error(`${this.config.name} shutting down...`);
191
- this.performCleanup().finally(() => process.exit(0));
192
- };
199
+ // Exit when stdout/stderr pipe breaks (parent process gone)
200
+ process.stdout.on('error', cleanup);
193
201
 
194
202
  process.once('SIGINT', cleanup);
195
203
  process.once('SIGTERM', cleanup);
204
+ process.once('SIGHUP', cleanup);
196
205
 
197
206
  return {
198
207
  close: async () => {