stigmergy 1.2.8 → 1.2.11

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 (48) hide show
  1. package/README.md +40 -6
  2. package/STIGMERGY.md +10 -0
  3. package/package.json +19 -5
  4. package/scripts/preuninstall.js +10 -0
  5. package/src/adapters/claude/install_claude_integration.js +21 -21
  6. package/src/adapters/codebuddy/install_codebuddy_integration.js +54 -51
  7. package/src/adapters/codex/install_codex_integration.js +27 -28
  8. package/src/adapters/gemini/install_gemini_integration.js +60 -60
  9. package/src/adapters/iflow/install_iflow_integration.js +72 -72
  10. package/src/adapters/qoder/install_qoder_integration.js +64 -64
  11. package/src/adapters/qwen/install_qwen_integration.js +7 -7
  12. package/src/cli/router.js +581 -175
  13. package/src/commands/skill-bridge.js +39 -0
  14. package/src/commands/skill-handler.js +150 -0
  15. package/src/commands/skill.js +127 -0
  16. package/src/core/cli_path_detector.js +710 -0
  17. package/src/core/cli_tools.js +72 -1
  18. package/src/core/coordination/nodejs/AdapterManager.js +29 -1
  19. package/src/core/directory_permission_manager.js +568 -0
  20. package/src/core/enhanced_cli_installer.js +609 -0
  21. package/src/core/installer.js +232 -88
  22. package/src/core/multilingual/language-pattern-manager.js +78 -50
  23. package/src/core/persistent_shell_configurator.js +468 -0
  24. package/src/core/skills/StigmergySkillManager.js +357 -0
  25. package/src/core/skills/__tests__/SkillInstaller.test.js +275 -0
  26. package/src/core/skills/__tests__/SkillParser.test.js +202 -0
  27. package/src/core/skills/__tests__/SkillReader.test.js +189 -0
  28. package/src/core/skills/cli-command-test.js +201 -0
  29. package/src/core/skills/comprehensive-e2e-test.js +473 -0
  30. package/src/core/skills/e2e-test.js +267 -0
  31. package/src/core/skills/embedded-openskills/SkillInstaller.js +438 -0
  32. package/src/core/skills/embedded-openskills/SkillParser.js +123 -0
  33. package/src/core/skills/embedded-openskills/SkillReader.js +143 -0
  34. package/src/core/skills/integration-test.js +248 -0
  35. package/src/core/skills/package.json +6 -0
  36. package/src/core/skills/regression-test.js +285 -0
  37. package/src/core/skills/run-all-tests.js +129 -0
  38. package/src/core/skills/sync-test.js +210 -0
  39. package/src/core/skills/test-runner.js +242 -0
  40. package/src/utils/helpers.js +3 -20
  41. package/src/auth.js +0 -173
  42. package/src/auth_command.js +0 -208
  43. package/src/calculator.js +0 -313
  44. package/src/core/enhanced_installer.js +0 -479
  45. package/src/core/enhanced_uninstaller.js +0 -638
  46. package/src/data_encryption.js +0 -143
  47. package/src/data_structures.js +0 -440
  48. package/src/deploy.js +0 -55
@@ -1,7 +1,7 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs/promises');
3
3
  const os = require('os');
4
- const { spawnSync } = require('child_process');
4
+ const { spawn, spawnSync } = require('child_process');
5
5
  const inquirer = require('inquirer');
6
6
  const SmartRouter = require('./smart_router');
7
7
  const { errorHandler } = require('./error_handler');
