@defai.digital/ax-cli 3.8.7 → 3.8.9

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 (209) hide show
  1. package/README.md +50 -393
  2. package/config-defaults/prompts.yaml +96 -12
  3. package/config-defaults/settings.yaml +3 -0
  4. package/dist/agent/llm-agent.d.ts +11 -2
  5. package/dist/agent/llm-agent.js +75 -104
  6. package/dist/agent/llm-agent.js.map +1 -1
  7. package/dist/agent/loop-detector.d.ts +70 -0
  8. package/dist/agent/loop-detector.js +339 -0
  9. package/dist/agent/loop-detector.js.map +1 -0
  10. package/dist/agent/progress-tracker.d.ts +94 -0
  11. package/dist/agent/progress-tracker.js +222 -0
  12. package/dist/agent/progress-tracker.js.map +1 -0
  13. package/dist/agent/specialized/analysis-agent.js +7 -16
  14. package/dist/agent/specialized/analysis-agent.js.map +1 -1
  15. package/dist/agent/specialized/debug-agent.js +7 -16
  16. package/dist/agent/specialized/debug-agent.js.map +1 -1
  17. package/dist/agent/specialized/documentation-agent.js +7 -16
  18. package/dist/agent/specialized/documentation-agent.js.map +1 -1
  19. package/dist/agent/specialized/performance-agent.js +7 -16
  20. package/dist/agent/specialized/performance-agent.js.map +1 -1
  21. package/dist/agent/specialized/refactoring-agent.js +7 -16
  22. package/dist/agent/specialized/refactoring-agent.js.map +1 -1
  23. package/dist/agent/specialized/testing-agent.js +7 -16
  24. package/dist/agent/specialized/testing-agent.js.map +1 -1
  25. package/dist/agent/status-reporter.js +2 -2
  26. package/dist/agent/status-reporter.js.map +1 -1
  27. package/dist/agent/subagent-types.d.ts +6 -0
  28. package/dist/agent/subagent-types.js +43 -56
  29. package/dist/agent/subagent-types.js.map +1 -1
  30. package/dist/agent/subagent.js +3 -3
  31. package/dist/agent/subagent.js.map +1 -1
  32. package/dist/analyzers/git/churn-calculator.js +2 -1
  33. package/dist/analyzers/git/churn-calculator.js.map +1 -1
  34. package/dist/checkpoint/storage.js +6 -4
  35. package/dist/checkpoint/storage.js.map +1 -1
  36. package/dist/commands/cache.js +8 -6
  37. package/dist/commands/cache.js.map +1 -1
  38. package/dist/commands/doctor.js +19 -27
  39. package/dist/commands/doctor.js.map +1 -1
  40. package/dist/commands/init.js +6 -5
  41. package/dist/commands/init.js.map +1 -1
  42. package/dist/commands/mcp-migrate.js +6 -5
  43. package/dist/commands/mcp-migrate.js.map +1 -1
  44. package/dist/commands/memory.js +8 -8
  45. package/dist/commands/memory.js.map +1 -1
  46. package/dist/commands/models.js +8 -12
  47. package/dist/commands/models.js.map +1 -1
  48. package/dist/commands/plan.js +1 -10
  49. package/dist/commands/plan.js.map +1 -1
  50. package/dist/commands/setup.js +5 -4
  51. package/dist/commands/setup.js.map +1 -1
  52. package/dist/commands/status.js +4 -4
  53. package/dist/commands/status.js.map +1 -1
  54. package/dist/constants.d.ts +50 -0
  55. package/dist/constants.js +55 -4
  56. package/dist/constants.js.map +1 -1
  57. package/dist/hooks/hook-runner.d.ts +138 -0
  58. package/dist/hooks/hook-runner.js +429 -0
  59. package/dist/hooks/hook-runner.js.map +1 -0
  60. package/dist/hooks/index.d.ts +6 -0
  61. package/dist/hooks/index.js +7 -0
  62. package/dist/hooks/index.js.map +1 -0
  63. package/dist/index.js +1 -19
  64. package/dist/index.js.map +1 -1
  65. package/dist/llm/tools.js +41 -43
  66. package/dist/llm/tools.js.map +1 -1
  67. package/dist/mcp/automatosx-loader.js +2 -1
  68. package/dist/mcp/automatosx-loader.js.map +1 -1
  69. package/dist/mcp/config-migrator.js +3 -2
  70. package/dist/mcp/config-migrator.js.map +1 -1
  71. package/dist/mcp/config-v2.d.ts +5 -0
  72. package/dist/mcp/config-v2.js +26 -0
  73. package/dist/mcp/config-v2.js.map +1 -1
  74. package/dist/mcp/error-formatter.js +4 -1
  75. package/dist/mcp/error-formatter.js.map +1 -1
  76. package/dist/mcp/reconnection.js +2 -1
  77. package/dist/mcp/reconnection.js.map +1 -1
  78. package/dist/mcp/registry.js +3 -2
  79. package/dist/mcp/registry.js.map +1 -1
  80. package/dist/mcp/resources.js +2 -1
  81. package/dist/mcp/resources.js.map +1 -1
  82. package/dist/mcp/validation.js +9 -0
  83. package/dist/mcp/validation.js.map +1 -1
  84. package/dist/memory/context-store.js +4 -6
  85. package/dist/memory/context-store.js.map +1 -1
  86. package/dist/memory/types.d.ts +2 -0
  87. package/dist/memory/types.js +4 -1
  88. package/dist/memory/types.js.map +1 -1
  89. package/dist/permissions/index.d.ts +6 -0
  90. package/dist/permissions/index.js +7 -0
  91. package/dist/permissions/index.js.map +1 -0
  92. package/dist/permissions/permission-manager.d.ts +145 -0
  93. package/dist/permissions/permission-manager.js +401 -0
  94. package/dist/permissions/permission-manager.js.map +1 -0
  95. package/dist/planner/task-planner.js +2 -1
  96. package/dist/planner/task-planner.js.map +1 -1
  97. package/dist/schemas/index.d.ts +2 -2
  98. package/dist/schemas/settings-schemas.d.ts +0 -14
  99. package/dist/schemas/settings-schemas.js +0 -10
  100. package/dist/schemas/settings-schemas.js.map +1 -1
  101. package/dist/schemas/tool-schemas.d.ts +2 -2
  102. package/dist/schemas/yaml-schemas.d.ts +62 -0
  103. package/dist/schemas/yaml-schemas.js +4 -0
  104. package/dist/schemas/yaml-schemas.js.map +1 -1
  105. package/dist/tools/bash.js +6 -5
  106. package/dist/tools/bash.js.map +1 -1
  107. package/dist/tools/confirmation-tool.js +3 -2
  108. package/dist/tools/confirmation-tool.js.map +1 -1
  109. package/dist/tools/registry.d.ts +1 -1
  110. package/dist/tools/registry.js +2 -1
  111. package/dist/tools/registry.js.map +1 -1
  112. package/dist/tools/text-editor.d.ts +9 -0
  113. package/dist/tools/text-editor.js +169 -0
  114. package/dist/tools/text-editor.js.map +1 -1
  115. package/dist/tools/todo-tool.js +3 -2
  116. package/dist/tools/todo-tool.js.map +1 -1
  117. package/dist/ui/components/tool-group-display.js +0 -6
  118. package/dist/ui/components/tool-group-display.js.map +1 -1
  119. package/dist/ui/hooks/use-input-handler.js +7 -6
  120. package/dist/ui/hooks/use-input-handler.js.map +1 -1
  121. package/dist/ui/hooks/use-input-history.js +4 -4
  122. package/dist/ui/hooks/use-input-history.js.map +1 -1
  123. package/dist/ui/utils/tool-grouper.d.ts +1 -2
  124. package/dist/ui/utils/tool-grouper.js +4 -15
  125. package/dist/ui/utils/tool-grouper.js.map +1 -1
  126. package/dist/utils/audit-logger.js +2 -1
  127. package/dist/utils/audit-logger.js.map +1 -1
  128. package/dist/utils/config-loader.d.ts +4 -0
  129. package/dist/utils/config-loader.js.map +1 -1
  130. package/dist/utils/encryption.js +2 -1
  131. package/dist/utils/encryption.js.map +1 -1
  132. package/dist/utils/file-cache.js +4 -2
  133. package/dist/utils/file-cache.js.map +1 -1
  134. package/dist/utils/history-manager.js +6 -6
  135. package/dist/utils/history-manager.js.map +1 -1
  136. package/dist/utils/onboarding-manager.js +2 -1
  137. package/dist/utils/onboarding-manager.js.map +1 -1
  138. package/dist/utils/path-helpers.js +3 -2
  139. package/dist/utils/path-helpers.js.map +1 -1
  140. package/dist/utils/path-security.js +3 -2
  141. package/dist/utils/path-security.js.map +1 -1
  142. package/dist/utils/prompt-builder.js +4 -0
  143. package/dist/utils/prompt-builder.js.map +1 -1
  144. package/dist/utils/settings-manager.d.ts +1 -21
  145. package/dist/utils/settings-manager.js +6 -86
  146. package/dist/utils/settings-manager.js.map +1 -1
  147. package/dist/utils/streaming-analyzer.d.ts +2 -13
  148. package/dist/utils/streaming-analyzer.js +3 -25
  149. package/dist/utils/streaming-analyzer.js.map +1 -1
  150. package/dist/utils/template-manager.js +9 -8
  151. package/dist/utils/template-manager.js.map +1 -1
  152. package/dist/utils/token-counter.d.ts +8 -1
  153. package/dist/utils/token-counter.js +14 -5
  154. package/dist/utils/token-counter.js.map +1 -1
  155. package/package.json +3 -2
  156. package/packages/schemas/README.md +1 -1
  157. package/packages/schemas/package.json +1 -1
  158. package/.ax-cli/CUSTOM.md +0 -97
  159. package/.ax-cli/auto-accept-audit.json +0 -1302
  160. package/.ax-cli/index.json +0 -43
  161. package/.ax-cli/memory.json +0 -55
  162. package/.ax-cli/settings.json +0 -12
  163. package/ax.config.json +0 -303
  164. package/dist/tools/web-search/cache.d.ts +0 -62
  165. package/dist/tools/web-search/cache.js +0 -105
  166. package/dist/tools/web-search/cache.js.map +0 -1
  167. package/dist/tools/web-search/engines/crates.d.ts +0 -19
  168. package/dist/tools/web-search/engines/crates.js +0 -87
  169. package/dist/tools/web-search/engines/crates.js.map +0 -1
  170. package/dist/tools/web-search/engines/npm.d.ts +0 -18
  171. package/dist/tools/web-search/engines/npm.js +0 -86
  172. package/dist/tools/web-search/engines/npm.js.map +0 -1
  173. package/dist/tools/web-search/engines/pypi.d.ts +0 -18
  174. package/dist/tools/web-search/engines/pypi.js +0 -75
  175. package/dist/tools/web-search/engines/pypi.js.map +0 -1
  176. package/dist/tools/web-search/engines/stackoverflow.d.ts +0 -30
  177. package/dist/tools/web-search/engines/stackoverflow.js +0 -130
  178. package/dist/tools/web-search/engines/stackoverflow.js.map +0 -1
  179. package/dist/tools/web-search/engines/wikipedia.d.ts +0 -27
  180. package/dist/tools/web-search/engines/wikipedia.js +0 -112
  181. package/dist/tools/web-search/engines/wikipedia.js.map +0 -1
  182. package/dist/tools/web-search/index.d.ts +0 -11
  183. package/dist/tools/web-search/index.js +0 -11
  184. package/dist/tools/web-search/index.js.map +0 -1
  185. package/dist/tools/web-search/router.d.ts +0 -36
  186. package/dist/tools/web-search/router.js +0 -270
  187. package/dist/tools/web-search/router.js.map +0 -1
  188. package/dist/tools/web-search/types.d.ts +0 -45
  189. package/dist/tools/web-search/types.js +0 -6
  190. package/dist/tools/web-search/types.js.map +0 -1
  191. package/dist/tools/web-search/web-search-tool.d.ts +0 -51
  192. package/dist/tools/web-search/web-search-tool.js +0 -262
  193. package/dist/tools/web-search/web-search-tool.js.map +0 -1
  194. package/packages/schemas/dist/index.d.ts +0 -14
  195. package/packages/schemas/dist/index.d.ts.map +0 -1
  196. package/packages/schemas/dist/index.js +0 -19
  197. package/packages/schemas/dist/index.js.map +0 -1
  198. package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
  199. package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
  200. package/packages/schemas/dist/public/core/brand-types.js +0 -243
  201. package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
  202. package/packages/schemas/dist/public/core/enums.d.ts +0 -227
  203. package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
  204. package/packages/schemas/dist/public/core/enums.js +0 -222
  205. package/packages/schemas/dist/public/core/enums.js.map +0 -1
  206. package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
  207. package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
  208. package/packages/schemas/dist/public/core/id-types.js +0 -136
  209. package/packages/schemas/dist/public/core/id-types.js.map +0 -1
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Intelligent Loop Detection System
3
+ *
4
+ * Based on Claude Code and industry best practices:
5
+ * 1. Progress-based detection (checks if state changes)
6
+ * 2. Tool-specific thresholds (different tools have different legitimate repeat patterns)
7
+ * 3. Sequence pattern detection (A→B→A→B cycles)
8
+ * 4. Configurable and transparent
9
+ *
10
+ * Key insight: The problem isn't repeated tool calls, it's repeated tool calls
11
+ * that don't make progress. Creating 10 files is fine. Trying to edit the same
12
+ * file 10 times with the same failing edit is not.
13
+ */
14
+ import { LLMToolCall } from "../llm/client.js";
15
+ export interface LoopDetectionResult {
16
+ isLoop: boolean;
17
+ reason?: string;
18
+ suggestion?: string;
19
+ /** Current count for this signature */
20
+ count: number;
21
+ /** Threshold that would trigger loop detection */
22
+ threshold: number;
23
+ }
24
+ export declare class LoopDetector {
25
+ /** Recent tool calls with full context */
26
+ private callHistory;
27
+ /** Signature -> count for quick lookup */
28
+ private signatureCounts;
29
+ /** Signature -> consecutive failure count */
30
+ private failureCounts;
31
+ /** Last N signatures for sequence detection */
32
+ private recentSequence;
33
+ /** Maximum history size */
34
+ private maxHistorySize;
35
+ /** Maximum sequence length for pattern detection */
36
+ private maxSequenceLength;
37
+ /**
38
+ * Check if a tool call would create a loop
39
+ * Call this BEFORE executing the tool
40
+ */
41
+ checkForLoop(toolCall: LLMToolCall): LoopDetectionResult;
42
+ /**
43
+ * Record a tool call after execution
44
+ * Call this AFTER executing the tool
45
+ */
46
+ recordToolCall(toolCall: LLMToolCall, success: boolean, outputHash?: string): void;
47
+ /**
48
+ * Reset all tracking (call at start of new conversation)
49
+ */
50
+ reset(): void;
51
+ /**
52
+ * Get current stats for debugging
53
+ */
54
+ getStats(): {
55
+ historySize: number;
56
+ uniqueSignatures: number;
57
+ failedSignatures: number;
58
+ };
59
+ private parseArgs;
60
+ private createSignature;
61
+ private extractFilePath;
62
+ private getThreshold;
63
+ private adjustThresholdForFailures;
64
+ private detectCycle;
65
+ private getSuggestion;
66
+ private hashString;
67
+ private cleanup;
68
+ }
69
+ export declare function getLoopDetector(): LoopDetector;
70
+ export declare function resetLoopDetector(): void;
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Intelligent Loop Detection System
3
+ *
4
+ * Based on Claude Code and industry best practices:
5
+ * 1. Progress-based detection (checks if state changes)
6
+ * 2. Tool-specific thresholds (different tools have different legitimate repeat patterns)
7
+ * 3. Sequence pattern detection (A→B→A→B cycles)
8
+ * 4. Configurable and transparent
9
+ *
10
+ * Key insight: The problem isn't repeated tool calls, it's repeated tool calls
11
+ * that don't make progress. Creating 10 files is fine. Trying to edit the same
12
+ * file 10 times with the same failing edit is not.
13
+ */
14
+ import { AGENT_CONFIG } from "../constants.js";
15
+ /**
16
+ * Configuration for tool-specific thresholds
17
+ * Higher thresholds for tools that are legitimately called repeatedly
18
+ */
19
+ const TOOL_THRESHOLDS = {
20
+ // File exploration - often need to view many files
21
+ view_file: 10,
22
+ read_file: 10,
23
+ list_files: 8,
24
+ // File creation - creating multiple files is normal
25
+ create_file: 15,
26
+ write_to_file: 15,
27
+ // Editing - more restrictive since repeated edits usually mean failure
28
+ str_replace_editor: 4,
29
+ // Search - may need multiple searches
30
+ search_files: 6,
31
+ search: 6,
32
+ // Bash - varies widely, use moderate threshold
33
+ bash: 8,
34
+ execute_bash: 8,
35
+ // Todo list - frequently updated
36
+ create_todo_list: 3,
37
+ update_todo_list: 10, // Higher because progress updates are normal
38
+ // Default for unknown tools
39
+ default: 5,
40
+ };
41
+ /**
42
+ * Tools that should be tracked by unique path/target
43
+ * These count repetitions per-target rather than globally
44
+ */
45
+ const PATH_TRACKED_TOOLS = new Set([
46
+ 'view_file',
47
+ 'read_file',
48
+ 'create_file',
49
+ 'write_to_file',
50
+ 'str_replace_editor',
51
+ ]);
52
+ /**
53
+ * Tools where failure should lower the threshold
54
+ * (repeated failures are more likely to be loops)
55
+ */
56
+ const FAILURE_SENSITIVE_TOOLS = new Set([
57
+ 'str_replace_editor',
58
+ 'bash',
59
+ 'execute_bash',
60
+ ]);
61
+ export class LoopDetector {
62
+ /** Recent tool calls with full context */
63
+ callHistory = [];
64
+ /** Signature -> count for quick lookup */
65
+ signatureCounts = new Map();
66
+ /** Signature -> consecutive failure count */
67
+ failureCounts = new Map();
68
+ /** Last N signatures for sequence detection */
69
+ recentSequence = [];
70
+ /** Maximum history size */
71
+ maxHistorySize = 100;
72
+ /** Maximum sequence length for pattern detection */
73
+ maxSequenceLength = 20;
74
+ /**
75
+ * Check if a tool call would create a loop
76
+ * Call this BEFORE executing the tool
77
+ */
78
+ checkForLoop(toolCall) {
79
+ // Check if loop detection is disabled
80
+ if (!AGENT_CONFIG.ENABLE_LOOP_DETECTION) {
81
+ return { isLoop: false, count: 0, threshold: Infinity };
82
+ }
83
+ try {
84
+ const args = this.parseArgs(toolCall);
85
+ const signature = this.createSignature(toolCall.function.name, args);
86
+ const threshold = this.getThreshold(toolCall.function.name, signature);
87
+ const currentCount = this.signatureCounts.get(signature) || 0;
88
+ const failureCount = this.failureCounts.get(signature) || 0;
89
+ // Adjust threshold based on failures
90
+ const adjustedThreshold = this.adjustThresholdForFailures(toolCall.function.name, threshold, failureCount);
91
+ // Check 1: Simple count-based detection with tool-specific threshold
92
+ if (currentCount >= adjustedThreshold) {
93
+ return {
94
+ isLoop: true,
95
+ reason: `Tool "${toolCall.function.name}" called ${currentCount + 1} times with same signature (threshold: ${adjustedThreshold})`,
96
+ suggestion: this.getSuggestion(toolCall.function.name, args),
97
+ count: currentCount + 1,
98
+ threshold: adjustedThreshold,
99
+ };
100
+ }
101
+ // Check 2: Sequence pattern detection (A→B→A→B cycles)
102
+ const cycleResult = this.detectCycle(signature);
103
+ if (cycleResult.isLoop) {
104
+ return {
105
+ ...cycleResult,
106
+ count: currentCount + 1,
107
+ threshold: adjustedThreshold,
108
+ };
109
+ }
110
+ return {
111
+ isLoop: false,
112
+ count: currentCount + 1,
113
+ threshold: adjustedThreshold,
114
+ };
115
+ }
116
+ catch (error) {
117
+ // On parse error, don't block
118
+ return { isLoop: false, count: 0, threshold: Infinity };
119
+ }
120
+ }
121
+ /**
122
+ * Record a tool call after execution
123
+ * Call this AFTER executing the tool
124
+ */
125
+ recordToolCall(toolCall, success, outputHash) {
126
+ const args = this.parseArgs(toolCall);
127
+ const signature = this.createSignature(toolCall.function.name, args);
128
+ const filePath = this.extractFilePath(args);
129
+ // Record in history
130
+ const record = {
131
+ signature,
132
+ toolName: toolCall.function.name,
133
+ args,
134
+ timestamp: Date.now(),
135
+ success,
136
+ filePath,
137
+ outputHash,
138
+ };
139
+ this.callHistory.push(record);
140
+ // Update signature count
141
+ const count = (this.signatureCounts.get(signature) || 0) + 1;
142
+ this.signatureCounts.set(signature, count);
143
+ // Update failure count
144
+ if (!success) {
145
+ const failures = (this.failureCounts.get(signature) || 0) + 1;
146
+ this.failureCounts.set(signature, failures);
147
+ }
148
+ else {
149
+ // Reset failure count on success
150
+ this.failureCounts.delete(signature);
151
+ }
152
+ // Update sequence
153
+ this.recentSequence.push(signature);
154
+ if (this.recentSequence.length > this.maxSequenceLength) {
155
+ this.recentSequence.shift();
156
+ }
157
+ // Cleanup old entries
158
+ this.cleanup();
159
+ }
160
+ /**
161
+ * Reset all tracking (call at start of new conversation)
162
+ */
163
+ reset() {
164
+ this.callHistory = [];
165
+ this.signatureCounts.clear();
166
+ this.failureCounts.clear();
167
+ this.recentSequence = [];
168
+ }
169
+ /**
170
+ * Get current stats for debugging
171
+ */
172
+ getStats() {
173
+ return {
174
+ historySize: this.callHistory.length,
175
+ uniqueSignatures: this.signatureCounts.size,
176
+ failedSignatures: this.failureCounts.size,
177
+ };
178
+ }
179
+ // ============================================================================
180
+ // Private Methods
181
+ // ============================================================================
182
+ parseArgs(toolCall) {
183
+ if (!toolCall.function.arguments) {
184
+ return {};
185
+ }
186
+ if (typeof toolCall.function.arguments === 'string') {
187
+ try {
188
+ return JSON.parse(toolCall.function.arguments);
189
+ }
190
+ catch {
191
+ return { raw: toolCall.function.arguments };
192
+ }
193
+ }
194
+ return toolCall.function.arguments;
195
+ }
196
+ createSignature(toolName, args) {
197
+ // For path-tracked tools, use path as primary key
198
+ if (PATH_TRACKED_TOOLS.has(toolName)) {
199
+ const path = this.extractFilePath(args);
200
+ if (path) {
201
+ // For editors, include edit content hash to distinguish different edits
202
+ if (toolName === 'str_replace_editor') {
203
+ const oldStr = typeof args.old_str === 'string' ? args.old_str : '';
204
+ const contentKey = this.hashString(oldStr.substring(0, 200));
205
+ return `${toolName}:${path}:${contentKey}`;
206
+ }
207
+ return `${toolName}:${path}`;
208
+ }
209
+ }
210
+ // For bash, use command as key
211
+ if (toolName === 'bash' || toolName === 'execute_bash') {
212
+ const cmd = typeof args.command === 'string'
213
+ ? args.command.trim().replace(/\s+/g, ' ')
214
+ : '';
215
+ return `${toolName}:${cmd}`;
216
+ }
217
+ // For search, use query as key
218
+ if (toolName === 'search' || toolName === 'search_files') {
219
+ const query = typeof args.query === 'string'
220
+ ? args.query.trim().toLowerCase()
221
+ : '';
222
+ return `${toolName}:${query}`;
223
+ }
224
+ // Default: tool name + stable hash of args
225
+ return `${toolName}:${this.hashString(JSON.stringify(args))}`;
226
+ }
227
+ extractFilePath(args) {
228
+ // Try common path argument names
229
+ for (const key of ['path', 'file_path', 'filepath', 'file']) {
230
+ if (typeof args[key] === 'string') {
231
+ return args[key];
232
+ }
233
+ }
234
+ return undefined;
235
+ }
236
+ getThreshold(toolName, _signature) {
237
+ // Use tool-specific threshold or default
238
+ return TOOL_THRESHOLDS[toolName] || TOOL_THRESHOLDS.default;
239
+ }
240
+ adjustThresholdForFailures(toolName, baseThreshold, failureCount) {
241
+ // For failure-sensitive tools, reduce threshold based on consecutive failures
242
+ if (FAILURE_SENSITIVE_TOOLS.has(toolName) && failureCount > 0) {
243
+ // Each failure reduces threshold by 1, minimum of 2
244
+ return Math.max(2, baseThreshold - failureCount);
245
+ }
246
+ return baseThreshold;
247
+ }
248
+ detectCycle(currentSignature) {
249
+ // Need at least 4 items for a 2-element cycle (A-B-A-B)
250
+ if (this.recentSequence.length < 4) {
251
+ return { isLoop: false, count: 0, threshold: Infinity };
252
+ }
253
+ // Check for 2-element cycles (A-B-A-B pattern)
254
+ const len = this.recentSequence.length;
255
+ const last4 = [...this.recentSequence.slice(-3), currentSignature];
256
+ if (last4[0] === last4[2] && last4[1] === last4[3]) {
257
+ // Check if this pattern has repeated 3+ times
258
+ let patternCount = 1;
259
+ for (let i = len - 4; i >= 1; i -= 2) {
260
+ if (this.recentSequence[i] === last4[1] && this.recentSequence[i - 1] === last4[0]) {
261
+ patternCount++;
262
+ }
263
+ else {
264
+ break;
265
+ }
266
+ }
267
+ if (patternCount >= 3) {
268
+ return {
269
+ isLoop: true,
270
+ reason: `Detected repeating cycle pattern (${patternCount} repetitions)`,
271
+ suggestion: 'The same sequence of operations is repeating. Try a different approach.',
272
+ count: patternCount,
273
+ threshold: 3,
274
+ };
275
+ }
276
+ }
277
+ return { isLoop: false, count: 0, threshold: Infinity };
278
+ }
279
+ getSuggestion(toolName, _args) {
280
+ switch (toolName) {
281
+ case 'str_replace_editor':
282
+ return 'The edit may be failing repeatedly. Check if the old_str matches exactly (including whitespace).';
283
+ case 'bash':
284
+ case 'execute_bash':
285
+ return 'The command may be failing. Check the error output and try a different approach.';
286
+ case 'view_file':
287
+ case 'read_file':
288
+ return 'Consider if you need to read this file again, or if the information is already available.';
289
+ case 'search':
290
+ case 'search_files':
291
+ return 'Try a different search query or search in a different location.';
292
+ default:
293
+ return 'Try a different approach to accomplish your goal.';
294
+ }
295
+ }
296
+ hashString(str) {
297
+ // Simple hash for signature creation
298
+ let hash = 0;
299
+ for (let i = 0; i < str.length; i++) {
300
+ const char = str.charCodeAt(i);
301
+ hash = ((hash << 5) - hash) + char;
302
+ hash = hash & hash; // Convert to 32bit integer
303
+ }
304
+ return hash.toString(16);
305
+ }
306
+ cleanup() {
307
+ // Remove old history entries
308
+ if (this.callHistory.length > this.maxHistorySize) {
309
+ const removeCount = this.callHistory.length - this.maxHistorySize + 20;
310
+ this.callHistory.splice(0, removeCount);
311
+ }
312
+ // Clean up signature counts for signatures not in recent history
313
+ if (this.signatureCounts.size > this.maxHistorySize * 2) {
314
+ const recentSignatures = new Set(this.callHistory.slice(-this.maxHistorySize).map(r => r.signature));
315
+ for (const sig of this.signatureCounts.keys()) {
316
+ if (!recentSignatures.has(sig)) {
317
+ this.signatureCounts.delete(sig);
318
+ this.failureCounts.delete(sig);
319
+ }
320
+ }
321
+ }
322
+ }
323
+ }
324
+ /**
325
+ * Singleton instance
326
+ */
327
+ let loopDetectorInstance = null;
328
+ export function getLoopDetector() {
329
+ if (!loopDetectorInstance) {
330
+ loopDetectorInstance = new LoopDetector();
331
+ }
332
+ return loopDetectorInstance;
333
+ }
334
+ export function resetLoopDetector() {
335
+ if (loopDetectorInstance) {
336
+ loopDetectorInstance.reset();
337
+ }
338
+ }
339
+ //# sourceMappingURL=loop-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-detector.js","sourceRoot":"","sources":["../../src/agent/loop-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Progress-Based Detection System (Phase 2)
3
+ *
4
+ * Tracks state changes to detect actual progress vs. loops.
5
+ * Key insight: The problem isn't repeated tool calls, it's repeated tool calls
6
+ * that don't make progress.
7
+ *
8
+ * Progress Indicators:
9
+ * - File operations: Content changed (hash comparison)
10
+ * - Bash commands: Exit code 0 vs non-zero
11
+ * - Edits: File actually modified
12
+ */
13
+ /**
14
+ * File state snapshot for comparison
15
+ */
16
+ interface FileState {
17
+ path: string;
18
+ hash: string;
19
+ size: number;
20
+ mtime: number;
21
+ exists: boolean;
22
+ }
23
+ /**
24
+ * Progress result for a tool execution
25
+ */
26
+ export interface ProgressResult {
27
+ madeProgress: boolean;
28
+ reason: string;
29
+ stateChange?: {
30
+ before: FileState | null;
31
+ after: FileState | null;
32
+ };
33
+ }
34
+ /**
35
+ * Bash execution result for progress tracking
36
+ */
37
+ export interface BashProgressResult {
38
+ madeProgress: boolean;
39
+ reason: string;
40
+ exitCode: number;
41
+ outputChanged: boolean;
42
+ }
43
+ /**
44
+ * Progress tracking for all tool operations
45
+ */
46
+ export declare class ProgressTracker {
47
+ /** Cache of file states (path -> state) */
48
+ private fileStateCache;
49
+ /** Cache of bash output hashes (command -> hash) */
50
+ private bashOutputCache;
51
+ /** Recent file modifications for pattern detection */
52
+ private recentFileOps;
53
+ /** Maximum recent operations to track */
54
+ private maxRecentOps;
55
+ /**
56
+ * Capture file state before an operation
57
+ */
58
+ captureFileState(path: string): Promise<FileState | null>;
59
+ /**
60
+ * Check if a file operation made progress
61
+ * Call this AFTER the operation completes
62
+ */
63
+ checkFileProgress(path: string, operation: 'create' | 'edit' | 'view', success: boolean): Promise<ProgressResult>;
64
+ /**
65
+ * Check if a bash command made progress
66
+ */
67
+ checkBashProgress(command: string, exitCode: number, output: string): BashProgressResult;
68
+ /**
69
+ * Detect if we're stuck in a file operation loop
70
+ * Returns true if the same file is being operated on repeatedly without progress
71
+ */
72
+ detectFileOpLoop(path: string): {
73
+ isLoop: boolean;
74
+ reason?: string;
75
+ suggestion?: string;
76
+ };
77
+ /**
78
+ * Get progress statistics
79
+ */
80
+ getStats(): {
81
+ trackedFiles: number;
82
+ trackedCommands: number;
83
+ recentOperations: number;
84
+ };
85
+ /**
86
+ * Reset all tracking
87
+ */
88
+ reset(): void;
89
+ private hashContent;
90
+ private recordFileOp;
91
+ }
92
+ export declare function getProgressTracker(): ProgressTracker;
93
+ export declare function resetProgressTracker(): void;
94
+ export {};