@microi.net/cli 4.9.6 → 4.9.8

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.
Files changed (93) hide show
  1. package/.codebuddy-plugin/marketplace.json +2 -2
  2. package/.codebuddy-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.workbuddy-plugin/marketplace.json +2 -2
  5. package/.workbuddy-plugin/plugin.json +1 -1
  6. package/assets/build-meta.json +6 -5
  7. package/package.json +1 -1
  8. package/scripts/mcp-server.js +83 -83
  9. package/scripts/microi-cli.js +55 -85
  10. package/scripts/microi-codex-broker.js +418 -0
  11. package/scripts/microi-codex-router.js +129 -65
  12. package/scripts/microi-skills.meta.json +310 -151
  13. package/skills/.microi-skills-version.json +2 -2
  14. package/skills/.progressive-disclosure-manifest.json +3566 -0
  15. package/skills/ai-platform-governance/SKILL.md +21 -166
  16. package/skills/ai-platform-governance/references/progressive-01-/345/212/237/350/203/275/345/274/200/345/205/263.md +190 -0
  17. package/skills/microi-client-frontend/SKILL.md +17 -434
  18. package/skills/microi-client-frontend/references/progressive-01-3-/345/212/250/346/200/201/346/214/211/351/222/256/347/263/273/347/273/237.md +144 -0
  19. package/skills/microi-client-frontend/references/progressive-02-8-/350/277/220/350/241/214/346/227/266/351/253/230/351/242/221/345/235/221/345/244/215/347/233/230.md +178 -0
  20. package/skills/microi-client-frontend/references/progressive-03-vue3-/345/211/215/347/253/257/345/276/256/346/234/215/345/212/241/345/256/277/344/270/273/350/247/204/345/210/231.md +144 -0
  21. package/skills/microi-db-schema/SKILL.md +3 -3
  22. package/skills/microi-db-schema/references/schema-overview.md +1 -1
  23. package/skills/microi-db-schema/references/schema.md +1 -1
  24. package/skills/microi-db-schema/references/table-catalog.md +1 -1
  25. package/skills/microi-form-engine/SKILL.md +1 -1
  26. package/skills/microi-form-layout/SKILL.md +19 -225
  27. package/skills/microi-form-layout/references/progressive-01-3-/344/270/211/347/247/215/345/210/206/347/273/204/347/232/204/345/255/230/345/202/250/344/270/216/351/205/215/347/275/256.md +235 -0
  28. package/skills/microi-frontend-sdk/SKILL.md +17 -151
  29. package/skills/microi-frontend-sdk/references/progressive-01-token-/345/275/223/345/211/215/347/231/273/345/275/225/347/224/250/346/210/267/344/270/216/345/275/223/345/211/215/347/273/210/347/253/257/347/231/273/345/275/225/345/215/217/350/256/256.md +171 -0
  30. package/skills/microi-mobile-app-quality/SKILL.md +22 -288
  31. package/skills/microi-mobile-app-quality/references/progressive-01-4-/351/207/215/350/246/201/346/214/211/351/222/256/345/277/205/351/241/273/345/270/246/345/233/276/346/240/207.md +209 -0
  32. package/skills/microi-mobile-app-quality/references/progressive-02-9-/344/270/273/351/242/230/345/210/207/346/215/242/345/277/205/351/241/273/347/234/237/345/256/236/344/270/224/345/205/250/345/261/200/347/224/237/346/225/210.md +117 -0
  33. package/skills/microi-system-delivery/SKILL.md +16 -380
  34. package/skills/microi-system-delivery/references/progressive-01-/346/240/207/345/207/206/345/267/245/344/275/234/346/265/201.md +186 -0
  35. package/skills/microi-system-delivery/references/progressive-02-/350/207/252/345/212/250/345/214/226/346/265/213/350/257/225/345/277/205/351/241/273/350/246/206/347/233/226/347/232/204/345/235/221.md +210 -0
  36. package/skills/microi-ui/SKILL.md +19 -169
  37. package/skills/microi-ui/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/234/272/346/231/257/350/223/235/345/233/276.md +183 -0
  38. package/skills/microi-uniapp-frontend/SKILL.md +26 -335
  39. package/skills/microi-uniapp-frontend/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/210/206/347/261/273-/345/217/214/346/240/217/345/210/227/350/241/250/347/213/254/347/253/213/346/273/232/345/212/250.md +225 -0
  40. package/skills/microi-uniapp-frontend/references/progressive-02-/345/205/263/351/224/256/344/270/232/345/212/241/350/265/204/344/272/247/344/270/215/345/276/227/351/273/230/350/256/244/351/200/211/344/270/255.md +154 -0
  41. package/skills/page-engine/SKILL.md +23 -271
  42. package/skills/page-engine/references/progressive-01-/346/211/200/346/234/211/347/273/204/344/273/266/347/261/273/345/236/213.md +234 -0
  43. package/skills/page-engine/references/progressive-02-/347/211/210/346/234/254/345/216/206/345/217/262-/345/271/266/345/217/221/344/277/235/345/255/230/344/270/216/345/233/236/346/273/232.md +60 -0
  44. package/skills/playwright-e2e/SKILL.md +24 -590
  45. package/skills/playwright-e2e/references/progressive-01-/345/205/250/350/207/252/345/212/250/347/231/273/345/275/225-/345/205/215/351/252/214/350/257/201/347/240/201-/344/275/206/344/270/215/345/205/215/345/257/206/347/240/201-/345/277/205/350/257/273.md +173 -0
  46. package/skills/playwright-e2e/references/progressive-02-/346/226/207/345/255/227/345/257/271/346/257/224/345/272/246/344/270/216/345/217/257/350/257/273/346/200/247/350/207/252/345/212/250/345/214/226/346/243/200/346/237/245-/345/277/205/345/201/232.md +183 -0
  47. package/skills/playwright-e2e/references/progressive-03-microi-helper-/346/250/241/346/235/277.md +221 -0
  48. package/skills/playwright-e2e/references/progressive-04-ci-/345/273/272/350/256/256.md +69 -0
  49. package/skills/scripts/optimize-progressive-disclosure.mjs +204 -0
  50. package/skills/scripts/refresh-progressive-disclosure.mjs +64 -0
  51. package/skills/scripts/validate-progressive-disclosure.mjs +52 -0
  52. package/skills/ui-design/SKILL.md +26 -1461
  53. package/skills/ui-design/references/progressive-01-/351/242/234/350/211/262/344/275/223/347/263/273-css-variables-/346/224/257/346/214/201/344/270/273/351/242/230/345/210/207/346/215/242.md +218 -0
  54. package/skills/ui-design/references/progressive-02-/345/255/227/344/275/223.md +155 -0
  55. package/skills/ui-design/references/progressive-03-/345/212/250/346/225/210/350/247/204/350/214/203-/344/270/260/345/257/214/344/275/206/344/270/215/345/215/241.md +235 -0
  56. package/skills/ui-design/references/progressive-04-/347/273/204/344/273/266/351/243/216/346/240/274/351/200/237/346/237/245.md +152 -0
  57. package/skills/ui-design/references/progressive-05-/347/247/273/345/212/250/347/253/257/344/270/223/347/224/250/350/247/204/350/214/203.md +238 -0
  58. package/skills/ui-design/references/progressive-06-/344/270/273/351/242/230/345/210/207/346/215/242/345/256/236/347/216/260.md +194 -0
  59. package/skills/ui-design/references/progressive-07-/351/200/237/346/237/245-/344/273/216/345/244/264/346/220/255/345/273/272/344/270/200/344/270/252/347/247/273/345/212/250/347/253/257/351/241/265/351/235/242.md +207 -0
  60. package/skills/ui-design/references/progressive-08-/350/241/250/345/215/225/345/210/206/347/273/204/350/247/204/350/214/203-tabs-vs-collapsegroup-/345/274/272/345/210/266.md +142 -0
  61. package/skills/v8-crud-api/SKILL.md +20 -245
  62. package/skills/v8-crud-api/references/progressive-01-/346/237/245/350/257/242/345/210/227/350/241/250-/345/210/206/351/241/265.md +226 -0
  63. package/skills/v8-crud-api/references/progressive-02-where-/346/235/241/344/273/266/350/257/255/346/263/225/351/200/237/346/237/245.md +49 -0
  64. package/skills/v8-export-import/SKILL.md +15 -425
  65. package/skills/v8-export-import/references/progressive-01-excellayout-/351/253/230/347/272/247/350/207/252/347/224/261/345/270/203/345/261/200.md +211 -0
  66. package/skills/v8-export-import/references/progressive-02-powerpoint-/345/257/274/345/207/272.md +202 -0
  67. package/skills/v8-export-import/references/progressive-03-/345/256/211/345/205/250-/346/200/247/350/203/275/346/263/250/346/204/217.md +42 -0
  68. package/skills/v8-file-upload/SKILL.md +16 -354
  69. package/skills/v8-file-upload/references/progressive-01-/345/205/254/346/234/211/346/241/266-vs-/347/247/201/346/234/211/346/241/266.md +227 -0
  70. package/skills/v8-file-upload/references/progressive-02-office-/346/226/207/344/273/266/345/234/250/347/272/277/347/274/226/350/276/221/347/211/210/346/234/254/345/217/267/350/247/204/345/210/231.md +149 -0
  71. package/skills/v8-frontend-events/SKILL.md +19 -205
  72. package/skills/v8-frontend-events/references/progressive-01-/345/210/227/350/241/250/344/272/213/344/273/266.md +219 -0
  73. package/skills/v8-http-integration/SKILL.md +14 -236
  74. package/skills/v8-http-integration/references/progressive-01-get-/350/257/267/346/261/202.md +220 -0
  75. package/skills/v8-http-integration/references/progressive-02-/351/224/231/350/257/257/345/244/204/347/220/206/346/250/241/345/274/217.md +44 -0
  76. package/skills/v8-menu-buttons/SKILL.md +15 -511
  77. package/skills/v8-menu-buttons/references/progressive-01-2-/346/214/211/351/222/256/345/257/271/350/261/241-schema.md +221 -0
  78. package/skills/v8-menu-buttons/references/progressive-02-8-/346/250/241/345/274/217-f-/345/220/216/345/217/260/344/273/273/345/212/241/346/214/211/351/222/256-/351/225/277/344/273/273/345/212/241.md +224 -0
  79. package/skills/v8-menu-buttons/references/progressive-03-10-/345/217/215/346/250/241/345/274/217-/351/201/277/345/205/215.md +104 -0
  80. package/skills/v8-mq-mqtt/SKILL.md +11 -175
  81. package/skills/v8-mq-mqtt/references/progressive-01-v8-mqtt-iot-/347/211/251/350/201/224/347/275/221.md +181 -0
  82. package/skills/v8-security/SKILL.md +16 -329
  83. package/skills/v8-security/references/progressive-01-2-/346/235/203/351/231/220/346/240/241/351/252/214.md +199 -0
  84. package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +158 -0
  85. package/skills/v8-table-event/SKILL.md +16 -236
  86. package/skills/v8-table-event/references/progressive-01-informv8-js-/350/241/250/345/215/225/346/211/223/345/274/200/344/272/213/344/273/266.md +216 -0
  87. package/skills/v8-table-event/references/progressive-02-/345/211/215/347/253/257/344/272/213/344/273/266/345/220/215-v8-eventname-/345/217/257/350/203/275/347/232/204/345/200/274.md +46 -0
  88. package/skills/v8-workflow/SKILL.md +19 -160
  89. package/skills/v8-workflow/references/progressive-01-/350/212/202/347/202/271/345/274/200/345/247/213-v8-/344/272/213/344/273/266.md +180 -0
  90. package/skills/workspace-conventions/SKILL.md +29 -361
  91. package/skills/workspace-conventions/references/progressive-01-/347/211/210/346/234/254/346/233/264/346/226/260/346/227/245/345/277/227/344/277/235/346/212/244/350/247/204/345/210/231-/345/274/272/345/210/266.md +208 -0
  92. package/skills/workspace-conventions/references/progressive-02-microi-net-api-/346/234/254/345/234/260/345/220/257/345/212/250/347/272/246/345/256/232.md +196 -0
  93. package/skills/workspace-conventions/references/progressive-03-cli-/344/270/216-ide-/346/217/222/344/273/266/351/224/231/347/211/210/345/205/261/345/255/230/347/272/246/345/256/232.md +27 -0
