aiexecode 1.0.94 → 1.0.127

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.

Potentially problematic release.


This version of aiexecode might be problematic. Click here for more details.

Files changed (80) hide show
  1. package/README.md +198 -88
  2. package/index.js +310 -86
  3. package/mcp-agent-lib/src/mcp_message_logger.js +17 -16
  4. package/package.json +4 -4
  5. package/payload_viewer/out/404/index.html +1 -1
  6. package/payload_viewer/out/404.html +1 -1
  7. package/payload_viewer/out/_next/static/chunks/{37d0cd2587a38f79.js → b6c0459f3789d25c.js} +1 -1
  8. package/payload_viewer/out/_next/static/chunks/b75131b58f8ca46a.css +3 -0
  9. package/payload_viewer/out/index.html +1 -1
  10. package/payload_viewer/out/index.txt +3 -3
  11. package/payload_viewer/web_server.js +361 -0
  12. package/prompts/completion_judge.txt +4 -0
  13. package/prompts/orchestrator.txt +116 -3
  14. package/src/LLMClient/client.js +401 -18
  15. package/src/LLMClient/converters/responses-to-claude.js +67 -18
  16. package/src/LLMClient/converters/responses-to-zai.js +667 -0
  17. package/src/LLMClient/errors.js +30 -4
  18. package/src/LLMClient/index.js +5 -0
  19. package/src/ai_based/completion_judge.js +263 -186
  20. package/src/ai_based/orchestrator.js +171 -35
  21. package/src/commands/agents.js +70 -0
  22. package/src/commands/apikey.js +1 -1
  23. package/src/commands/bg.js +129 -0
  24. package/src/commands/commands.js +51 -0
  25. package/src/commands/debug.js +52 -0
  26. package/src/commands/help.js +11 -1
  27. package/src/commands/model.js +42 -7
  28. package/src/commands/reasoning_effort.js +2 -2
  29. package/src/commands/skills.js +46 -0
  30. package/src/config/ai_models.js +106 -6
  31. package/src/config/constants.js +71 -0
  32. package/src/config/feature_flags.js +6 -7
  33. package/src/frontend/App.js +108 -1
  34. package/src/frontend/components/AutocompleteMenu.js +7 -1
  35. package/src/frontend/components/BackgroundProcessList.js +175 -0
  36. package/src/frontend/components/ConversationItem.js +26 -10
  37. package/src/frontend/components/CurrentModelView.js +2 -2
  38. package/src/frontend/components/HelpView.js +106 -2
  39. package/src/frontend/components/Input.js +33 -11
  40. package/src/frontend/components/ModelListView.js +1 -1
  41. package/src/frontend/components/SetupWizard.js +51 -8
  42. package/src/frontend/hooks/useFileCompletion.js +467 -0
  43. package/src/frontend/utils/toolUIFormatter.js +261 -0
  44. package/src/system/agents_loader.js +289 -0
  45. package/src/system/ai_request.js +156 -12
  46. package/src/system/background_process.js +317 -0
  47. package/src/system/code_executer.js +496 -56
  48. package/src/system/command_parser.js +33 -3
  49. package/src/system/conversation_state.js +265 -0
  50. package/src/system/conversation_trimmer.js +132 -0
  51. package/src/system/custom_command_loader.js +386 -0
  52. package/src/system/file_integrity.js +73 -10
  53. package/src/system/log.js +10 -2
  54. package/src/system/output_helper.js +52 -9
  55. package/src/system/session.js +213 -58
  56. package/src/system/session_memory.js +30 -2
  57. package/src/system/skill_loader.js +318 -0
  58. package/src/system/system_info.js +254 -40
  59. package/src/system/tool_approval.js +10 -0
  60. package/src/system/tool_registry.js +15 -1
  61. package/src/system/ui_events.js +11 -0
  62. package/src/tools/code_editor.js +16 -10
  63. package/src/tools/file_reader.js +66 -9
  64. package/src/tools/glob.js +0 -3
  65. package/src/tools/ripgrep.js +5 -7
  66. package/src/tools/skill_tool.js +122 -0
  67. package/src/tools/web_downloader.js +0 -3
  68. package/src/util/clone.js +174 -0
  69. package/src/util/config.js +55 -2
  70. package/src/util/config_migration.js +174 -0
  71. package/src/util/debug_log.js +8 -2
  72. package/src/util/exit_handler.js +8 -0
  73. package/src/util/file_reference_parser.js +132 -0
  74. package/src/util/path_validator.js +178 -0
  75. package/src/util/prompt_loader.js +91 -1
  76. package/src/util/safe_fs.js +66 -3
  77. package/payload_viewer/out/_next/static/chunks/ecd2072ebf41611f.css +0 -3
  78. /package/payload_viewer/out/_next/static/{wkEKh6i9XPSyP6rjDRvHn → 42iEoi-1o5MxNIZ1SWSvV}/_buildManifest.js +0 -0
  79. /package/payload_viewer/out/_next/static/{wkEKh6i9XPSyP6rjDRvHn → 42iEoi-1o5MxNIZ1SWSvV}/_clientMiddlewareManifest.json +0 -0
  80. /package/payload_viewer/out/_next/static/{wkEKh6i9XPSyP6rjDRvHn → 42iEoi-1o5MxNIZ1SWSvV}/_ssgManifest.js +0 -0
