polydev-ai 1.2.14 → 1.2.15

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.
package/lib/cliManager.ts CHANGED
@@ -10,7 +10,6 @@ import * as path from 'path'
10
10
  import * as fs from 'fs'
11
11
  import * as os from 'os'
12
12
  const which = require('which')
13
- const shell = require('shelljs')
14
13
 
15
14
  const execAsync = promisify(exec)
16
15
 
@@ -20,8 +19,8 @@ export interface CLIProvider {
20
19
  executable: string
21
20
  versionCommand: string
22
21
  authCheckCommand: string
23
- chatCommand: string
24
- supportsStdin: boolean
22
+ chatCommand: string | string[]
23
+ alternateChatCommands?: Array<string | string[]>
25
24
  supportsArgs: boolean
26
25
  installInstructions: string
27
26
  authInstructions: string
@@ -45,6 +44,7 @@ export interface CLIResponse {
45
44
  error?: string
46
45
  tokensUsed?: number
47
46
  latencyMs?: number
47
+ mode?: 'stdin' | 'args'
48
48
  }
49
49
 
50
50
  export class CLIManager {
@@ -64,8 +64,7 @@ export class CLIManager {
64
64
  executable: 'claude',
65
65
  versionCommand: 'claude --version',
66
66
  authCheckCommand: 'claude auth status',
67
- chatCommand: 'claude chat',
68
- supportsStdin: true,
67
+ chatCommand: ['claude', 'chat'],
69
68
  supportsArgs: true,
70
69
  installInstructions: 'Install via: npm install -g @anthropic-ai/claude-code',
71
70
  authInstructions: 'Authenticate with: claude auth login'
@@ -75,12 +74,16 @@ export class CLIManager {
75
74
  name: 'Codex CLI',
76
75
  executable: 'codex',
77
76
  versionCommand: 'codex --version',
78
- authCheckCommand: 'codex login --check', // Changed to check login status
79
- chatCommand: 'codex exec', // Changed from 'codex chat' to 'codex exec'
80
- supportsStdin: false, // Codex exec doesn't use stdin
77
+ authCheckCommand: 'codex auth status',
78
+ chatCommand: ['exec'],
79
+ alternateChatCommands: [
80
+ ['chat'],
81
+ ['prompt'],
82
+ ['ask']
83
+ ],
81
84
  supportsArgs: true,
82
- installInstructions: 'Install via: npm install -g codex-cli',
83
- authInstructions: 'Authenticate with: codex login'
85
+ installInstructions: 'Install Codex CLI from OpenAI',
86
+ authInstructions: 'Authenticate with: codex auth'
84
87
  },
85
88
  {
86
89
  id: 'gemini_cli',
@@ -88,8 +91,7 @@ export class CLIManager {
88
91
  executable: 'gemini',
89
92
  versionCommand: 'gemini --version',
90
93
  authCheckCommand: 'gemini auth status',
91
- chatCommand: 'gemini chat',
92
- supportsStdin: true,
94
+ chatCommand: ['gemini', 'chat'],
93
95
  supportsArgs: true,
94
96
  installInstructions: 'Install Gemini CLI from Google',
95
97
  authInstructions: 'Authenticate with: gemini auth login'
@@ -197,19 +199,56 @@ export class CLIManager {
197
199
  }
198
200
  }
199
201
 
202
+ if (providerId === 'codex_cli' && timeoutMs < 90000) {
203
+ timeoutMs = 90000
204
+ }
205
+
200
206
  const startTime = Date.now()
201
207
 
202
208
  try {
203
- let result: string
209
+ const commandVariants = [
210
+ this.normalizeCommand(provider.chatCommand),
211
+ ...(provider.alternateChatCommands || []).map(cmd => this.normalizeCommand(cmd))
212
+ ].filter(parts => parts.length > 0)
204
213
 
205
- if (mode === 'stdin' && provider.supportsStdin) {
206
- result = await this.sendPromptViaStdin(provider, prompt, timeoutMs)
207
- } else if (mode === 'args' && provider.supportsArgs) {
208
- result = await this.sendPromptViaArgs(provider, prompt, timeoutMs)
209
- } else {
214
+ if (commandVariants.length === 0) {
215
+ throw new Error(`${provider.name} does not have a valid chat command configured`)
216
+ }
217
+
218
+ if (provider.id === 'codex_cli') {
219
+ const execArgs = commandVariants.find(parts => parts.includes('exec')) || commandVariants[0]
220
+ const result = await this.executeCodexExec(provider.executable, execArgs, prompt, timeoutMs)
221
+ return {
222
+ success: true,
223
+ content: result,
224
+ latencyMs: Date.now() - startTime,
225
+ mode: 'args'
226
+ }
227
+ }
228
+
229
+ let result: string | undefined
230
+ let effectiveMode: 'stdin' | 'args' = 'args'
231
+ let lastError: Error | undefined
232
+
233
+ for (const commandParts of commandVariants) {
234
+ if (!provider.supportsArgs) {
235
+ lastError = new Error(`${provider.name} does not support args mode`)
236
+ continue
237
+ }
238
+
239
+ try {
240
+ result = await this.sendPromptViaArgs(commandParts, prompt, timeoutMs)
241
+ break
242
+ } catch (error) {
243
+ lastError = error instanceof Error ? error : new Error(String(error))
244
+ }
245
+ }
246
+
247
+ if (typeof result !== 'string') {
210
248
  return {
211
249
  success: false,
212
- error: `${provider.name} does not support ${mode} mode`
250
+ error: lastError?.message || 'CLI execution failed',
251
+ latencyMs: Date.now() - startTime
213
252
  }
214
253
  }
215
254
 
@@ -218,7 +257,8 @@ export class CLIManager {
218
257
  return {
219
258
  success: true,
220
259
  content: result,
221
- latencyMs
260
+ latencyMs,
261
+ mode: effectiveMode
222
262
  }
223
263
 
224
264
  } catch (error) {
@@ -310,67 +350,212 @@ export class CLIManager {
310
350
  }
311
351
  }
312
352
 
313
- /**
314
- * Send prompt via stdin mode
315
- */
316
- private async sendPromptViaStdin(
317
- provider: CLIProvider,
353
+ private normalizeCommand(command: string | string[]): string[] {
354
+ if (Array.isArray(command)) {
355
+ return command.map(part => part.trim()).filter(Boolean)
356
+ }
357
+ return command.split(/\s+/).map(part => part.trim()).filter(Boolean)
358
+ }
359
+
360
+ private async sendPromptViaArgs(
361
+ commandParts: string[],
318
362
  prompt: string,
319
363
  timeoutMs: number
320
364
  ): Promise<string> {
365
+ if (commandParts.length === 0) {
366
+ throw new Error('Invalid CLI command configuration')
367
+ }
368
+
369
+ const [executable, ...baseArgs] = commandParts
370
+ const args = [...baseArgs, prompt]
371
+
372
+ if (process.env.POLYDEV_CLI_DEBUG) {
373
+ console.log(`[CLI Debug] Executing (args) ${executable} ${args.join(' ')}`)
374
+ }
375
+
321
376
  return new Promise((resolve, reject) => {
322
- const child = spawn(provider.chatCommand, [], {
377
+ const baseTmp = process.env.POLYDEV_CLI_TMPDIR || process.env.TMPDIR || os.tmpdir()
378
+ const tmpDir = path.join(baseTmp, 'polydev-codex')
379
+ try {
380
+ fs.mkdirSync(tmpDir, { recursive: true })
381
+ } catch (error) {
382
+ console.warn('[CLI Debug] Failed to create Codex temp dir:', error)
383
+ }
384
+
385
+ const child = spawn(executable, args, {
323
386
  stdio: ['pipe', 'pipe', 'pipe'],
324
- timeout: timeoutMs
387
+ shell: process.platform === 'win32',
388
+ env: {
389
+ ...process.env,
390
+ TMPDIR: tmpDir,
391
+ TEMP: tmpDir,
392
+ TMP: tmpDir
393
+ }
325
394
  })
326
395
 
396
+ console.log(`[CLI Debug] Spawning Codex process: ${executable} ${args.join(' ')}`)
397
+
398
+ // No stdin needed for exec mode; close immediately to avoid hangs.
399
+ if (child.stdin) {
400
+ child.stdin.end()
401
+ }
402
+
327
403
  let stdout = ''
328
404
  let stderr = ''
405
+ let finished = false
406
+
407
+ const timeoutHandle = setTimeout(() => {
408
+ if (!finished) {
409
+ finished = true
410
+ try {
411
+ child.kill('SIGTERM')
412
+ setTimeout(() => {
413
+ if (!child.killed) {
414
+ child.kill('SIGKILL')
415
+ }
416
+ }, 1500)
417
+ } catch {}
418
+ reject(new Error(`CLI command timeout after ${timeoutMs}ms`))
419
+ }
420
+ }, timeoutMs)
329
421
 
330
- child.stdout?.on('data', (data) => {
422
+ child.stdout?.on('data', data => {
331
423
  stdout += data.toString()
332
424
  })
333
425
 
334
- child.stderr?.on('data', (data) => {
426
+ child.stderr?.on('data', data => {
335
427
  stderr += data.toString()
336
428
  })
337
429
 
338
- child.on('close', (code) => {
430
+ child.on('close', code => {
431
+ if (finished) return
432
+ finished = true
433
+ clearTimeout(timeoutHandle)
434
+
435
+ if (process.env.POLYDEV_CLI_DEBUG) {
436
+ console.log(`[CLI Debug] (args) exit code ${code}`)
437
+ if (stdout) console.log(`[CLI Debug] stdout: ${stdout.trim().slice(0, 500)}`)
438
+ if (stderr) console.log(`[CLI Debug] stderr: ${stderr.trim().slice(0, 500)}`)
439
+ }
440
+
441
+ const trimmedStdout = stdout.trim()
442
+ const trimmedStderr = stderr.trim()
443
+
339
444
  if (code === 0) {
340
- resolve(stdout.trim())
445
+ resolve(trimmedStdout || trimmedStderr)
341
446
  } else {
342
- reject(new Error(`CLI exited with code ${code}: ${stderr}`))
447
+ const message = trimmedStderr || trimmedStdout || `CLI command failed (code ${code})`
448
+ reject(new Error(message))
343
449
  }
344
450
  })
345
451
 
346
- child.on('error', (error) => {
452
+ child.on('error', error => {
453
+ if (finished) return
454
+ finished = true
455
+ clearTimeout(timeoutHandle)
347
456
  reject(error)
348
457
  })
349
-
350
- // Send prompt via stdin
351
- if (child.stdin) {
352
- child.stdin.write(prompt)
353
- child.stdin.end()
354
- }
355
458
  })
356
459
  }
357
460
 
358
- /**
359
- * Send prompt via command arguments
360
- */
361
- private async sendPromptViaArgs(
362
- provider: CLIProvider,
461
+ private async executeCodexExec(
462
+ executable: string,
463
+ commandArgs: string[],
363
464
  prompt: string,
364
465
  timeoutMs: number
365
466
  ): Promise<string> {
366
- const command = `${provider.chatCommand} "${prompt.replace(/"/g, '\\"')}"`
367
-
368
- try {
369
- const { stdout } = await execAsync(command, { timeout: timeoutMs })
370
- return stdout.trim()
371
- } catch (error) {
372
- throw new Error(`CLI command failed: ${error}`)
467
+ if (!executable) {
468
+ throw new Error('Missing Codex executable')
373
469
  }
470
+
471
+ if (!commandArgs || commandArgs.length === 0) {
472
+ throw new Error('Invalid Codex command configuration')
473
+ }
474
+
475
+ const workingDir = process.cwd()
476
+ const args = [
477
+ ...commandArgs,
478
+ '--sandbox',
479
+ 'workspace-write',
480
+ '--skip-git-repo-check',
481
+ '--cd',
482
+ workingDir,
483
+ prompt
484
+ ]
485
+
486
+ return new Promise((resolve, reject) => {
487
+ const child = spawn(executable, args, {
488
+ stdio: ['pipe', 'pipe', 'pipe'],
489
+ shell: process.platform === 'win32'
490
+ })
491
+
492
+ if (child.stdin) {
493
+ child.stdin.end()
494
+ }
495
+
496
+ let stdout = ''
497
+ let stderr = ''
498
+ let resolved = false
499
+
500
+ const stop = (handler: () => void) => {
501
+ if (!resolved) {
502
+ resolved = true
503
+ try {
504
+ child.kill('SIGTERM')
505
+ } catch {}
506
+ handler()
507
+ }
508
+ }
509
+
510
+ const timeoutHandle = setTimeout(() => {
511
+ stop(() => reject(new Error(`Codex exec timeout after ${timeoutMs}ms`)))
512
+ }, timeoutMs)
513
+
514
+ const flushIfComplete = () => {
515
+ const bulletMatch = stdout.match(/•\s*(.+)/)
516
+ if (bulletMatch && bulletMatch[1]) {
517
+ const answer = bulletMatch[1].trim()
518
+ clearTimeout(timeoutHandle)
519
+ stop(() => resolve(answer))
520
+ }
521
+ }
522
+
523
+ child.stdout?.on('data', data => {
524
+ stdout += data.toString()
525
+ flushIfComplete()
526
+ })
527
+
528
+ child.stderr?.on('data', data => {
529
+ stderr += data.toString()
530
+ })
531
+
532
+ child.on('close', code => {
533
+ if (resolved) return
534
+ resolved = true
535
+ clearTimeout(timeoutHandle)
536
+
537
+ const trimmedStdout = stdout.trim()
538
+ const trimmedStderr = stderr.trim()
539
+
540
+ if (code === 0 && trimmedStdout) {
541
+ const bulletMatch = trimmedStdout.match(/•\s*(.+)/)
542
+ if (bulletMatch && bulletMatch[1]) {
543
+ resolve(bulletMatch[1].trim())
544
+ return
545
+ }
546
+ resolve(trimmedStdout)
547
+ } else {
548
+ reject(new Error(trimmedStderr || trimmedStdout || `Codex exited with code ${code}`))
549
+ }
550
+ })
551
+
552
+ child.on('error', error => {
553
+ if (resolved) return
554
+ resolved = true
555
+ clearTimeout(timeoutHandle)
556
+ reject(error)
557
+ })
558
+ })
374
559
  }
375
560
 
376
561
  /**
@@ -81,7 +81,7 @@ class ZeroKnowledgeEncryption {
81
81
  const keyData = cursor.value;
82
82
  // Check if key needs rotation
83
83
  if (new Date() > new Date(keyData.rotationDue)) {
84
- console.error('[ZK Encryption] Key rotation needed, generating new key');
84
+ console.log('[ZK Encryption] Key rotation needed, generating new key');
85
85
  await this.createAndStoreKey();
86
86
  }
87
87
  else {
@@ -214,7 +214,7 @@ class ZeroKnowledgeEncryption {
214
214
  */
215
215
  async rotateKeys() {
216
216
  await this.createAndStoreKey();
217
- console.error('[ZK Encryption] Key rotation completed');
217
+ console.log('[ZK Encryption] Key rotation completed');
218
218
  }
219
219
  /**
220
220
  * Generate unique key ID
@@ -274,7 +274,7 @@ class ZeroKnowledgeEncryption {
274
274
  await transaction.objectStore('keys').clear();
275
275
  await transaction.objectStore('cache').clear();
276
276
  this.activeKey = null;
277
- console.error('[ZK Encryption] All keys cleared');
277
+ console.log('[ZK Encryption] All keys cleared');
278
278
  }
279
279
  }
280
280
  exports.ZeroKnowledgeEncryption = ZeroKnowledgeEncryption;
@@ -286,4 +286,4 @@ ZeroKnowledgeEncryption.KEY_ROTATION_DAYS = 30;
286
286
  ZeroKnowledgeEncryption.DB_NAME = 'PolydevZKMemory';
287
287
  ZeroKnowledgeEncryption.DB_VERSION = 1;
288
288
  // Export singleton instance
289
- exports.zkEncryption = new ZeroKnowledgeEncryption();
289
+ exports.zkEncryption = new ZeroKnowledgeEncryption();
package/mcp/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-perspectives",
3
- "version": "1.2.14",
3
+ "version": "1.2.0",
4
4
  "description": "Agentic workflow assistant - get diverse perspectives from multiple LLMs when stuck or need enhanced reasoning",
5
5
  "author": "Polydev AI",
6
6
  "license": "MIT",
@@ -685,4 +685,4 @@
685
685
  "step_4": "Use the token in your MCP tool calls"
686
686
  }
687
687
  }
688
- }
688
+ }
package/mcp/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.2.8",
3
+ "version": "1.2.6",
4
4
  "description": "Get diverse AI perspectives from multiple LLMs via MCP - supports Cline, Claude Code, and other MCP clients",
5
5
  "main": "stdio-wrapper.js",
6
6
  "bin": {
@@ -43,4 +43,4 @@
43
43
  "bugs": {
44
44
  "url": "https://github.com/backspacevenkat/polydev-website/issues"
45
45
  }
46
- }
46
+ }
@@ -3,27 +3,56 @@
3
3
  // Lightweight stdio wrapper with local CLI functionality and remote Polydev MCP server fallback
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
+ const os = require('os');
6
7
  const { CLIManager } = require('../lib/cliManager');
7
8
 
9
+ function ensureWritableTmpDir() {
10
+ const candidates = [
11
+ process.env.POLYDEV_TMPDIR,
12
+ '/tmp/polydev',
13
+ '/tmp',
14
+ path.join(os.tmpdir(), 'polydev'),
15
+ path.join(process.cwd(), '.polydev-tmp')
16
+ ].filter(Boolean);
17
+
18
+ for (const candidate of candidates) {
19
+ try {
20
+ fs.mkdirSync(candidate, { recursive: true });
21
+ fs.accessSync(candidate, fs.constants.W_OK);
22
+ return candidate;
23
+ } catch (error) {
24
+ console.warn(`[Stdio Wrapper] TMP candidate not writable (${candidate}):`, error.message);
25
+ }
26
+ }
27
+
28
+ console.error('[Stdio Wrapper] No writable TMP directory found; Codex CLI will fail.');
29
+ return null;
30
+ }
31
+
32
+ const writableTmp = ensureWritableTmpDir();
33
+ if (writableTmp) {
34
+ process.env.TMPDIR = writableTmp;
35
+ process.env.TMP = writableTmp;
36
+ process.env.TEMP = writableTmp;
37
+ console.error(`[Stdio Wrapper] Using TMP directory: ${writableTmp}`);
38
+ }
39
+
8
40
  class StdioMCPWrapper {
9
41
  constructor() {
10
42
  this.userToken = process.env.POLYDEV_USER_TOKEN;
11
- // Don't exit immediately - wait for initialization to report error properly
12
-
13
- // Initialize CLI Manager for local CLI functionality (only if token exists)
14
- if (this.userToken) {
15
- this.cliManager = new CLIManager();
43
+ if (!this.userToken) {
44
+ console.error('POLYDEV_USER_TOKEN environment variable is required');
45
+ process.exit(1);
16
46
  }
17
47
 
48
+ // Initialize CLI Manager for local CLI functionality
49
+ this.cliManager = new CLIManager();
50
+
18
51
  // Load manifest for tool definitions
19
52
  this.loadManifest();
20
53
 
21
54
  // Smart refresh scheduler (will be started after initialization)
22
55
  this.refreshScheduler = null;
23
-
24
- // Track if initial CLI detection has been done
25
- this.initialDetectionDone = false;
26
- this.initialDetectionPromise = null;
27
56
  }
28
57
 
29
58
  loadManifest() {
@@ -69,18 +98,6 @@ class StdioMCPWrapper {
69
98
  };
70
99
 
71
100
  case 'tools/call':
72
- // Check if token is missing
73
- if (!this.userToken) {
74
- return {
75
- jsonrpc: '2.0',
76
- id,
77
- error: {
78
- code: -32603,
79
- message: 'POLYDEV_USER_TOKEN environment variable is required. Please add it to your MCP configuration.'
80
- }
81
- };
82
- }
83
-
84
101
  // Handle CLI tools locally, forward others to remote server
85
102
  const toolName = params.name;
86
103
  if (toolName.startsWith('polydev.') && this.isCliTool(toolName)) {
@@ -230,10 +247,6 @@ class StdioMCPWrapper {
230
247
  // Update database with CLI status
231
248
  await this.updateCliStatusInDatabase(results);
232
249
 
233
- // Mark initial detection as done
234
- this.initialDetectionDone = true;
235
- this.initialDetectionPromise = null;
236
-
237
250
  return {
238
251
  success: true,
239
252
  results,
@@ -244,10 +257,6 @@ class StdioMCPWrapper {
244
257
 
245
258
  } catch (error) {
246
259
  console.error('[Stdio Wrapper] Local CLI detection error:', error);
247
- // Mark as done even on error to prevent blocking
248
- this.initialDetectionDone = true;
249
- this.initialDetectionPromise = null;
250
-
251
260
  return {
252
261
  success: false,
253
262
  error: error.message,
@@ -309,16 +318,6 @@ class StdioMCPWrapper {
309
318
  console.error(`[Stdio Wrapper] Local CLI prompt sending with perspectives`);
310
319
 
311
320
  try {
312
- // Ensure initial CLI detection has completed before sending prompts
313
- if (!this.initialDetectionDone && this.initialDetectionPromise) {
314
- console.error('[Stdio Wrapper] Waiting for initial CLI detection to complete...');
315
- await this.initialDetectionPromise;
316
- } else if (!this.initialDetectionDone && !this.initialDetectionPromise) {
317
- console.error('[Stdio Wrapper] Running initial CLI detection before sending prompt...');
318
- this.initialDetectionPromise = this.localForceCliDetection({});
319
- await this.initialDetectionPromise;
320
- }
321
-
322
321
  let { provider_id, prompt, mode = 'args', timeout_ms = 30000 } = args;
323
322
 
324
323
  // Ensure timeout_ms is valid (not undefined, null, Infinity, or negative)
@@ -402,18 +401,7 @@ class StdioMCPWrapper {
402
401
  */
403
402
  async getAllAvailableProviders() {
404
403
  try {
405
- // Try to load from cache first to avoid re-detection
406
- const cachedStatus = await this.loadLocalCliStatus();
407
- let results;
408
-
409
- if (cachedStatus && Object.keys(cachedStatus).length > 0) {
410
- console.error('[Stdio Wrapper] Using cached CLI status');
411
- results = cachedStatus;
412
- } else {
413
- console.error('[Stdio Wrapper] No cached status, running detection');
414
- results = await this.cliManager.forceCliDetection();
415
- }
416
-
404
+ const results = await this.cliManager.forceCliDetection();
417
405
  const availableProviders = [];
418
406
 
419
407
  // Priority order: claude_code > codex_cli > gemini_cli
@@ -894,7 +882,19 @@ class StdioMCPWrapper {
894
882
  }
895
883
 
896
884
  async start() {
897
- console.error('[Stdio Wrapper] Starting Polydev Stdio MCP Wrapper...');
885
+ console.log('Starting Polydev Stdio MCP Wrapper...');
886
+
887
+ // Run initial CLI detection on startup
888
+ console.error('[Stdio Wrapper] Running initial CLI detection...');
889
+ try {
890
+ await this.localForceCliDetection({});
891
+ console.error('[Stdio Wrapper] Initial CLI detection completed');
892
+ } catch (error) {
893
+ console.error('[Stdio Wrapper] Initial CLI detection failed:', error);
894
+ }
895
+
896
+ // Start smart refresh scheduler for automatic updates
897
+ this.startSmartRefreshScheduler();
898
898
 
899
899
  process.stdin.setEncoding('utf8');
900
900
  let buffer = '';
@@ -919,46 +919,25 @@ class StdioMCPWrapper {
919
919
  });
920
920
 
921
921
  process.stdin.on('end', () => {
922
- console.error('[Stdio Wrapper] Shutting down...');
922
+ console.log('Stdio MCP Wrapper shutting down...');
923
923
  this.stopSmartRefreshScheduler();
924
924
  process.exit(0);
925
925
  });
926
926
 
927
927
  // Handle process signals
928
928
  process.on('SIGINT', () => {
929
- console.error('[Stdio Wrapper] Received SIGINT, shutting down...');
929
+ console.log('Received SIGINT, shutting down...');
930
930
  this.stopSmartRefreshScheduler();
931
931
  process.exit(0);
932
932
  });
933
933
 
934
934
  process.on('SIGTERM', () => {
935
- console.error('[Stdio Wrapper] Received SIGTERM, shutting down...');
935
+ console.log('Received SIGTERM, shutting down...');
936
936
  this.stopSmartRefreshScheduler();
937
937
  process.exit(0);
938
938
  });
939
939
 
940
- console.error('[Stdio Wrapper] Ready and listening on stdin...');
941
-
942
- // Run initial CLI detection AFTER stdin handler is set up
943
- if (this.userToken && this.cliManager) {
944
- console.error('[Stdio Wrapper] Scheduling initial CLI detection...');
945
- // Run asynchronously after a short delay to not block initialization
946
- setTimeout(async () => {
947
- console.error('[Stdio Wrapper] Running initial CLI detection...');
948
- try {
949
- this.initialDetectionPromise = this.localForceCliDetection({});
950
- await this.initialDetectionPromise;
951
- console.error('[Stdio Wrapper] Initial CLI detection completed');
952
- } catch (error) {
953
- console.error('[Stdio Wrapper] Initial CLI detection failed:', error);
954
- }
955
-
956
- // Start smart refresh scheduler for automatic updates
957
- this.startSmartRefreshScheduler();
958
- }, 100);
959
- } else {
960
- console.error('[Stdio Wrapper] No token provided - CLI detection disabled');
961
- }
940
+ console.log('Stdio MCP Wrapper ready and listening on stdin...');
962
941
  }
963
942
  }
964
943