chrome-ai-bridge 2.3.3 → 2.3.4

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.
@@ -73,9 +73,10 @@ export function getIpcGuardConfig() {
73
73
  sessionIdleMs: Number(process.env.CAI_IPC_SESSION_IDLE_MS),
74
74
  startupDelayJitterMs: Number(process.env.CAI_STARTUP_DELAY_JITTER_MS),
75
75
  startupProcessThreshold: Number(process.env.CAI_STARTUP_PROCESS_THRESHOLD),
76
+ primaryIdleMs: Number(process.env.CAI_PRIMARY_IDLE_MS),
76
77
  };
77
78
  return {
78
- maxSessions: raw.maxSessions > 0 ? Math.floor(raw.maxSessions) : 16,
79
+ maxSessions: raw.maxSessions > 0 ? Math.floor(raw.maxSessions) : 6,
79
80
  maxQueue: raw.maxQueue > 0 ? Math.floor(raw.maxQueue) : 64,
80
81
  queueWaitTimeoutMs: raw.queueWaitTimeoutMs > 0 ? Math.floor(raw.queueWaitTimeoutMs) : 10_000,
81
82
  sessionIdleMs: raw.sessionIdleMs > 0 ? Math.floor(raw.sessionIdleMs) : 300_000,
@@ -83,5 +84,6 @@ export function getIpcGuardConfig() {
83
84
  startupProcessThreshold: raw.startupProcessThreshold > 0
84
85
  ? Math.floor(raw.startupProcessThreshold)
85
86
  : 8,
87
+ primaryIdleMs: raw.primaryIdleMs > 0 ? Math.floor(raw.primaryIdleMs) : 300_000,
86
88
  };
87
89
  }
package/build/src/main.js CHANGED
@@ -138,6 +138,11 @@ if (!becamePrimary) {
138
138
  process.exit(1);
139
139
  }
140
140
  // ─── Primary mode ───
141
+ // Idle auto-exit tracking for Primary process
142
+ let primaryLastActivityAt = Date.now();
143
+ const touchPrimaryActivity = () => {
144
+ primaryLastActivityAt = Date.now();
145
+ };
141
146
  // Start session cleanup timer
142
147
  const sessionConfig = getSessionConfig();
143
148
  const cleanupTimer = setInterval(async () => {
@@ -172,6 +177,7 @@ function registerTool(tool) {
172
177
  inputSchema: tool.schema,
173
178
  annotations: tool.annotations,
174
179
  }, async (params) => {
180
+ touchPrimaryActivity();
175
181
  const guard = await toolMutex.acquire();
176
182
  try {
177
183
  logger(`${tool.name} request: ${JSON.stringify(params, null, ' ')}`);
@@ -368,6 +374,7 @@ logDisclaimers();
368
374
  return;
369
375
  }
370
376
  let ipcTransport;
377
+ touchPrimaryActivity();
371
378
  if (sessionId && ipcTransports[sessionId]) {
372
379
  ipcTransport = ipcTransports[sessionId];
373
380
  touchIpcSession(sessionId);
@@ -439,6 +446,7 @@ logDisclaimers();
439
446
  res.writeHead(400).end('Invalid or missing session ID');
440
447
  return;
441
448
  }
449
+ touchPrimaryActivity();
442
450
  touchIpcSession(sessionId);
443
451
  try {
444
452
  await ipcTransports[sessionId].handleRequest(req, res);
@@ -481,6 +489,16 @@ logDisclaimers();
481
489
  }
482
490
  });
483
491
  ipcServer.listen(IPC_CONFIG.port, IPC_CONFIG.host, onListening);
492
+ // Primary idle auto-exit: exit when no activity and no active IPC sessions
493
+ const primaryIdleCheckTimer = setInterval(() => {
494
+ const activeSessionCount = Object.keys(ipcTransports).length;
495
+ if (Date.now() - primaryLastActivityAt > ipcGuardConfig.primaryIdleMs &&
496
+ activeSessionCount === 0) {
497
+ logger(`[main] Primary idle for ${Math.round((Date.now() - primaryLastActivityAt) / 1000)}s with 0 active sessions. Auto-exiting.`);
498
+ shutdown('idle timeout');
499
+ }
500
+ }, 30_000);
501
+ primaryIdleCheckTimer.unref();
484
502
  }
485
503
  // Graceful shutdown handler with timeout
486
504
  // Based on review: タイムアウト必須、強制終了タイマー必要
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-ai-bridge",
3
- "version": "2.3.3",
3
+ "version": "2.3.4",
4
4
  "description": "MCP server bridging Chrome extension and AI assistants (ChatGPT, Gemini). Extension-only mode - no Puppeteer.",
5
5
  "type": "module",
6
6
  "bin": "./scripts/cli.mjs",