@@ -3,6 +3,7 @@ import path from 'path';
3
3
  import fs from 'fs';
4
4
  import { fileURLToPath } from 'url';
5
5
  import OpenAI from 'openai';
6
+ import Anthropic from '@anthropic-ai/sdk';
6
7
  function consolelog() { }
7
8
 
8
9
  const __filename = fileURLToPath(import.meta.url);
@@ -48,6 +49,46 @@ if (openaiApiKey) {
48
49
  consolelog(' Checked: process.env.OPENAI_API_KEY and ~/.aiexe/settings.json');
49
50
  }
50
51
 
52
+ // Initialize Z.AI client (Anthropic SDK with Z.AI base URL)
53
+ let zaiClient = null;
54
+ const zaiApiKey = process.env.ZAI_API_KEY || aiAgentSettings.API_KEY;
55
+ const ZAI_BASE_URL = 'https://api.z.ai/api/anthropic';
56
+
57
+ // Check if API key is Z.AI format (32-char hex + '.' + 16-char alphanumeric)
58
+ function isZaiApiKey(apiKey) {
59
+ if (!apiKey || typeof apiKey !== 'string') return false;
60
+ return /^[a-f0-9]{32}\.[A-Za-z0-9]{16}$/.test(apiKey);
61
+ }
62
+
63
+ if (zaiApiKey && isZaiApiKey(zaiApiKey)) {
64
+ zaiClient = new Anthropic({
65
+ apiKey: zaiApiKey,
66
+ baseURL: ZAI_BASE_URL,
67
+ });
68
+ consolelog('✅ Z.AI client initialized (Anthropic SDK with Z.AI base URL)');
69
+ } else {
70
+ consolelog('⚠️ Z.AI API key not found or invalid format - Z.AI testing will return mock responses');
71
+ }
72
+
73
+ // Initialize Anthropic client
74
+ let anthropicClient = null;
75
+ const anthropicApiKey = process.env.ANTHROPIC_API_KEY || aiAgentSettings.ANTHROPIC_API_KEY;
76
+
77
+ // Check if API key is Anthropic format (sk-ant-...)
78
+ function isAnthropicApiKey(apiKey) {
79
+ if (!apiKey || typeof apiKey !== 'string') return false;
80
+ return apiKey.startsWith('sk-ant-');
81
+ }
82
+
83
+ if (anthropicApiKey && isAnthropicApiKey(anthropicApiKey)) {
84
+ anthropicClient = new Anthropic({
85
+ apiKey: anthropicApiKey,
86
+ });
87
+ consolelog('✅ Anthropic client initialized');
88
+ } else {
89
+ consolelog('⚠️ Anthropic API key not found or invalid format - Anthropic testing will return mock responses');
90
+ }
91
+
51
92
 
52
93
  // ID generation function
53
94
  function generateId() {
@@ -420,6 +461,326 @@ function startWebServer(port = 3300) {
420
461
  }
421
462
  });