@@ -33,7 +33,7 @@ class StigmergyInstaller {
33
33
  const whichCmd = process.platform === 'win32' ? 'where' : 'which';
34
34
  const whichResult = spawnSync(whichCmd, [toolName], {
35
35
  encoding: 'utf8',
36
- timeout: 3000,
36
+ timeout: 10000,
37
37
  stdio: ['pipe', 'pipe', 'pipe'],
38
38
  shell: true,
39
39
  });
@@ -93,7 +93,7 @@ class StigmergyInstaller {
93
93
  const whichCmd = process.platform === 'win32' ? 'where' : 'which';
94
94
  const whichResult = spawnSync(whichCmd, [toolName], {
95
95
  encoding: 'utf8',
96
- timeout: 3000,
96
+ timeout: 10000,
97
97
  stdio: ['pipe', 'pipe', 'pipe'], // Use pipes to avoid file opening
98
98
  shell: true,
99
99
  });
@@ -141,7 +141,7 @@ class StigmergyInstaller {
141
141
  try {
142
142
  const result = spawnSync(toolName, check.args, {
143
143
  encoding: 'utf8',
144
- timeout: 3000,
144
+ timeout: 10000,
145
145
  stdio: ['pipe', 'pipe', 'pipe'], // Ensure all IO is piped
146
146
  shell: false, // Don't use shell to avoid extra window opening
147
147
  windowsHide: true, // Hide console window on Windows
@@ -247,27 +247,111 @@ class StigmergyInstaller {
247
247
  * Show install options for missing CLI tools
248
248
  */
249
249
  async showInstallOptions(missingTools) {
250
- // This is a placeholder implementation
251
- console.log('[INSTALL] No install options to show');
252
- return [];
250
+ if (Object.keys(missingTools).length === 0) {
251
+ console.log('[INSTALL] All tools are already installed!');
252
+ return [];
253
+ }
254
+
255
+ console.log('\n[INSTALL] Missing AI CLI Tools:');
256
+ const options = [];
257
+ let index = 1;
258
+
259
+ for (const [toolName, toolInfo] of Object.entries(missingTools)) {
260
+ const option = {
261
+ name: `${index++}. ${toolInfo.name} - ${toolInfo.install}`,
262
+ value: toolName,
263
+ };
264
+ options.push(option);
265
+ console.log(` ${option.name}`);
266
+ }
267
+
268
+ return options;
253
269
  }
254
270
 
255
271
  /**
256
272
  * Get user selection for CLI tools to install
257
273
  */
258
274
  async getUserSelection(options, missingTools) {
259
- // This is a placeholder implementation
260
- console.log('[INSTALL] No user selection needed');
261
- return [];
275
+ if (options.length === 0) {
276
+ return [];
277
+ }
278
+
279
+ // For non-interactive mode, install all missing tools
280
+ if (process.env.CI || process.argv.includes('--auto-install') || process.argv.includes('--force')) {
281
+ console.log('[INSTALL] Auto-installing all missing tools...');
282
+ return options.map(option => option.value);
283
+ }
284
+
285
+ // Interactive mode
286
+ try {
287
+ const { selectedTools } = await inquirer.prompt([
288
+ {
289
+ type: 'checkbox',
290
+ name: 'selectedTools',
291
+ message: 'Select tools to install (Press Space to select, Enter to confirm):',
292
+ choices: options,
293
+ validate: (input) => {
294
+ if (input && input.length > 0) return true;
295
+ return 'Please select at least one tool to install';
296
+ },
297
+ },
298
+ ]);
299
+ return selectedTools || [];
300
+ } catch (error) {
301
+ console.log('[INSTALL] Interactive mode failed, installing all missing tools...');
302
+ return options.map(option => option.value);
303
+ }
262
304
  }
263
305
 
264
306
  /**
265
307
  * Install selected CLI tools
266
308
  */
267
309
  async installTools(selectedTools, missingTools) {
268
- // This is a placeholder implementation
269
- console.log('[INSTALL] No tools to install');
270
- return true;
310
+ const chalk = require('chalk');
311
+ let successCount = 0;
312
+
313
+ for (const toolName of selectedTools) {
314
+ const toolInfo = missingTools[toolName];
315
+ if (!toolInfo) continue;
316
+
317
+ console.log(`\n[INSTALL] Installing ${toolInfo.name}...`);
318
+ console.log(chalk.yellow(`Command: ${toolInfo.install}`));
319
+
320
+ try {
321
+ // Parse the install command
322
+ const [command, ...args] = toolInfo.install.split(' ');
323
+
324
+ // Execute the installation command
325
+ const result = spawnSync(command, args, {
326
+ stdio: 'inherit', // Show output in real-time
327
+ shell: true, // Use shell for npm commands
328
+ encoding: 'utf-8'
329
+ });
330
+
331
+ if (result.status === 0) {
332
+ console.log(chalk.green(`[OK] Successfully installed ${toolInfo.name}`));
333
+ successCount++;
334
+ } else {
335
+ console.log(chalk.red(`[ERROR] Failed to install ${toolInfo.name}. Exit code: ${result.status}`));
336
+ // Continue with other tools
337
+ }
338
+ } catch (error) {
339
+ console.log(chalk.red(`[ERROR] Installation failed for ${toolInfo.name}: ${error.message}`));
340
+ // Continue with other tools
341
+ }
342
+ }
343
+
344
+ if (successCount > 0) {
345
+ console.log(chalk.green(`\n[INSTALL] Successfully installed ${successCount}/${selectedTools.length} tools`));
346
+
347
+ // Add a short delay to ensure installations are complete
348
+ await new Promise(resolve => setTimeout(resolve, 2000));
349
+
350
+ return true;
351
+ } else {
352
+ console.log(chalk.red('[INSTALL] No tools were successfully installed'));
353
+ return false;
354
+ }
271
355
  }
272
356
 
273
357
  /**
@@ -415,15 +499,66 @@ class StigmergyInstaller {
415
499
  // Create PROJECT_CONSTITUTION.md if it doesn't exist
416
500
  const projectConstitutionPath = path.join(currentDir, 'PROJECT_CONSTITUTION.md');
417
501
  if (!(await fs.access(projectConstitutionPath).then(() => true).catch(() => false))) {
418
- const constitutionContent = `# 项目协作宪法
419
-
420
- ## 协作基本原则
421
- - 所有协作通过PROJECT_SPEC.json协调
422
- - 智能体基于背景状态自主决�?- 无中央调度器,实现去中心化协�?
423
- ## 任务管理原则
424
- - 智能体可认领分配给自己的任务
425
- - 智能体可认领与其能力匹配的未分配任务
426
- - 任务状态实时更新至共享背景
502
+ const constitutionContent = `# Project Collaboration Constitution
503
+
504
+ ## Basic Collaboration Principles
505
+ - All collaboration is coordinated through PROJECT_SPEC.json
506
+ - Agents make autonomous decisions based on background state
507
+ - No central scheduler, achieving decentralized collaboration
508
+
509
+ ## PROJECT_SPEC.json Usage
510
+ The PROJECT_SPEC.json file serves as the central coordination point for all project activities.
511
+
512
+ ### Basic Structure:
513
+ \`\`
514
+ {
515
+ "projectName": "your-project-name",
516
+ "version": "1.0.0",
517
+ "description": "Project description",
518
+ "collaboration": {
519
+ "activeTasks": [],
520
+ "completedTasks": [],
521
+ "sharedContext": {}
522
+ }
523
+ }
524
+ \`\`
525
+
526
+ ### Common Usage Examples:
527
+ 1. Define project tasks:
528
+ \`\`
529
+ {
530
+ "collaboration": {
531
+ "activeTasks": [
532
+ {
533
+ "id": "task-001",
534
+ "name": "Implement feature X",
535
+ "status": "in-progress",
536
+ "assignedTo": "any",
537
+ "priority": "high",
538
+ "description": "Task details..."
539
+ }
540
+ ]
541
+ }
542
+ }
543
+ \`\`
544
+
545
+ 2. Track shared context:
546
+ \`\`
547
+ {
548
+ "collaboration": {
549
+ "sharedContext": {
550
+ "lastCompletion": "2025-02-22T10:00:00Z",
551
+ "activeDevelopers": ["developer1", "developer2"],
552
+ "currentSprint": "sprint-2"
553
+ }
554
+ }
555
+ }
556
+ \`\`
557
+
558
+ ## Task Management Principles
559
+ - Agents can claim tasks assigned to themselves
560
+ - Agents can claim unassigned tasks that match their capabilities
561
+ - Task status is updated in real-time to the shared context
427
562
  `;
428
563
  await fs.writeFile(projectConstitutionPath, constitutionContent, 'utf8');
429
564
  console.log('[PROJECT] Created PROJECT_CONSTITUTION.md');
@@ -443,40 +578,65 @@ class StigmergyInstaller {
443
578
  const fs = require('fs/promises');
444
579
  const path = require('path');
445
580
  const { spawn } = require('child_process');
446
-
581
+
447
582
  console.log(`[CONFIG] Configuring ${toolInfo.name}...`);
448
-
583
+
449
584
  try {
450
585
  // Map tool names to their adapter directory names
451
586
  const toolToAdapterDir = {
452
587
  'qodercli': 'qoder',
453
588
  'qwencode': 'qwen'
454
589
  };
455
-
590
+
456
591
  const adapterDirName = toolToAdapterDir[toolName] || toolName;
457
- const installScriptPath = path.join(__dirname, '..', 'adapters', adapterDirName, `install_${adapterDirName}_integration.js`);
458
-
459
- // Check if the JavaScript installation script exists
460
- try {
461
- await fs.access(installScriptPath);
462
- console.log(`[RUN] Running JavaScript installation script for ${toolInfo.name}...`);
463
-
464
- // Run the JavaScript installation script
465
- const result = await this.runInstallScript(installScriptPath);
466
-
467
- if (result.success) {
468
- console.log(`[OK] ${toolInfo.name} installation script completed successfully`);
469
- } else {
470
- console.log(`[WARN] ${toolInfo.name} installation script failed: ${result.error}`);
592
+
593
+ // Try to find the installation script using multiple approaches to handle different installation scenarios
594
+ let installScriptPath;
595
+ const possiblePaths = [
596
+ // Standard path: src/core/../adapters => src/adapters
597
+ path.join(__dirname, '..', 'adapters', adapterDirName, `install_${adapterDirName}_integration.js`),
598
+ // Path when running from global installation in a different context
599
+ path.join(process.cwd(), 'src', 'adapters', adapterDirName, `install_${adapterDirName}_integration.js`),
600
+ // Path when we might be in a different location due to module resolution
601
+ path.resolve(__dirname, '..', 'adapters', adapterDirName, `install_${adapterDirName}_integration.js`)
602
+ ];
603
+
604
+ // Check if we're in the global npm installation by looking for the install script
605
+ for (const possiblePath of possiblePaths) {
606
+ try {
607
+ await fs.access(possiblePath);
608
+ installScriptPath = possiblePath;
609
+ console.log(`[DEBUG] Found installation script at: ${possiblePath}`);
610
+ break;
611
+ } catch (error) {
612
+ // Continue to next possible path
613
+ continue;
471
614
  }
472
- } catch (error) {
473
- console.log(`[WARN] JavaScript installation script not found for ${toolInfo.name}: ${installScriptPath}`);
615
+ }
616
+
617
+ // If we still haven't found the installation script
618
+ if (!installScriptPath) {
619
+ console.log(`[WARN] JavaScript installation script not found for ${toolInfo.name} at possible paths:`, possiblePaths);
474
620
  console.log(`[FALLBACK] Using inline configuration for ${toolInfo.name}...`);
475
-
476
- // Fallback to inline configuration if script doesn't exist
477
621
  await this.inlineToolConfiguration(toolName, toolInfo);
622
+ return;
478
623
  }
479
-
624
+
625
+ // Installation script found, execute it
626
+ console.log(`[RUN] Running JavaScript installation script for ${toolInfo.name}...`);
627
+
628
+ // Run the JavaScript installation script
629
+ const result = await this.runInstallScript(installScriptPath);
630
+
631
+ if (result.success) {
632
+ console.log(`[OK] ${toolInfo.name} installation script completed successfully`);
633
+ } else {
634
+ console.log(`[WARN] ${toolInfo.name} installation script failed: ${result.error}`);
635
+ // If the installation script fails but was found, still try to use inline configuration as fallback
636
+ console.log(`[FALLBACK] Using inline configuration for ${toolInfo.name} after script failure...`);
637
+ await this.inlineToolConfiguration(toolName, toolInfo);
638
+ }
639
+
480
640
  } catch (error) {
481
641
  console.log(`[WARN] Configuration failed for ${toolInfo.name}: ${error.message}`);
482
642
  }
@@ -490,7 +650,7 @@ class StigmergyInstaller {
490
650
  const child = spawn('node', [scriptPath], {
491
651
  cwd: path.dirname(scriptPath),
492
652
  stdio: 'pipe',
493
- timeout: 30000 // 30 second timeout
653
+ timeout: 100000 // 30 second timeout
494
654
  });
495
655
 
496
656
  let stdout = '';
@@ -546,10 +706,29 @@ class StigmergyInstaller {
546
706
  console.log(`[OK] Configuration file created: ${toolInfo.config}`);
547
707
 
548
708
  // Step 2: Copy adapter files if they exist
549
- const adapterDir = path.join(__dirname, '..', 'adapters', toolName === 'qodercli' ? 'qoder' : toolName);
550
- if (await this.fileExists(adapterDir)) {
709
+ // Try to find the adapter directory using multiple approaches to handle different installation scenarios
710
+ let adapterDir;
711
+ const possibleAdapterPaths = [
712
+ // Standard path: src/core/../adapters => src/adapters
713
+ path.join(__dirname, '..', 'adapters', toolName === 'qodercli' ? 'qoder' : toolName),
714
+ // Path when running from global installation
715
+ path.resolve(__dirname, '..', 'adapters', toolName === 'qodercli' ? 'qoder' : toolName)
716
+ ];
717
+
718
+ for (const possiblePath of possibleAdapterPaths) {
719
+ if (await this.fileExists(possiblePath)) {
720
+ adapterDir = possiblePath;
721
+ console.log(`[DEBUG] Found adapter directory at: ${possiblePath}`);
722
+ break;
723
+ }
724
+ }
725
+
726
+ // If we found the adapter directory, copy the files
727
+ if (adapterDir) {
551
728
  await this.copyAdapterFiles(adapterDir, toolInfo.hooksDir);
552
729
  console.log(`[OK] Adapter files copied for ${toolInfo.name}`);
730
+ } else {
731
+ console.log(`[WARN] Adapter directory not found for ${toolInfo.name} at possible paths:`, possibleAdapterPaths);
553
732
  }
554
733
 
555
734
  // Step 3: Create tool-specific hook files
@@ -582,7 +761,7 @@ class StigmergyInstaller {
582
761
  supported_tools: ['claude', 'gemini', 'qwen', 'iflow', 'qodercli', 'codebuddy', 'copilot', 'codex'],
583
762
  trigger_patterns: [
584
763
  'use\\s+(\\w+)\\s+to\\s+(.+)$',
585
- 'call\\s+(\\w+)\\s+(.+)$',
764
+ 'call\\s+(\\w+)\\s+(.+)$',
586
765
  'ask\\s+(\\w+)\\s+(.+)$',
587
766
  'stigmergy\\s+(\\w+)\\s+(.+)$'
588
767
  ]
@@ -792,7 +971,7 @@ class StigmergyInstaller {
792
971
  generateCrossCliGuide(toolName) {
793
972
  const toolNames = {
794
973
  'claude': 'Claude CLI',
795
- 'gemini': 'Gemini CLI',
974
+ 'gemini': 'Gemini CLI',
796
975
  'qwen': 'Qwen CLI',
797
976
  'iflow': 'iFlow CLI',
798
977
  'qodercli': 'Qoder CLI',
@@ -801,26 +980,8 @@ class StigmergyInstaller {
801
980
  'codex': 'OpenAI Codex CLI'
802
981
  };
803
982
 
804
- const isChinese = ['claude', 'qwen', 'iflow', 'qodercli', 'codebuddy'].includes(toolName);
805
-
806
- if (isChinese) {
807
- return `# ${toolNames[toolName]} Cross-CLI 通信指南
808
-
809
- ## Cross-CLI Communication
810
- 当您需要调用其他AI工具时,请使用以下提示<<<在shell中执行以下命令:stigmergy <工具名> <任务描述>>>
811
-
812
- 示例:
813
- - 在shell中运行:stigmergy claude "写一个Python函数"
814
- - 在shell中运行:stigmergy gemini "翻译这段文字"
815
- - 在shell中运行:stigmergy qwen "分析这段代码"
816
-
817
- 可用工具:claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
818
-
819
- ---
820
- *本文档由Stigmergy CLI自动生成和维护*
821
- `;
822
- } else {
823
- return `# ${toolNames[toolName]} Cross-CLI Communication Guide
983
+ // All documentation generated in English for consistency
984
+ return `# ${toolNames[toolName]} Cross-CLI Communication Guide
824
985
 
825
986
  ## Cross-CLI Communication
826
987
  When you need to call other AI tools, please use the following prompt <<<Execute the following command in shell: stigmergy <tool_name> <task_description>>>
@@ -835,7 +996,6 @@ Available tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, code
835
996
  ---
836
997
  *This document is automatically generated and maintained by Stigmergy CLI*
837
998
  `;
838
- }
839
999
  }
840
1000
 
841
1001
  /**
@@ -876,23 +1036,8 @@ Available tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, code
876
1036
  * Generate content to append to .md files
877
1037
  */
878
1038
  generateCrossCliAppendContent(toolName) {
879
- const isChinese = ['claude', 'qwen', 'iflow', 'qodercli', 'codebuddy'].includes(toolName);
880
-
881
- if (isChinese) {
882
- return `
883
-
884
- ## Cross-CLI Communication
885
- 当您需要调用其他AI工具时,请使用以下提示<<<在shell中执行以下命令:stigmergy <工具名> <任务描述>>>
886
-
887
- 示例:
888
- - 在shell中运行:stigmergy claude "写一个Python函数"
889
- - 在shell中运行:stigmergy gemini "翻译这段文字"
890
- - 在shell中运行:stigmergy qwen "分析这段代码"
891
-
892
- 可用工具:claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
893
- `;
894
- } else {
895
- return `
1039
+ // All documentation generated in English for consistency
1040
+ return `
896
1041
 
897
1042
  ## Cross-CLI Communication
898
1043
  When you need to call other AI tools, please use the following prompt <<<Execute the following command in shell: stigmergy <tool_name> <task_description>>>
@@ -904,7 +1049,6 @@ Examples:
904
1049
 
905
1050
  Available tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
906
1051
  `;
907
- }
908
1052
  }
909
1053
 
910
1054
  /**
@@ -1,8 +1,5 @@
1
1
  // src/core/multilingual/language-pattern-manager.js
2
2
 
3
- const path = require('path');
4
- const fs = require('fs');
5
-
6
3
  class LanguagePatternManager {
7
4
  constructor() {
8
5
  this.supportedLanguages = {
@@ -19,54 +16,85 @@ class LanguagePatternManager {
19
16
  ar: { name: 'Arabic', direction: 'rtl' },
20
17
  tr: { name: 'Turkish', direction: 'ltr' }
21
18
  };
22
-
23
- this.languagePatterns = {};
24
- this.loadLanguagePatterns();
25
- }
26
-
27
- loadLanguagePatterns() {
28
- // Load patterns for each supported language
29
- const patternDir = path.join(process.cwd(), '.qoder', 'specs', 'multilingual-hook-system', 'language-patterns');
30
-
31
- if (fs.existsSync(patternDir)) {
32
- const patternFiles = fs.readdirSync(patternDir);
33
-
34
- // Mapping from filename to language code
35
- const fileToLanguageMap = {
36
- 'english': 'en',
37
- 'chinese': 'zh',
38
- 'japanese': 'ja',
39
- 'korean': 'ko',
40
- 'german': 'de',
41
- 'french': 'fr',
42
- 'spanish': 'es',
43
- 'italian': 'it',
44
- 'portuguese': 'pt',
45
- 'russian': 'ru',
46
- 'arabic': 'ar',
47
- 'turkish': 'tr'
48
- };
49
19
 
50
- for (const file of patternFiles) {
51
- if (file.endsWith('.js') && file !== '.gitkeep') {
52
- const fileName = path.basename(file, '.js');
53
- const languageCode = fileToLanguageMap[fileName];
54
-
55
- if (languageCode && this.supportedLanguages[languageCode]) {
56
- try {
57
- const filePath = path.join(patternDir, file);
58
- // Clear cache to ensure fresh load
59
- delete require.cache[require.resolve(filePath)];
60
- const patterns = require(filePath);
61
- this.languagePatterns[languageCode] = patterns;
62
- console.log(`Loaded ${patterns.length} patterns for ${languageCode} (${fileName})`);
63
- } catch (error) {
64
- console.warn(`Failed to load patterns for language ${languageCode} (${fileName}):`, error.message);
65
- }
66
- }
67
- }
68
- }
69
- }
20
+ // Define language patterns directly, same as in HookDeploymentManager.js
21
+ this.languagePatterns = {
22
+ // English patterns
23
+ en: [
24
+ { name: 'use_tool_for_task', regex: /(?:use|call|ask)\s+(\w+)\s+(?:to|for)\s+(.+)$/i },
25
+ { name: 'please_use_tool', regex: /(?:please\s+)?(?:use|call|ask)\s+(\w+)\s+(.+)$/i },
26
+ { name: 'tool_please_help', regex: /(\w+)[,\s]+(?:please\s+)?(?:help\s+me\s+)?(.+)$/i }
27
+ ],
28
+ // Chinese patterns
29
+ zh: [
30
+ { name: 'qing_yong_gongneng_bang_wo', regex: /请用(\w+)\s*帮我(.+)$/i },
31
+ { name: 'diaoyong_lai', regex: /调用(\w+)\s*来(.+)$/i },
32
+ { name: 'yong_gongneng_bang_wo', regex: /用(\w+)\s*帮我(.+)$/i },
33
+ { name: 'tool_comma_task', regex: /(\w+),(.+)$/i },
34
+ { name: 'rang_gongneng', regex: /让(\w+)\s*(.+)$/i }
35
+ ],
36
+ // German patterns
37
+ de: [
38
+ { name: 'benutze_tool_um', regex: /benutze\s+(\w+)\s+um\s+(.+)$/i },
39
+ { name: 'verwende_tool_fur', regex: /verwende\s+(\w+)\s+für\s+(.+)$/i },
40
+ { name: 'rufe_tool_fur_an', regex: /rufe\s+(\w+)\s+für\s+(.+)\s+an$/i }
41
+ ],
42
+ // French patterns
43
+ fr: [
44
+ { name: 'utilise_tool_pour', regex: /utilise\s+(\w+)\s+pour\s+(.+)$/i },
45
+ { name: 'emploie_tool_avec', regex: /emploie\s+(\w+)\s+avec\s+(.+)$/i },
46
+ { name: 'appelle_tool_pour', regex: /appelle\s+(\w+)\s+pour\s+(.+)$/i }
47
+ ],
48
+ // Spanish patterns
49
+ es: [
50
+ { name: 'usa_tool_para', regex: /usa\s+(\w+)\s+para\s+(.+)$/i },
51
+ { name: 'utiliza_tool_para', regex: /utiliza\s+(\w+)\s+para\s+(.+)$/i },
52
+ { name: 'llama_tool_para', regex: /llama\s+(\w+)\s+para\s+(.+)$/i }
53
+ ],
54
+ // Italian patterns
55
+ it: [
56
+ { name: 'usa_tool_per', regex: /usa\s+(\w+)\s+per\s+(.+)$/i },
57
+ { name: 'utilizza_tool_per', regex: /utilizza\s+(\w+)\s+per\s+(.+)$/i },
58
+ { name: 'chiedi_tool_per', regex: /chiedi\s+(\w+)\s+per\s+(.+)$/i }
59
+ ],
60
+ // Portuguese patterns
61
+ pt: [
62
+ { name: 'usa_tool_para_pt', regex: /usa\s+(\w+)\s+para\s+(.+)$/i },
63
+ { name: 'utiliza_tool_para_pt', regex: /utiliza\s+(\w+)\s+para\s+(.+)$/i },
64
+ { name: 'chama_tool_para', regex: /chama\s+(\w+)\s+para\s+(.+)$/i }
65
+ ],
66
+ // Russian patterns
67
+ ru: [
68
+ { name: 'ispolzuy_tool_chtoby', regex: /используй\s+(\w+)\s+чтобы\s+(.+)$/i },
69
+ { name: 'primeni_tool_dlya', regex: /примени\s+(\w+)\s+для\s+(.+)$/i },
70
+ { name: 'vysovyi_tool_dlya', regex: /вызови\s+(\w+)\s+для\s+(.+)$/i }
71
+ ],
72
+ // Arabic patterns
73
+ ar: [
74
+ { name: 'ista5dam_tool_liktabat', regex: /استخدم\s+(\w+)\s+ل(?:كتابة|عمل)\s+(.+)$/i },
75
+ { name: 'atssil_b_tool', regex: /اتصل\s+ب\s+(\w+)\s+(.+)$/i },
76
+ { name: 'ast5raj_tool', regex: /استخرج\s+(\w+)\s+(.+)$/i }
77
+ ],
78
+ // Japanese patterns
79
+ ja: [
80
+ { name: 'tool_o_tsukatte', regex: /(\w+)\s*を使って\s*(.+)$/i },
81
+ { name: 'tool_wo_yatte', regex: /(\w+)\s*を\s*やって\s*(.+)$/i },
82
+ { name: 'tool_ni_onegaishimasu', regex: /(\w+)、\s*(.+)$/i }
83
+ ],
84
+ // Korean patterns
85
+ ko: [
86
+ { name: 'tool_sayonghae', regex: /(\w+)\s*를\s*사용해\s*(.+)$/i },
87
+ { name: 'tool_sayonghayeyo', regex: /(\w+)\s*를\s*사용하여\s*(.+)$/i },
88
+ { name: 'tool_irae', regex: /(\w+)\s*을\s*이용해\s*(.+)$/i },
89
+ { name: 'tool_ggumyeon', regex: /(\w+)\s*하고\s*(.+)$/i }
90
+ ],
91
+ // Turkish patterns
92
+ tr: [
93
+ { name: 'tool_icin_kullan', regex: /(\w+)'?u\s*(.+)\s+için\s+kullan/i },
94
+ { name: 'tool_kullan_icin', regex: /(\w+)\s*kullan\s+için\s*(.+)$/i },
95
+ { name: 'tool_ile_yap', regex: /(\w+)\s*ile\s*(.+)$/i }
96
+ ]
97
+ };
70
98
  }
71
99
 
72
100
  getPatterns(languageCode) {