stigmergy 1.0.97 → 1.0.98

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,16 +1,16 @@
1
1
  // Enhanced CLI Help Analyzer with better pattern extraction
2
- const { spawnSync } = require("child_process");
3
- const fs = require("fs/promises");
4
- const path = require("path");
5
- const os = require("os");
6
- const { CLI_TOOLS } = require("./cli_tools");
7
- const { errorHandler, ERROR_TYPES } = require("./error_handler");
2
+ const { spawnSync } = require('child_process');
3
+ const fs = require('fs/promises');
4
+ const path = require('path');
5
+ const os = require('os');
6
+ const { CLI_TOOLS } = require('./cli_tools');
7
+ const { errorHandler, ERROR_TYPES } = require('./error_handler');
8
8
 
9
9
  class CLIHelpAnalyzer {
10
10
  constructor() {
11
- this.configDir = path.join(os.homedir(), ".stigmergy", "cli-patterns");
12
- this.persistentConfig = path.join(this.configDir, "cli-patterns.json");
13
- this.lastAnalysisFile = path.join(this.configDir, "last-analysis.json");
11
+ this.configDir = path.join(os.homedir(), '.stigmergy', 'cli-patterns');
12
+ this.persistentConfig = path.join(this.configDir, 'cli-patterns.json');
13
+ this.lastAnalysisFile = path.join(this.configDir, 'last-analysis.json');
14
14
  this.cliTools = CLI_TOOLS;
15
15
 
16
16
  // Pattern recognition rules for different CLI types
@@ -69,7 +69,7 @@ class CLIHelpAnalyzer {
69
69
  const configExists = await this.fileExists(this.persistentConfig);
70
70
  if (!configExists) {
71
71
  await this.savePersistentConfig({
72
- version: "1.0.0",
72
+ version: '1.0.0',
73
73
  lastUpdated: new Date().toISOString(),
74
74
  cliPatterns: {},
75
75
  failedAttempts: {},
@@ -78,7 +78,7 @@ class CLIHelpAnalyzer {
78
78
 
79
79
  return true;
80
80
  } catch (error) {
81
- await errorHandler.logError(error, "ERROR", "CLIHelpAnalyzer.initialize");
81
+ await errorHandler.logError(error, 'ERROR', 'CLIHelpAnalyzer.initialize');
82
82
  return false;
83
83
  }
84
84
  }
@@ -91,14 +91,14 @@ class CLIHelpAnalyzer {
91
91
 
92
92
  for (const [cliName, cliConfig] of Object.entries(this.cliTools)) {
93
93
  try {
94
- if (process.env.DEBUG === "true") {
94
+ if (process.env.DEBUG === 'true') {
95
95
  console.log(`Analyzing ${cliName}...`);
96
96
  }
97
97
  results[cliName] = await this.analyzeCLI(cliName);
98
98
  } catch (error) {
99
99
  await errorHandler.logError(
100
100
  error,
101
- "WARN",
101
+ 'WARN',
102
102
  `CLIHelpAnalyzer.analyzeAllCLI.${cliName}`,
103
103
  );
104
104
  results[cliName] = { success: false, error: error.message };
@@ -165,36 +165,36 @@ class CLIHelpAnalyzer {
165
165
  */
166
166
  async getHelpInfo(cliName, cliConfig) {
167
167
  const helpMethods = [
168
- ["--help"],
169
- ["-h"],
170
- ["help"],
171
- ["--usage"],
172
- [""],
173
- ["version"],
174
- ["--version"],
175
- ["-v"],
168
+ ['--help'],
169
+ ['-h'],
170
+ ['help'],
171
+ ['--usage'],
172
+ [''],
173
+ ['version'],
174
+ ['--version'],
175
+ ['-v'],
176
176
  ];
177
177
 
178
- let rawHelp = "";
179
- let version = "unknown";
180
- let method = "unknown";
178
+ let rawHelp = '';
179
+ let version = 'unknown';
180
+ let method = 'unknown';
181
181
 
182
182
  // Try different help commands
183
183
  for (const helpArgs of helpMethods) {
184
184
  try {
185
185
  const result = spawnSync(cliName, helpArgs, {
186
- encoding: "utf8",
186
+ encoding: 'utf8',
187
187
  timeout: 15000,
188
188
  shell: true,
189
189
  });
190
190
 
191
191
  if (result.status === 0 && result.stdout) {
192
192
  rawHelp = result.stdout;
193
- method = `${cliName} ${helpArgs.join(" ")}`;
193
+ method = `${cliName} ${helpArgs.join(' ')}`;
194
194
  break;
195
195
  } else if (result.stderr) {
196
196
  rawHelp = result.stderr;
197
- method = `${cliName} ${helpArgs.join(" ")} (stderr)`;
197
+ method = `${cliName} ${helpArgs.join(' ')} (stderr)`;
198
198
  break;
199
199
  }
200
200
  } catch (error) {
@@ -206,9 +206,9 @@ class CLIHelpAnalyzer {
206
206
  // Try to get version separately
207
207
  if (cliConfig.version) {
208
208
  try {
209
- const versionCmd = cliConfig.version.split(" ");
209
+ const versionCmd = cliConfig.version.split(' ');
210
210
  const versionResult = spawnSync(versionCmd[0], versionCmd.slice(1), {
211
- encoding: "utf8",
211
+ encoding: 'utf8',
212
212
  timeout: 10000,
213
213
  shell: true,
214
214
  });
@@ -236,41 +236,41 @@ class CLIHelpAnalyzer {
236
236
  const name = cliName.toLowerCase();
237
237
 
238
238
  // Detect based on CLI name
239
- if (name.includes("claude") || name.includes("anthropic")) {
240
- return "anthropic";
239
+ if (name.includes('claude') || name.includes('anthropic')) {
240
+ return 'anthropic';
241
241
  }
242
- if (name.includes("gemini") || name.includes("google")) {
243
- return "google";
242
+ if (name.includes('gemini') || name.includes('google')) {
243
+ return 'google';
244
244
  }
245
245
  if (
246
- name.includes("codex") ||
247
- name.includes("openai") ||
248
- name.includes("chatgpt")
246
+ name.includes('codex') ||
247
+ name.includes('openai') ||
248
+ name.includes('chatgpt')
249
249
  ) {
250
- return "openai";
250
+ return 'openai';
251
251
  }
252
252
 
253
253
  // Detect based on help content patterns
254
- if (text.includes("anthropic") || text.includes("claude")) {
255
- return "anthropic";
254
+ if (text.includes('anthropic') || text.includes('claude')) {
255
+ return 'anthropic';
256
256
  }
257
257
  if (
258
- text.includes("google") ||
259
- text.includes("gemini") ||
260
- text.includes("vertex")
258
+ text.includes('google') ||
259
+ text.includes('gemini') ||
260
+ text.includes('vertex')
261
261
  ) {
262
- return "google";
262
+ return 'google';
263
263
  }
264
264
  if (
265
- text.includes("openai") ||
266
- text.includes("gpt") ||
267
- text.includes("codex")
265
+ text.includes('openai') ||
266
+ text.includes('gpt') ||
267
+ text.includes('codex')
268
268
  ) {
269
- return "openai";
269
+ return 'openai';
270
270
  }
271
271
 
272
272
  // Default to generic
273
- return "generic";
273
+ return 'generic';
274
274
  }
275
275
 
276
276
  /**
@@ -298,7 +298,7 @@ class CLIHelpAnalyzer {
298
298
  const parts = match.trim().split(/\s+/);
299
299
  return {
300
300
  name: parts[0],
301
- description: parts.slice(1).join(" "),
301
+ description: parts.slice(1).join(' '),
302
302
  syntax: match.trim(),
303
303
  };
304
304
  });
@@ -309,12 +309,12 @@ class CLIHelpAnalyzer {
309
309
  if (optionMatches) {
310
310
  patterns.options = [...new Set(optionMatches)];
311
311
  patterns.flags = optionMatches
312
- .filter((opt) => opt.startsWith("--"))
313
- .map((opt) => opt.replace(/^--/, ""));
312
+ .filter((opt) => opt.startsWith('--'))
313
+ .map((opt) => opt.replace(/^--/, ''));
314
314
  }
315
315
 
316
316
  // Extract main commands (first level)
317
- const lines = helpText.split("\n");
317
+ const lines = helpText.split('\n');
318
318
  for (const line of lines) {
319
319
  const trimmed = line.trim();
320
320
 
@@ -322,7 +322,7 @@ class CLIHelpAnalyzer {
322
322
  if (/^[a-z][a-z0-9_-]+\s+.+$/.test(trimmed)) {
323
323
  const parts = trimmed.split(/\s+/);
324
324
  const command = parts[0];
325
- const description = parts.slice(1).join(" ");
325
+ const description = parts.slice(1).join(' ');
326
326
 
327
327
  if (!patterns.commands.find((cmd) => cmd.name === command)) {
328
328
  patterns.commands.push({
@@ -348,30 +348,30 @@ class CLIHelpAnalyzer {
348
348
 
349
349
  // Look for non-interactive mode flags
350
350
  if (
351
- text.includes("print") ||
352
- text.includes("non-interactive") ||
353
- text.includes("output")
351
+ text.includes('print') ||
352
+ text.includes('non-interactive') ||
353
+ text.includes('output')
354
354
  ) {
355
- patterns.nonInteractiveFlag = "--print";
355
+ patterns.nonInteractiveFlag = '--print';
356
356
  }
357
357
 
358
358
  // Look for prompt-related flags
359
- if (text.includes("prompt") || text.includes("-p ")) {
360
- patterns.promptFlag = "-p";
359
+ if (text.includes('prompt') || text.includes('-p ')) {
360
+ patterns.promptFlag = '-p';
361
361
  }
362
362
 
363
363
  // Look for required flags for non-interactive mode
364
- if (text.includes("non-interactive") && text.includes("prompt")) {
365
- patterns.requiredFlags.push("-p");
364
+ if (text.includes('non-interactive') && text.includes('prompt')) {
365
+ patterns.requiredFlags.push('-p');
366
366
  }
367
367
 
368
368
  // Extract common usage patterns from examples
369
- const exampleLines = helpText.split("\n");
369
+ const exampleLines = helpText.split('\n');
370
370
  for (const line of exampleLines) {
371
371
  if (
372
372
  line.includes('-p "') ||
373
- line.includes("--prompt") ||
374
- line.includes(" -p ")
373
+ line.includes('--prompt') ||
374
+ line.includes(' -p ')
375
375
  ) {
376
376
  patterns.commonPatterns.push(line.trim());
377
377
  }
@@ -383,17 +383,17 @@ class CLIHelpAnalyzer {
383
383
  */
384
384
  analyzeCommandStructure(patterns) {
385
385
  const structure = {
386
- primaryCommand: "",
387
- commandFormat: "",
388
- argumentStyle: "",
389
- optionStyle: "",
386
+ primaryCommand: '',
387
+ commandFormat: '',
388
+ argumentStyle: '',
389
+ optionStyle: '',
390
390
  interactiveMode: false,
391
391
  hasSubcommands: patterns.subcommands.length > 0,
392
- complexity: "simple",
392
+ complexity: 'simple',
393
393
  // Fields for better execution
394
394
  nonInteractiveSupport: !!patterns.nonInteractiveFlag,
395
- promptStyle: patterns.promptFlag ? "flag" : "argument",
396
- executionPattern: "",
395
+ promptStyle: patterns.promptFlag ? 'flag' : 'argument',
396
+ executionPattern: '',
397
397
  // Additional fields for CLI parameter handling
398
398
  nonInteractiveFlag: patterns.nonInteractiveFlag,
399
399
  promptFlag: patterns.promptFlag,
@@ -403,39 +403,39 @@ class CLIHelpAnalyzer {
403
403
 
404
404
  // Determine complexity based on available commands
405
405
  if (patterns.commands.length > 10 || patterns.subcommands.length > 5) {
406
- structure.complexity = "complex";
406
+ structure.complexity = 'complex';
407
407
  } else if (patterns.commands.length > 3 || patterns.options.length > 10) {
408
- structure.complexity = "moderate";
408
+ structure.complexity = 'moderate';
409
409
  }
410
410
 
411
411
  // Determine command format based on patterns
412
412
  if (patterns.subcommands.length > 0) {
413
- structure.commandFormat = "cli <subcommand> [options] [args]";
413
+ structure.commandFormat = 'cli <subcommand> [options] [args]';
414
414
  } else if (patterns.options.length > 0) {
415
- structure.commandFormat = "cli [options] [args]";
415
+ structure.commandFormat = 'cli [options] [args]';
416
416
  } else {
417
- structure.commandFormat = "cli [args]";
417
+ structure.commandFormat = 'cli [args]';
418
418
  }
419
419
 
420
420
  // Check for interactive mode indicators
421
421
  const hasInteractiveIndicators = patterns.commands.some(
422
422
  (cmd) =>
423
- cmd.name.includes("chat") ||
424
- cmd.name.includes("interactive") ||
425
- cmd.name.includes("shell") ||
423
+ cmd.name.includes('chat') ||
424
+ cmd.name.includes('interactive') ||
425
+ cmd.name.includes('shell') ||
426
426
  (cmd.description &&
427
- cmd.description.toLowerCase().includes("interactive")),
427
+ cmd.description.toLowerCase().includes('interactive')),
428
428
  );
429
429
 
430
430
  structure.interactiveMode = hasInteractiveIndicators;
431
431
 
432
432
  // Determine execution pattern
433
433
  if (patterns.nonInteractiveFlag && patterns.promptFlag) {
434
- structure.executionPattern = "flag-based";
434
+ structure.executionPattern = 'flag-based';
435
435
  } else if (patterns.nonInteractiveFlag) {
436
- structure.executionPattern = "argument-based";
436
+ structure.executionPattern = 'argument-based';
437
437
  } else {
438
- structure.executionPattern = "interactive-default";
438
+ structure.executionPattern = 'interactive-default';
439
439
  }
440
440
 
441
441
  return structure;
@@ -454,34 +454,34 @@ class CLIHelpAnalyzer {
454
454
  if (exampleMatches) {
455
455
  for (const match of exampleMatches) {
456
456
  const exampleText = match
457
- .replace(/^(example|usage|用法|使用)[::]\s*/i, "")
457
+ .replace(/^(example|usage|用法|使用)[::]\s*/i, '')
458
458
  .trim();
459
459
 
460
460
  // Split by lines and extract command examples
461
461
  const lines = exampleText
462
- .split("\n")
462
+ .split('\n')
463
463
  .map((line) => line.trim())
464
464
  .filter(
465
- (line) => line && !line.startsWith("#") && !line.startsWith("//"),
465
+ (line) => line && !line.startsWith('#') && !line.startsWith('//'),
466
466
  );
467
467
 
468
468
  for (const line of lines) {
469
469
  if (
470
- line.includes("$") ||
471
- line.includes(">") ||
472
- line.startsWith("cli") ||
470
+ line.includes('$') ||
471
+ line.includes('>') ||
472
+ line.startsWith('cli') ||
473
473
  /^[a-z][\w-]*\s/.test(line)
474
474
  ) {
475
475
  // Extract clean command
476
476
  const command = line
477
- .replace(/^[>$\s]+/, "")
478
- .replace(/^cli\s*/, "")
477
+ .replace(/^[>$\s]+/, '')
478
+ .replace(/^cli\s*/, '')
479
479
  .trim();
480
480
  if (command) {
481
481
  examples.push({
482
482
  command,
483
483
  raw: line,
484
- description: "",
484
+ description: '',
485
485
  });
486
486
  }
487
487
  }
@@ -500,30 +500,30 @@ class CLIHelpAnalyzer {
500
500
 
501
501
  // Check for different interaction modes
502
502
  if (
503
- text.includes("chat") ||
504
- text.includes("conversation") ||
505
- text.includes("interactive")
503
+ text.includes('chat') ||
504
+ text.includes('conversation') ||
505
+ text.includes('interactive')
506
506
  ) {
507
- return "chat";
507
+ return 'chat';
508
508
  }
509
509
 
510
510
  if (
511
- text.includes("api") ||
512
- text.includes("endpoint") ||
513
- text.includes("request")
511
+ text.includes('api') ||
512
+ text.includes('endpoint') ||
513
+ text.includes('request')
514
514
  ) {
515
- return "api";
515
+ return 'api';
516
516
  }
517
517
 
518
518
  if (patterns.subcommands.length > 0) {
519
- return "subcommand";
519
+ return 'subcommand';
520
520
  }
521
521
 
522
522
  if (patterns.options.length > 5) {
523
- return "option";
523
+ return 'option';
524
524
  }
525
525
 
526
- return "simple";
526
+ return 'simple';
527
527
  }
528
528
 
529
529
  /**
@@ -586,7 +586,7 @@ class CLIHelpAnalyzer {
586
586
  config.lastUpdated = new Date().toISOString();
587
587
  await this.savePersistentConfig(config);
588
588
  } catch (err) {
589
- console.error("Failed to record failed attempt:", err.message);
589
+ console.error('Failed to record failed attempt:', err.message);
590
590
  }
591
591
  }
592
592
 
@@ -595,11 +595,11 @@ class CLIHelpAnalyzer {
595
595
  */
596
596
  async loadPersistentConfig() {
597
597
  try {
598
- const data = await fs.readFile(this.persistentConfig, "utf8");
598
+ const data = await fs.readFile(this.persistentConfig, 'utf8');
599
599
  return JSON.parse(data);
600
600
  } catch (error) {
601
601
  return {
602
- version: "1.0.0",
602
+ version: '1.0.0',
603
603
  lastUpdated: new Date().toISOString(),
604
604
  cliPatterns: {},
605
605
  failedAttempts: {},
@@ -1,5 +1,5 @@
1
1
  // Unified CLI Parameter Handler
2
- const { spawn } = require("child_process");
2
+ const { spawn } = require('child_process');
3
3
 
4
4
  class CLIParameterHandler {
5
5
  /**
@@ -14,8 +14,8 @@ class CLIParameterHandler {
14
14
  let toolArgs = [];
15
15
 
16
16
  // Special handling for Codex CLI which always needs 'exec' subcommand
17
- if (toolName === "codex") {
18
- return ["exec", "-p", `"${prompt}"`];
17
+ if (toolName === 'codex') {
18
+ return ['exec', '-p', `"${prompt}"`];
19
19
  }
20
20
 
21
21
  try {
@@ -32,21 +32,21 @@ class CLIParameterHandler {
32
32
  toolArgs = [commandStructure.nonInteractiveFlag, `"${prompt}"`];
33
33
  } else {
34
34
  // Fallback to standard -p flag
35
- toolArgs = ["-p", `"${prompt}"`];
35
+ toolArgs = ['-p', `"${prompt}"`];
36
36
  }
37
- } else if (commandStructure.executionPattern === "flag-based") {
37
+ } else if (commandStructure.executionPattern === 'flag-based') {
38
38
  // Explicitly flag-based tools
39
39
  if (commandStructure.promptFlag) {
40
40
  toolArgs = [commandStructure.promptFlag, `"${prompt}"`];
41
41
  } else {
42
- toolArgs = ["-p", `"${prompt}"`];
42
+ toolArgs = ['-p', `"${prompt}"`];
43
43
  }
44
- } else if (commandStructure.executionPattern === "argument-based") {
44
+ } else if (commandStructure.executionPattern === 'argument-based') {
45
45
  // Argument-based tools
46
46
  toolArgs = [`"${prompt}"`];
47
- } else if (commandStructure.executionPattern === "subcommand-based") {
47
+ } else if (commandStructure.executionPattern === 'subcommand-based') {
48
48
  // Subcommand-based tools
49
- toolArgs = ["-p", `"${prompt}"`];
49
+ toolArgs = ['-p', `"${prompt}"`];
50
50
  } else {
51
51
  // Fallback to tool-specific handling
52
52
  toolArgs = this.getToolSpecificArguments(toolName, prompt);
@@ -72,12 +72,12 @@ class CLIParameterHandler {
72
72
  static getToolSpecificArguments(toolName, prompt) {
73
73
  // Tool-specific argument handling
74
74
  const toolSpecificArgs = {
75
- claude: ["-p", `"${prompt}"`],
76
- qodercli: ["-p", `"${prompt}"`],
77
- iflow: ["-p", `"${prompt}"`],
78
- codebuddy: ["-p", `"${prompt}"`],
79
- copilot: ["-p", `"${prompt}"`],
80
- codex: ["exec", "-p", `"${prompt}"`], // Codex needs 'exec' subcommand
75
+ claude: ['-p', `"${prompt}"`],
76
+ qodercli: ['-p', `"${prompt}"`],
77
+ iflow: ['-p', `"${prompt}"`],
78
+ codebuddy: ['-p', `"${prompt}"`],
79
+ copilot: ['-p', `"${prompt}"`],
80
+ codex: ['exec', '-p', `"${prompt}"`], // Codex needs 'exec' subcommand
81
81
  };
82
82
 
83
83
  // Return tool-specific arguments if available
@@ -88,14 +88,14 @@ class CLIParameterHandler {
88
88
  // Default handling for other tools
89
89
  // Check if the tool commonly uses -p flag
90
90
  const toolsWithPFlag = [
91
- "claude",
92
- "qodercli",
93
- "iflow",
94
- "codebuddy",
95
- "copilot",
91
+ 'claude',
92
+ 'qodercli',
93
+ 'iflow',
94
+ 'codebuddy',
95
+ 'copilot',
96
96
  ];
97
97
  if (toolsWithPFlag.includes(toolName)) {
98
- return ["-p", `"${prompt}"`];
98
+ return ['-p', `"${prompt}"`];
99
99
  }
100
100
 
101
101
  // Default to argument-based approach
@@ -116,7 +116,7 @@ class CLIParameterHandler {
116
116
 
117
117
  // Execute the tool
118
118
  const child = spawn(toolPath, toolArgs, {
119
- stdio: "inherit",
119
+ stdio: 'inherit',
120
120
  shell: true,
121
121
  });
122
122