422
463
 
464
+ // Anthropic API test endpoint
465
+ app.post('/api/test-anthropic', async (req, res) => {
466
+ try {
467
+ const payload = req.body;
468
+
469
+ if (anthropicClient && anthropicApiKey && isAnthropicApiKey(anthropicApiKey)) {
470
+ // Convert Responses API format to Anthropic Messages API format if needed
471
+ let anthropicPayload = { ...payload };
472
+
473
+ // If payload uses Responses API format (input array), convert to messages
474
+ if (payload.input && Array.isArray(payload.input)) {
475
+ const messages = [];
476
+ let systemMessage = null;
477
+
478
+ for (const item of payload.input) {
479
+ if (item.role === 'system') {
480
+ if (Array.isArray(item.content)) {
481
+ systemMessage = item.content.map(c => c.text || c).join('\n');
482
+ } else if (typeof item.content === 'string') {
483
+ systemMessage = item.content;
484
+ }
485
+ } else if (item.role === 'user' || item.role === 'assistant') {
486
+ let content;
487
+ if (Array.isArray(item.content)) {
488
+ content = item.content.map(c => ({
489
+ type: 'text',
490
+ text: c.text || c
491
+ }));
492
+ } else {
493
+ content = [{ type: 'text', text: item.content || '' }];
494
+ }
495
+ messages.push({ role: item.role, content });
496
+ }
497
+ }
498
+
499
+ anthropicPayload = {
500
+ model: payload.model || 'claude-3-haiku-20240307',
501
+ max_tokens: payload.max_output_tokens || payload.max_tokens || 4096,
502
+ messages: messages,
503
+ };
504
+
505
+ if (systemMessage) {
506
+ anthropicPayload.system = systemMessage;
507
+ }
508
+ }
509
+
510
+ // Ensure required fields
511
+ if (!anthropicPayload.model) anthropicPayload.model = 'claude-3-haiku-20240307';
512
+ if (!anthropicPayload.max_tokens) anthropicPayload.max_tokens = 4096;
513
+
514
+ // Make the API call
515
+ const response = await anthropicClient.messages.create(anthropicPayload);
516
+
517
+ // Convert Anthropic response to Responses API format
518
+ const output = [];
519
+ let outputText = '';
520
+
521
+ if (response.content && Array.isArray(response.content)) {
522
+ for (const block of response.content) {
523
+ if (block.type === 'text') {
524
+ outputText += block.text;
525
+ } else if (block.type === 'tool_use') {
526
+ output.push({
527
+ type: 'function_call',
528
+ id: block.id,
529
+ call_id: block.id,
530
+ name: block.name,
531
+ arguments: JSON.stringify(block.input)
532
+ });
533
+ }
534
+ }
535
+ }
536
+
537
+ if (outputText) {
538
+ output.unshift({
539
+ type: 'message',
540
+ id: `msg_${generateId()}`,
541
+ status: 'completed',
542
+ role: 'assistant',
543
+ content: [{
544
+ type: 'output_text',
545
+ text: outputText
546
+ }]
547
+ });
548
+ }
549
+
550
+ const convertedResponse = {
551
+ id: response.id,
552
+ object: 'response',
553
+ created_at: Math.floor(Date.now() / 1000),
554
+ status: response.stop_reason === 'end_turn' ? 'completed' : 'incomplete',
555
+ model: response.model,
556
+ provider: 'anthropic',
557
+ output: output,
558
+ usage: {
559
+ input_tokens: response.usage?.input_tokens || 0,
560
+ output_tokens: response.usage?.output_tokens || 0,
561
+ total_tokens: (response.usage?.input_tokens || 0) + (response.usage?.output_tokens || 0),
562
+ cache_creation_input_tokens: response.usage?.cache_creation_input_tokens,
563
+ cache_read_input_tokens: response.usage?.cache_read_input_tokens
564
+ },
565
+ stop_reason: response.stop_reason
566
+ };
567
+
568
+ res.json({
569
+ success: true,
570
+ provider: 'anthropic',
571
+ status: 200,
572
+ data: convertedResponse,
573
+ originalPayload: payload,
574
+ convertedPayload: anthropicPayload,
575
+ rawResponse: response
576
+ });
577
+ } else {
578
+ // Mock response when API key is not available
579
+ res.json({
580
+ success: false,
581
+ provider: 'anthropic',
582
+ error: 'Anthropic API key not found or invalid format',
583
+ hint: 'Anthropic API key format: sk-ant-...',
584
+ mockResponse: {
585
+ taskName: "api_test_RES",
586
+ timestamp: new Date().toISOString(),
587
+ data: {
588
+ id: `resp_${generateId()}`,
589
+ object: "response",
590
+ created_at: Math.floor(Date.now() / 1000),
591
+ status: "completed",
592
+ model: payload.model || 'claude-3-haiku-20240307',
593
+ provider: 'anthropic',
594
+ output: [{
595
+ id: `msg_${generateId()}`,
596
+ type: "message",
597
+ status: "completed",
598
+ content: [{
599
+ type: "output_text",
600
+ text: 'This is a mock response. Set a valid Anthropic API key to get real responses.'
601
+ }],
602
+ role: "assistant"
603
+ }],
604
+ usage: {
605
+ input_tokens: 10,
606
+ output_tokens: 15,
607
+ total_tokens: 25
608
+ }
609
+ }
610
+ },
611
+ originalPayload: payload
612
+ });
613
+ }
614
+ } catch (error) {
615
+ res.status(500).json({
616
+ success: false,
617
+ provider: 'anthropic',
618
+ error: error.message,
619
+ originalPayload: req.body
620
+ });
621
+ }
622
+ });
623
+
624
+ // Z.AI (GLM) API test endpoint - Uses Anthropic SDK with Z.AI base URL
625
+ app.post('/api/test-zai', async (req, res) => {
626
+ try {
627
+ const payload = req.body;
628
+
629
+ if (zaiClient && zaiApiKey && isZaiApiKey(zaiApiKey)) {
630
+ // Convert Responses API format to Anthropic Messages API format if needed
631
+ let zaiPayload = { ...payload };
632
+
633
+ // If payload uses Responses API format (input array), convert to messages
634
+ if (payload.input && Array.isArray(payload.input)) {
635
+ const messages = [];
636
+ let systemMessage = null;
637
+
638
+ for (const item of payload.input) {
639
+ if (item.role === 'system') {
640
+ // Extract system message content
641
+ if (Array.isArray(item.content)) {
642
+ systemMessage = item.content.map(c => c.text || c).join('\n');
643
+ } else if (typeof item.content === 'string') {
644
+ systemMessage = item.content;
645
+ }
646
+ } else if (item.role === 'user' || item.role === 'assistant') {
647
+ let content;
648
+ if (Array.isArray(item.content)) {
649
+ content = item.content.map(c => ({
650
+ type: 'text',
651
+ text: c.text || c
652
+ }));
653
+ } else {
654
+ content = [{ type: 'text', text: item.content || '' }];
655
+ }
656
+ messages.push({ role: item.role, content });
657
+ }
658
+ }
659
+
660
+ zaiPayload = {
661
+ model: payload.model || 'glm-4.5',
662
+ max_tokens: payload.max_output_tokens || payload.max_tokens || 8192,
663
+ messages: messages,
664
+ };
665
+
666
+ if (systemMessage) {
667
+ zaiPayload.system = systemMessage;
668
+ }
669
+ }
670
+
671
+ // Ensure required fields
672
+ if (!zaiPayload.model) zaiPayload.model = 'glm-4.5';
673
+ if (!zaiPayload.max_tokens) zaiPayload.max_tokens = 8192;
674
+
675
+ // Make the API call
676
+ const response = await zaiClient.messages.create(zaiPayload);
677
+
678
+ // Convert Anthropic response to Responses API format
679
+ const output = [];
680
+ let outputText = '';
681
+
682
+ if (response.content && Array.isArray(response.content)) {
683
+ for (const block of response.content) {
684
+ if (block.type === 'text') {
685
+ outputText += block.text;
686
+ } else if (block.type === 'tool_use') {
687
+ output.push({
688
+ type: 'function_call',
689
+ id: block.id,
690
+ call_id: block.id,
691
+ name: block.name,
692
+ arguments: JSON.stringify(block.input)
693
+ });
694
+ }
695
+ }
696
+ }
697
+
698
+ if (outputText) {
699
+ output.unshift({
700
+ type: 'message',
701
+ id: `msg_${generateId()}`,
702
+ status: 'completed',
703
+ role: 'assistant',
704
+ content: [{
705
+ type: 'output_text',
706
+ text: outputText
707
+ }]
708
+ });
709
+ }
710
+
711
+ const convertedResponse = {
712
+ id: response.id,
713
+ object: 'response',
714
+ created_at: Math.floor(Date.now() / 1000),
715
+ status: response.stop_reason === 'end_turn' ? 'completed' : 'incomplete',
716
+ model: response.model,
717
+ provider: 'zai',
718
+ output: output,
719
+ usage: {
720
+ input_tokens: response.usage?.input_tokens || 0,
721
+ output_tokens: response.usage?.output_tokens || 0,
722
+ total_tokens: (response.usage?.input_tokens || 0) + (response.usage?.output_tokens || 0),
723
+ cache_creation_input_tokens: response.usage?.cache_creation_input_tokens,
724
+ cache_read_input_tokens: response.usage?.cache_read_input_tokens
725
+ },
726
+ stop_reason: response.stop_reason
727
+ };
728
+
729
+ res.json({
730
+ success: true,
731
+ provider: 'zai',
732
+ status: 200,
733
+ data: convertedResponse,
734
+ originalPayload: payload,
735
+ convertedPayload: zaiPayload,
736
+ rawResponse: response
737
+ });
738
+ } else {
739
+ // Mock response when API key is not available
740
+ res.json({
741
+ success: false,
742
+ provider: 'zai',
743
+ error: 'Z.AI API key not found or invalid format',
744
+ hint: 'Z.AI API key format: 32-char hex + "." + 16-char alphanumeric',
745
+ mockResponse: {
746
+ taskName: "api_test_RES",
747
+ timestamp: new Date().toISOString(),
748
+ data: {
749
+ id: `resp_${generateId()}`,
750
+ object: "response",
751
+ created_at: Math.floor(Date.now() / 1000),
752
+ status: "completed",
753
+ model: payload.model || 'glm-4.5',
754
+ provider: 'zai',
755
+ output: [{
756
+ id: `msg_${generateId()}`,
757
+ type: "message",
758
+ status: "completed",
759
+ content: [{
760
+ type: "output_text",
761
+ text: 'This is a mock response. Set a valid Z.AI API key to get real responses.'
762
+ }],
763
+ role: "assistant"
764
+ }],
765
+ usage: {
766
+ input_tokens: 10,
767
+ output_tokens: 15,
768
+ total_tokens: 25
769
+ }
770
+ }
771
+ },
772
+ originalPayload: payload
773
+ });
774
+ }
775
+ } catch (error) {
776
+ res.status(500).json({
777
+ success: false,
778
+ provider: 'zai',
779
+ error: error.message,
780
+ originalPayload: req.body
781
+ });
782
+ }
783
+ });
423
784
 
