@yeaft/webchat-agent 1.0.210 → 1.0.211

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.
@@ -1 +1 @@
1
- {"version":"1.0.210"}
1
+ {"version":"1.0.211"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "1.0.210",
3
+ "version": "1.0.211",
4
4
  "description": "Remote worker agent for Yeaft Web Code Agent — connects the native Yeaft engine, CLI providers, and workbench tools",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/yeaft/mcp.js CHANGED
@@ -141,8 +141,17 @@ class MCPServerConnection extends EventEmitter {
141
141
  */
142
142
  async start() {
143
143
  return new Promise((resolve, reject) => {
144
- const timer = setTimeout(() => {
145
- reject(new Error(`MCP server "${this.#name}" startup timeout (${STARTUP_TIMEOUT_MS}ms)`));
144
+ let settled = false;
145
+ let timer = null;
146
+ const failStart = async (err) => {
147
+ if (settled) return;
148
+ settled = true;
149
+ if (timer) clearTimeout(timer);
150
+ await this.stop();
151
+ reject(err);
152
+ };
153
+ timer = setTimeout(() => {
154
+ void failStart(new Error(`MCP server "${this.#name}" startup timeout (${STARTUP_TIMEOUT_MS}ms)`));
146
155
  }, STARTUP_TIMEOUT_MS);
147
156
 
148
157
  try {
@@ -181,23 +190,22 @@ class MCPServerConnection extends EventEmitter {
181
190
  });
182
191
 
183
192
  this.#process.on('error', (err) => {
184
- clearTimeout(timer);
185
- reject(err);
193
+ void failStart(err);
186
194
  });
187
195
 
188
196
  // Initialize MCP protocol
189
197
  this.#initialize().then(() => {
198
+ if (settled) return;
199
+ settled = true;
190
200
  clearTimeout(timer);
191
201
  this.#ready = true;
192
202
  resolve();
193
203
  }).catch((err) => {
194
- clearTimeout(timer);
195
- reject(err);
204
+ void failStart(err);
196
205
  });
197
206
 
198
207
  } catch (err) {
199
- clearTimeout(timer);
200
- reject(err);
208
+ void failStart(err);
201
209
  }
202
210
  });
203
211
  }
@@ -319,23 +327,27 @@ class MCPServerConnection extends EventEmitter {
319
327
  * Stop the MCP server process.
320
328
  */
321
329
  async stop() {
322
- if (this.#process) {
323
- this.#ready = false;
324
- this.#process.kill('SIGTERM');
325
- // Wait a bit then force kill. Test fakes do not emit close, so cap the
326
- // wait at 2s and do not require a close event for cleanup to finish.
327
- await Promise.race([
328
- new Promise(resolve => {
329
- if (this.#closed) return resolve();
330
- this.#process.once('close', resolve);
331
- }),
332
- new Promise(resolve => setTimeout(resolve, 2000)),
333
- ]);
334
- if (this.#process && !this.#process.killed && !this.#closed) {
335
- this.#process.kill('SIGKILL');
336
- }
337
- this.#process = null;
330
+ const child = this.#process;
331
+ if (!child) return;
332
+
333
+ this.#ready = false;
334
+ let closed = this.#closed;
335
+ if (!closed) {
336
+ child.kill('SIGTERM');
337
+ closed = await new Promise(resolve => {
338
+ let timer = null;
339
+ const finish = (didClose) => {
340
+ if (timer) clearTimeout(timer);
341
+ child.removeListener('close', onClose);
342
+ resolve(didClose);
343
+ };
344
+ const onClose = () => finish(true);
345
+ child.once('close', onClose);
346
+ timer = setTimeout(() => finish(false), 2000);
347
+ });
348
+ if (!closed) child.kill('SIGKILL');
338
349
  }
350
+ if (this.#process === child) this.#process = null;
339
351
  }
340
352
  }
341
353