@defai.digital/ax-cli 3.8.7 → 3.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -393
- package/config-defaults/settings.yaml +3 -0
- package/dist/agent/llm-agent.d.ts +11 -2
- package/dist/agent/llm-agent.js +73 -104
- package/dist/agent/llm-agent.js.map +1 -1
- package/dist/agent/loop-detector.d.ts +70 -0
- package/dist/agent/loop-detector.js +339 -0
- package/dist/agent/loop-detector.js.map +1 -0
- package/dist/agent/progress-tracker.d.ts +94 -0
- package/dist/agent/progress-tracker.js +222 -0
- package/dist/agent/progress-tracker.js.map +1 -0
- package/dist/agent/status-reporter.js +2 -2
- package/dist/agent/status-reporter.js.map +1 -1
- package/dist/agent/subagent.js +3 -3
- package/dist/agent/subagent.js.map +1 -1
- package/dist/analyzers/git/churn-calculator.js +2 -1
- package/dist/analyzers/git/churn-calculator.js.map +1 -1
- package/dist/checkpoint/storage.js +6 -4
- package/dist/checkpoint/storage.js.map +1 -1
- package/dist/commands/cache.js +8 -6
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/doctor.js +19 -27
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/mcp-migrate.js +6 -5
- package/dist/commands/mcp-migrate.js.map +1 -1
- package/dist/commands/models.js +8 -12
- package/dist/commands/models.js.map +1 -1
- package/dist/commands/plan.js +1 -10
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/setup.js +2 -1
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/status.js +4 -4
- package/dist/commands/status.js.map +1 -1
- package/dist/constants.d.ts +12 -0
- package/dist/constants.js +16 -4
- package/dist/constants.js.map +1 -1
- package/dist/hooks/hook-runner.d.ts +138 -0
- package/dist/hooks/hook-runner.js +429 -0
- package/dist/hooks/hook-runner.js.map +1 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.js +1 -19
- package/dist/index.js.map +1 -1
- package/dist/llm/tools.js +2 -39
- package/dist/llm/tools.js.map +1 -1
- package/dist/mcp/automatosx-loader.js +2 -1
- package/dist/mcp/automatosx-loader.js.map +1 -1
- package/dist/mcp/config-migrator.js +3 -2
- package/dist/mcp/config-migrator.js.map +1 -1
- package/dist/mcp/config-v2.d.ts +5 -0
- package/dist/mcp/config-v2.js +26 -0
- package/dist/mcp/config-v2.js.map +1 -1
- package/dist/mcp/error-formatter.js +4 -1
- package/dist/mcp/error-formatter.js.map +1 -1
- package/dist/mcp/reconnection.js +2 -1
- package/dist/mcp/reconnection.js.map +1 -1
- package/dist/mcp/registry.js +3 -2
- package/dist/mcp/registry.js.map +1 -1
- package/dist/mcp/resources.js +2 -1
- package/dist/mcp/resources.js.map +1 -1
- package/dist/mcp/validation.js +9 -0
- package/dist/mcp/validation.js.map +1 -1
- package/dist/memory/context-store.js +4 -6
- package/dist/memory/context-store.js.map +1 -1
- package/dist/memory/types.d.ts +2 -0
- package/dist/memory/types.js +4 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/permissions/index.d.ts +6 -0
- package/dist/permissions/index.js +7 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/permission-manager.d.ts +145 -0
- package/dist/permissions/permission-manager.js +401 -0
- package/dist/permissions/permission-manager.js.map +1 -0
- package/dist/planner/task-planner.js +2 -1
- package/dist/planner/task-planner.js.map +1 -1
- package/dist/schemas/index.d.ts +2 -2
- package/dist/schemas/settings-schemas.d.ts +0 -14
- package/dist/schemas/settings-schemas.js +0 -10
- package/dist/schemas/settings-schemas.js.map +1 -1
- package/dist/schemas/tool-schemas.d.ts +2 -2
- package/dist/schemas/yaml-schemas.d.ts +15 -0
- package/dist/schemas/yaml-schemas.js +3 -0
- package/dist/schemas/yaml-schemas.js.map +1 -1
- package/dist/tools/bash.js +6 -5
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/confirmation-tool.js +3 -2
- package/dist/tools/confirmation-tool.js.map +1 -1
- package/dist/tools/registry.d.ts +1 -1
- package/dist/tools/registry.js +2 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/todo-tool.js +3 -2
- package/dist/tools/todo-tool.js.map +1 -1
- package/dist/ui/components/tool-group-display.js +0 -6
- package/dist/ui/components/tool-group-display.js.map +1 -1
- package/dist/ui/hooks/use-input-handler.js +7 -6
- package/dist/ui/hooks/use-input-handler.js.map +1 -1
- package/dist/ui/hooks/use-input-history.js +4 -4
- package/dist/ui/hooks/use-input-history.js.map +1 -1
- package/dist/ui/utils/tool-grouper.d.ts +1 -2
- package/dist/ui/utils/tool-grouper.js +4 -15
- package/dist/ui/utils/tool-grouper.js.map +1 -1
- package/dist/utils/audit-logger.js +2 -1
- package/dist/utils/audit-logger.js.map +1 -1
- package/dist/utils/config-loader.d.ts +3 -0
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/encryption.js +2 -1
- package/dist/utils/encryption.js.map +1 -1
- package/dist/utils/file-cache.js +4 -2
- package/dist/utils/file-cache.js.map +1 -1
- package/dist/utils/onboarding-manager.js +2 -1
- package/dist/utils/onboarding-manager.js.map +1 -1
- package/dist/utils/path-helpers.js +3 -2
- package/dist/utils/path-helpers.js.map +1 -1
- package/dist/utils/path-security.js +3 -2
- package/dist/utils/path-security.js.map +1 -1
- package/dist/utils/settings-manager.d.ts +1 -21
- package/dist/utils/settings-manager.js +2 -82
- package/dist/utils/settings-manager.js.map +1 -1
- package/dist/utils/streaming-analyzer.d.ts +2 -13
- package/dist/utils/streaming-analyzer.js +3 -25
- package/dist/utils/streaming-analyzer.js.map +1 -1
- package/dist/utils/token-counter.d.ts +8 -1
- package/dist/utils/token-counter.js +14 -5
- package/dist/utils/token-counter.js.map +1 -1
- package/package.json +3 -2
- package/packages/schemas/README.md +1 -1
- package/packages/schemas/package.json +1 -1
- package/.ax-cli/CUSTOM.md +0 -97
- package/.ax-cli/auto-accept-audit.json +0 -1302
- package/.ax-cli/index.json +0 -43
- package/.ax-cli/memory.json +0 -55
- package/.ax-cli/settings.json +0 -12
- package/ax.config.json +0 -303
- package/dist/tools/web-search/cache.d.ts +0 -62
- package/dist/tools/web-search/cache.js +0 -105
- package/dist/tools/web-search/cache.js.map +0 -1
- package/dist/tools/web-search/engines/crates.d.ts +0 -19
- package/dist/tools/web-search/engines/crates.js +0 -87
- package/dist/tools/web-search/engines/crates.js.map +0 -1
- package/dist/tools/web-search/engines/npm.d.ts +0 -18
- package/dist/tools/web-search/engines/npm.js +0 -86
- package/dist/tools/web-search/engines/npm.js.map +0 -1
- package/dist/tools/web-search/engines/pypi.d.ts +0 -18
- package/dist/tools/web-search/engines/pypi.js +0 -75
- package/dist/tools/web-search/engines/pypi.js.map +0 -1
- package/dist/tools/web-search/engines/stackoverflow.d.ts +0 -30
- package/dist/tools/web-search/engines/stackoverflow.js +0 -130
- package/dist/tools/web-search/engines/stackoverflow.js.map +0 -1
- package/dist/tools/web-search/engines/wikipedia.d.ts +0 -27
- package/dist/tools/web-search/engines/wikipedia.js +0 -112
- package/dist/tools/web-search/engines/wikipedia.js.map +0 -1
- package/dist/tools/web-search/index.d.ts +0 -11
- package/dist/tools/web-search/index.js +0 -11
- package/dist/tools/web-search/index.js.map +0 -1
- package/dist/tools/web-search/router.d.ts +0 -36
- package/dist/tools/web-search/router.js +0 -270
- package/dist/tools/web-search/router.js.map +0 -1
- package/dist/tools/web-search/types.d.ts +0 -45
- package/dist/tools/web-search/types.js +0 -6
- package/dist/tools/web-search/types.js.map +0 -1
- package/dist/tools/web-search/web-search-tool.d.ts +0 -51
- package/dist/tools/web-search/web-search-tool.js +0 -262
- package/dist/tools/web-search/web-search-tool.js.map +0 -1
- package/packages/schemas/dist/index.d.ts +0 -14
- package/packages/schemas/dist/index.d.ts.map +0 -1
- package/packages/schemas/dist/index.js +0 -19
- package/packages/schemas/dist/index.js.map +0 -1
- package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
- package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/brand-types.js +0 -243
- package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
- package/packages/schemas/dist/public/core/enums.d.ts +0 -227
- package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/enums.js +0 -222
- package/packages/schemas/dist/public/core/enums.js.map +0 -1
- package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
- package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/id-types.js +0 -136
- 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 {};
|