424
785
  // Health check endpoint
425
786
  app.get('/api/health', (req, res) => {
@@ -15,6 +15,7 @@ You have access to the full conversation history between the orchestrator and th
15
15
  **CORE PRINCIPLE**: Focus STRICTLY on whether the ESSENTIAL requirements requested by the user have been fulfilled. The agent should NEVER perform optional enhancements beyond the user's explicit request.
16
16
 
17
17
  ### Mission is COMPLETE (should_complete: true) when:
18
+ - **The request cannot be fulfilled as stated**: The assistant clearly explains that the literal request is impossible and why. Do NOT continue pursuing an unfulfillable goal.
18
19
  - **All essential requirements from the user's original request have been satisfied**
19
20
  - The assistant explicitly states the task is finished/complete/done
20
21
  - The assistant provides final results or deliverables that satisfy the original mission's core requirements
@@ -31,6 +32,9 @@ You have access to the full conversation history between the orchestrator and th
31
32
  - The assistant's message is incomplete or cut off
32
33
  - The message is just status updates without clear completion signals
33
34
  - **There are mandatory next steps required to fulfill the user's core request**
35
+ - **The assistant is seeking permission, confirmation, or approval before taking action**
36
+ - **The assistant offers to do something rather than just doing it** (e.g., "Would you like me to...", "Should I...", "Do you want me to...", "Can I...")
37
+ - **The assistant's response implies waiting for user decision before proceeding with work**
34
38
 
35
39
  ### Key Distinction:
36
40
  - **Essential Requirements**: ONLY the core functionality, features, or fixes explicitly requested by the user
@@ -47,6 +47,21 @@ NEVER ASK USER:
47
47
  - Permission to continue
48
48
  - Technical decisions
49
49
 
50
+ # Understanding request feasibility
51
+
52
+ Before attempting any action, assess whether the request is actually achievable:
53
+
54
+ 1. **Literal interpretation first**: Understand what the user literally asked for
55
+ 2. **Feasibility check**: Can this request actually be fulfilled as stated?
56
+ 3. **No silent reinterpretation**: If the literal request is impossible, do NOT silently substitute it with something "related" or "similar"
57
+
58
+ When a request cannot be fulfilled as stated:
59
+ - Clearly explain why it cannot be done
60
+ - Ask for clarification or suggest what you CAN do
61
+ - Do NOT attempt workarounds that don't address the actual request
62
+
63
+ Principle: Honesty about limitations is more valuable than creative reinterpretation that misses the point.
64
+
50
65
  # Understanding user intent
51
66
 
52
67
  Distinguish between conversation and work:
@@ -379,7 +394,33 @@ Use for: Finding code by content, exploring codebases, locating specific impleme
379
394
 
380
395
  ### bash
381
396
 
382
- Purpose: Execute shell commands
397
+ Purpose: Execute shell commands (for terminal operations ONLY)
398
+
399
+ **CRITICAL - Use Specialized Tools Instead of Bash:**
400
+
401
+ NEVER use bash for these operations - use the dedicated tools:
402
+
403
+ | Operation | WRONG (bash) | CORRECT (dedicated tool) |
404
+ |-----------|--------------|--------------------------|
405
+ | Read files | `cat file.js` | `read_file({ filePath: "file.js" })` |
406
+ | Read file sections | `head -100 file.js` | `read_file_range({ filePath, startLine, endLine })` |
407
+ | Search content | `grep -r "pattern" .` | `ripgrep({ pattern: "pattern" })` |
408
+ | Find files | `find . -name "*.js"` | `glob_search({ pattern: "**/*.js" })` |
409
+ | Edit files | `sed -i 's/old/new/' file` | `edit_file_replace({ file_path, old_string, new_string })` |
410
+ | Write files | `echo "content" > file` | `write_file({ file_path, content })` |
411
+
412
+ **Why dedicated tools are mandatory:**
413
+ - bash output is truncated to 8000 chars - long files get cut off
414
+ - Dedicated tools have proper error handling and formatting
415
+ - Dedicated tools integrate with file integrity tracking
416
+ - Dedicated tools display results properly in UI
417
+
418
+ **When to use bash:**
419
+ - git commands: `git status`, `git commit`, `git push`
420
+ - Package management: `npm install`, `pip install`
421
+ - Running scripts: `npm test`, `python script.py`
422
+ - Directory operations: `mkdir`, `rm -rf`, `mv`, `cp`
423
+ - System commands: `chmod`, `chown`, `which`
383
424
 
384
425
  Usage notes:
385
426
  - Output limits: stdout 8000 chars, stderr 4000 chars
@@ -813,10 +854,43 @@ Match the user's language:
813
854
 
814
855
  ## Tool usage
815
856
 
816
- - Use specialized tools: glob_search and ripgrep, NOT bash find/grep
817
- - No file editing via bash: Never use sed, awk, echo > for file content
857
+ **MANDATORY - Specialized Tools Over Bash:**
858
+
859
+ This is NOT optional. You MUST use dedicated tools for these operations:
860
+
861
+ | Task | NEVER Use | ALWAYS Use |
862
+ |------|-----------|------------|
863
+ | Read files | cat, head, tail, less | read_file, read_file_range |
864
+ | Search content | grep, rg, ack | ripgrep |
865
+ | Find files | find, ls -R, locate | glob_search |
866
+ | Edit files | sed, awk, perl -i | edit_file_replace |
867
+ | Create/write files | echo >, cat <<EOF | write_file |
868
+
869
+ **Why this matters:**
870
+ - bash output truncated at 8000 chars → long content gets lost
871
+ - Dedicated tools have built-in limits and error handling
872
+ - File integrity tracking only works with dedicated tools
873
+ - Results display properly in UI with dedicated tools
874
+
875
+ **Correct patterns:**
876
+ ```
877
+ # Find files → glob_search
878
+ glob_search({ pattern: "**/*.ts" })
879
+
880
+ # Search content → ripgrep
881
+ ripgrep({ pattern: "TODO", output_mode: "content", head_limit: 20 })
882
+
883
+ # Read file → read_file
884
+ read_file({ filePath: "src/index.js" })
885
+
886
+ # Large file → read_file_range
887
+ read_file_range({ filePath: "big.log", startLine: 1, endLine: 500 })
888
+ ```
889
+
890
+ **Other tool usage rules:**
818
891
  - Auto-exclusions trusted: node_modules, .git, etc. are automatically excluded
819
892
  - Parallel when possible: Execute independent tool calls simultaneously
893
+ - Check output limits: ripgrep has 30KB limit, read_file has 2000 line limit
820
894
 
821
895
  ## Error handling
822
896
 
@@ -827,6 +901,44 @@ When errors occur, handle them autonomously:
827
901
  - Fix immediately: Don't report errors - fix them and continue
828
902
  - Iterate as needed: If fix doesn't work, try alternative approaches
829
903
 
904
+ ## CRITICAL - Avoiding repetitive behavior
905
+
906
+ **You MUST recognize and break out of repetitive patterns:**
907
+
908
+ SELF-AWARENESS RULES:
909
+ 1. **Same action, same result = STOP**: If you execute the same command and get the same result twice, DO NOT try it a third time
910
+ 2. **Analyze before retrying**: When something fails, understand WHY before trying again
911
+ 3. **Change approach**: If an approach isn't working, try a fundamentally different strategy
912
+ 4. **Admit limitations**: If you cannot solve a problem after 2-3 different approaches, clearly tell the user
913
+
914
+ FORBIDDEN PATTERNS:
915
+ - Running the same bash command repeatedly hoping for different results
916
+ - Re-reading the same file without making changes
917
+ - Retrying the same edit that failed without fixing the root cause
918
+ - Looping through identical tool calls
919
+
920
+ REQUIRED BEHAVIOR:
921
+ - After failure: STOP → ANALYZE root cause → TRY DIFFERENT approach
922
+ - After 2 identical failures: STOP completely and inform user
923
+ - When stuck: Clearly explain what you tried, why it failed, and ask for guidance
924
+
925
+ EXAMPLE - WRONG:
926
+ ```
927
+ bash("node test.js") → Error
928
+ bash("node test.js") → Same error
929
+ bash("node test.js") → Same error (FORBIDDEN - endless loop!)
930
+ ```
931
+
932
+ EXAMPLE - CORRECT:
933
+ ```
934
+ bash("node test.js") → Error: "module not found"
935
+ STOP and ANALYZE: The error says module is not found
936
+ read_file("test.js") → Check what module is being imported
937
+ DIFFERENT APPROACH: Fix the import or install the module
938
+ ```
939
+
940
+ **If you find yourself doing the same thing more than twice, you have FAILED to think properly. STOP and THINK.**
941
+
830
942
  # Response format
831
943
 
832
944
  ## Tool call structure
@@ -1092,3 +1204,4 @@ ASK USER:
1092
1204
 
1093
1205
  DECIDE YOURSELF:
1094
1206
  - All implementation details (HOW to implement)
1207
+