@@ -10,6 +10,7 @@
10
10
  const childProcess = require('node:child_process');
11
11
  const crypto = require('node:crypto');
12
12
  const fs = require('node:fs');
13
+ const net = require('node:net');
13
14
  const os = require('node:os');
14
15
  const path = require('node:path');
15
16
 
@@ -18,13 +19,14 @@ const CONFIG_FILE = '.microi-config.json';
18
19
  const TOKEN_FILE = '.microi-mcp-tokens.json';
19
20
  const PROTOCOL_VERSION = '2024-11-05';
20
21
  const pluginRoot = path.resolve(__dirname, '..');
21
- const mcpServerPath = path.join(__dirname, 'mcp-server.js');
22
+ const mcpServerPath = path.resolve(process.env.MICROI_MCP_SERVER_PATH || path.join(__dirname, 'mcp-server.js'));
23
+ const brokerScriptPath = path.resolve(process.env.MICROI_CODEX_BROKER_SCRIPT || path.join(__dirname, 'microi-codex-broker.js'));
22
24
  const packagePath = path.join(pluginRoot, 'package.json');
23
- const pluginVersion = readJson(packagePath, {}).version || '0.0.0';
24
- const children = new Map();
25
+ const pluginVersion = process.env.MICROI_TOOL_VERSION || readJson(packagePath, {}).version || '0.0.0';
25
26
  let inputBuffer = '';
26
27
  let requestSequence = 0;
27
28
  let shuttingDown = false;
29
+ let brokerClient = null;
28
30
 
29
31
  function readJson(filePath, fallback) {
30
32
  try {
@@ -231,56 +233,102 @@ function buildApplicationsDir(profile) {
231
233
  return path.join(profile.syncRoot, serverDir, osClientDir, 'AI应用');
232
234
  }
233
235
 
234
- function deviceId() {
235
- const raw = `MCP:${os.hostname() || 'Unknown'}`;
236
- if (/^[\x20-\x7E]{1,128}$/.test(raw)) return raw;
237
- return `MCP-${crypto.createHash('sha256').update(raw).digest('hex').slice(0, 16)}`;
236
+ function brokerCoordinates(workspace) {
237
+ const normalizedRoot = process.platform === 'win32'
238
+ ? workspace.workspaceRoot.toLowerCase()
239
+ : workspace.workspaceRoot;
240
+ const key = crypto.createHash('sha256').update(`${normalizedRoot}\0${pluginVersion}`).digest('hex').slice(0, 24);
241
+ const runtimeRoot = path.resolve(process.env.MICROI_RUNTIME_HOME || path.join(os.homedir(), '.microi', 'runtime'));
242
+ const endpoint = process.env.MICROI_CODEX_BROKER_ENDPOINT || (process.platform === 'win32'
243
+ ? `\\\\.\\pipe\\microi-codex-${key}`
244
+ : path.join(runtimeRoot, 'brokers', `${key}.sock`));
245
+ return {
246
+ endpoint,
247
+ leasePath: path.resolve(process.env.MICROI_CODEX_BROKER_LEASE || path.join(runtimeRoot, 'leases', `microi-codex-${key}.json`)),
248
+ workspaceRoot: workspace.workspaceRoot,
249
+ };
250
+ }
251
+
252
+ function wait(milliseconds) {
253
+ return new Promise(resolve => setTimeout(resolve, milliseconds));
254
+ }
255
+
256
+ function readBrokerToken(leasePath) {
257
+ const lease = readJson(leasePath, {});
258
+ return typeof lease.token === 'string' ? lease.token : '';
238
259
  }
239
260
 
240
- class ChildMcp {
241
- constructor(profile) {
242
- this.profile = profile;
261
+ class SharedBrokerClient {
262
+ constructor(workspace) {
263
+ this.coordinates = brokerCoordinates(workspace);
243
264
  this.pending = new Map();
244
265
  this.buffer = '';
245
- this.ready = this.start();
266
+ this.closed = false;
267
+ this.spawnAttempted = false;
268
+ this.ready = this.connect();
246
269
  }
247
270
 
248
- async start() {
249
- if (!fs.existsSync(mcpServerPath)) {
250
- throw new Error(`Codex Plugin 缺少 MCP bundle:${mcpServerPath}`);
271
+ startBroker() {
272
+ if (!fs.existsSync(brokerScriptPath)) {
273
+ throw new Error(`Codex Plugin 缺少共享 Broker:${brokerScriptPath}`);
251
274
  }
252
- this.child = childProcess.spawn(process.execPath, [mcpServerPath], {
253
- cwd: this.profile.workspaceRoot,
275
+ const child = childProcess.spawn(process.execPath, [brokerScriptPath], {
276
+ cwd: pluginRoot,
277
+ detached: true,
254
278
  windowsHide: true,
255
- stdio: ['pipe', 'pipe', 'pipe'],
279
+ stdio: 'ignore',
256
280
  env: {
257
281
  ...process.env,
258
- MICROI_API_URL: this.profile.apiBaseUrl,
259
- MICROI_TOKEN_FILE: this.profile.tokenPath,
260
- MICROI_AUTH_RECOVERY_DIR: `${this.profile.tokenPath}.recovery`,
261
- MICROI_OS_CLIENT: this.profile.osClient,
262
- MICROI_OS_CLIENT_TYPE: this.profile.osClientType,
263
- MICROI_OS_CLIENT_NETWORK: this.profile.osClientNetwork,
264
- MICROI_WORKSPACE_ROOT: this.profile.workspaceRoot,
265
- MICROI_SYNC_ROOT: this.profile.syncRoot,
266
- MICROI_AI_APPLICATIONS_DIR: buildApplicationsDir(this.profile),
267
- MICROI_LABEL_BASE64: Buffer.from(this.profile.label, 'utf8').toString('base64'),
268
- MICROI_MCP_DID: deviceId(),
269
- MICROI_TOOL_SOURCE: 'codex-plugin',
282
+ MICROI_CODEX_BROKER_ENDPOINT: this.coordinates.endpoint,
283
+ MICROI_CODEX_BROKER_LEASE: this.coordinates.leasePath,
284
+ MICROI_WORKSPACE_ROOT: this.coordinates.workspaceRoot,
285
+ MICROI_MCP_SERVER_PATH: mcpServerPath,
270
286
  MICROI_TOOL_VERSION: pluginVersion,
271
- MICROI_CODEX_MODE: '1',
272
287
  },
273
288
  });
274
- this.child.stdout.on('data', chunk => this.onData(chunk));
275
- this.child.stderr.on('data', chunk => process.stderr.write(`[${this.profile.name}] ${chunk}`));
276
- this.child.on('error', error => this.rejectAll(error));
277
- this.child.on('exit', code => this.rejectAll(new Error(`Microi MCP ${this.profile.name} 已退出(${code ?? 'unknown'})`)));
278
- await this.request('initialize', {
279
- protocolVersion: PROTOCOL_VERSION,
280
- capabilities: {},
281
- clientInfo: { name: 'microi-codex-plugin-router', version: pluginVersion },
282
- }, true);
283
- this.notify('notifications/initialized', {});
289
+ child.on('error', () => { /* connect retry reports the actionable failure */ });
290
+ child.unref();
291
+ }
292
+
293
+ openSocket() {
294
+ return new Promise((resolve, reject) => {
295
+ const socket = net.createConnection(this.coordinates.endpoint);
296
+ const fail = error => {
297
+ socket.destroy();
298
+ reject(error);
299
+ };
300
+ socket.once('error', fail);
301
+ socket.once('connect', () => {
302
+ socket.off('error', fail);
303
+ this.socket = socket;
304
+ socket.setEncoding('utf8');
305
+ socket.on('data', chunk => this.onData(chunk));
306
+ socket.on('error', error => this.rejectAll(error));
307
+ socket.on('close', () => {
308
+ this.closed = true;
309
+ this.rejectAll(new Error('Microi shared broker disconnected'));
310
+ });
311
+ resolve();
312
+ });
313
+ });
314
+ }
315
+
316
+ async connect() {
317
+ let lastError;
318
+ for (let attempt = 0; attempt < 50; attempt += 1) {
319
+ try {
320
+ await this.openSocket();
321
+ return;
322
+ } catch (error) {
323
+ lastError = error;
324
+ if (!this.spawnAttempted || attempt === 15) {
325
+ this.spawnAttempted = true;
326
+ this.startBroker();
327
+ }
328
+ await wait(Math.min(40 + attempt * 12, 250));
329
+ }
330
+ }
331
+ throw new Error(`无法连接 Microi 共享 Broker:${lastError instanceof Error ? lastError.message : String(lastError)}`);
284
332
  }
285
333
 
286
334
  onData(chunk) {
@@ -296,7 +344,7 @@ class ChildMcp {
296
344
  const pending = this.pending.get(String(message.id));
297
345
  if (!pending) continue;
298
346
  this.pending.delete(String(message.id));
299
- if (message.error) pending.reject(new Error(message.error.message || JSON.stringify(message.error)));
347
+ if (message.error) pending.reject(new Error(typeof message.error === 'string' ? message.error : (message.error.message || JSON.stringify(message.error))));
300
348
  else pending.resolve(message.result);
301
349
  }
302
350
  }
@@ -306,37 +354,42 @@ class ChildMcp {
306
354
  this.pending.clear();
307
355
  }
308
356
 
309
- write(message) {
310
- if (!this.child || this.child.stdin.destroyed) throw new Error(`Microi MCP ${this.profile.name} 不可用`);
311
- this.child.stdin.write(`${JSON.stringify(message)}\n`);
312
- }
313
-
314
- request(method, params, skipReady = false) {
357
+ request(profile, method, params) {
315
358
  return (async () => {
316
- if (!skipReady) await this.ready;
359
+ await this.ready;
360
+ if (this.closed || !this.socket || this.socket.destroyed) throw new Error('Microi shared broker is unavailable');
361
+ let auth = '';
362
+ for (let attempt = 0; attempt < 10 && !auth; attempt += 1) {
363
+ auth = readBrokerToken(this.coordinates.leasePath);
364
+ if (!auth) await wait(25);
365
+ }
366
+ if (!auth) throw new Error('Microi shared broker lease is unavailable');
317
367
  const id = `router-${process.pid}-${++requestSequence}`;
318
368
  const response = new Promise((resolve, reject) => this.pending.set(id, { resolve, reject }));
319
- this.write({ jsonrpc: '2.0', id, method, params });
369
+ this.socket.write(`${JSON.stringify({
370
+ id,
371
+ auth,
372
+ type: 'request',
373
+ profile: { ...profile, applicationsDir: buildApplicationsDir(profile) },
374
+ method,
375
+ params,
376
+ })}\n`);
320
377
  return response;
321
378
  })();
322
379
  }
323
380
 
324
- notify(method, params) {
325
- this.write({ jsonrpc: '2.0', method, params });
381
+ close() {
382
+ try { this.socket?.end(); } catch { /* best effort */ }
326
383
  }
384
+ }
327
385
 
328
- stop() {
329
- try { this.child?.stdin.end(); } catch { /* best effort */ }
330
- try { this.child?.kill('SIGTERM'); } catch { /* best effort */ }
331
- }
386
+ function sharedBroker(profile) {
387
+ if (!brokerClient || brokerClient.closed) brokerClient = new SharedBrokerClient({ workspaceRoot: profile.workspaceRoot });
388
+ return brokerClient;
332
389
  }
333
390
 
334
- function childFor(profile) {
335
- const existing = children.get(profile.identity);
336
- if (existing) return existing;
337
- const child = new ChildMcp(profile);
338
- children.set(profile.identity, child);
339
- return child;
391
+ function requestThroughBroker(profile, method, params) {
392
+ return sharedBroker(profile).request(profile, method, params);
340
393
  }
341
394
 
342
395
  function resultText(value, isError = false) {
@@ -378,7 +431,7 @@ async function callRouterTool(args) {
378
431
  }
379
432
  try {
380
433
  const profile = selectProfile(args?.profile);
381
- return await childFor(profile).request('tools/call', {
434
+ return await requestThroughBroker(profile, 'tools/call', {
382
435
  name: 'microi_codex',
383
436
  arguments: { action, params: args?.params || {} },
384
437
  });
@@ -421,7 +474,7 @@ async function readResource(uri) {
421
474
  const raw = decodeURIComponent(match[4] || '');
422
475
  params = raw ? JSON.parse(raw) : {};
423
476
  }
424
- const result = await childFor(profile).request('tools/call', {
477
+ const result = await requestThroughBroker(profile, 'tools/call', {
425
478
  name: 'microi_codex',
426
479
  arguments: { action, params },
427
480
  });
@@ -482,8 +535,8 @@ async function handle(message) {
482
535
  function shutdown() {
483
536
  if (shuttingDown) return;
484
537
  shuttingDown = true;
485
- for (const child of children.values()) child.stop();
486
- children.clear();
538
+ brokerClient?.close();
539
+ brokerClient = null;
487
540
  }
488
541
 
489
542
  process.stdin.setEncoding('utf8');
@@ -506,5 +559,16 @@ process.stdin.on('data', chunk => {
506
559
  });
507
560
  process.stdin.on('end', () => { shutdown(); process.exit(0); });
508
561
  process.stdin.on('error', () => { shutdown(); process.exit(1); });
562
+ process.stdout.on('error', error => { shutdown(); process.exit(error?.code === 'EPIPE' ? 0 : 1); });
563
+ process.on('disconnect', () => { shutdown(); process.exit(0); });
509
564
  for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) process.on(signal, () => { shutdown(); process.exit(0); });
510
565
  process.on('exit', shutdown);
566
+
567
+ const parentPid = process.ppid;
568
+ if (parentPid > 1) {
569
+ const parentWatchTimer = setInterval(() => {
570
+ try { process.kill(parentPid, 0); }
571
+ catch (error) { if (error?.code === 'ESRCH') { shutdown(); process.exit(0); } }
572
+ }, 5000);
573
+ parentWatchTimer.unref();
574
+ }