@rama_nigg/open-cursor 2.3.5 → 2.3.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 +3 -0
- package/dist/index.js +33 -10
- package/dist/plugin-entry.js +33 -10
- package/package.json +1 -1
- package/src/provider/tool-loop-guard.ts +51 -5
package/README.md
CHANGED
|
@@ -27,6 +27,9 @@ Add to `~/.config/opencode/opencode.json`:
|
|
|
27
27
|
"cursor-acp": {
|
|
28
28
|
"name": "Cursor ACP",
|
|
29
29
|
"npm": "@ai-sdk/openai-compatible",
|
|
30
|
+
"options": {
|
|
31
|
+
"baseURL": "http://127.0.0.1:32124/v1"
|
|
32
|
+
},
|
|
30
33
|
"models": {
|
|
31
34
|
"cursor-acp/auto": { "name": "Auto" },
|
|
32
35
|
"cursor-acp/composer-1.5": { "name": "Composer 1.5" },
|
package/dist/index.js
CHANGED
|
@@ -17431,30 +17431,32 @@ function createToolLoopGuard(messages, maxRepeat) {
|
|
|
17431
17431
|
const successFingerprint = `${toolCall.function.name}|values:${valueSignature}|success`;
|
|
17432
17432
|
const repeatCount = (counts.get(successFingerprint) ?? 0) + 1;
|
|
17433
17433
|
counts.set(successFingerprint, repeatCount);
|
|
17434
|
+
const isExplorationTool = EXPLORATION_TOOLS.has(toolCall.function.name.toLowerCase());
|
|
17435
|
+
const effectiveMaxRepeat = isExplorationTool ? maxRepeat * EXPLORATION_LIMIT_MULTIPLIER : maxRepeat;
|
|
17434
17436
|
const coarseSuccessFingerprint = deriveSuccessCoarseFingerprint(toolCall.function.name, toolCall.function.arguments);
|
|
17435
17437
|
const coarseRepeatCount = coarseSuccessFingerprint ? (coarseCounts.get(coarseSuccessFingerprint) ?? 0) + 1 : 0;
|
|
17436
17438
|
if (coarseSuccessFingerprint) {
|
|
17437
17439
|
coarseCounts.set(coarseSuccessFingerprint, coarseRepeatCount);
|
|
17438
17440
|
}
|
|
17439
|
-
const coarseTriggered = coarseSuccessFingerprint ? coarseRepeatCount >
|
|
17441
|
+
const coarseTriggered = coarseSuccessFingerprint ? coarseRepeatCount > effectiveMaxRepeat : false;
|
|
17440
17442
|
return {
|
|
17441
17443
|
fingerprint: coarseTriggered ? coarseSuccessFingerprint : successFingerprint,
|
|
17442
17444
|
repeatCount: coarseTriggered ? coarseRepeatCount : repeatCount,
|
|
17443
|
-
maxRepeat,
|
|
17445
|
+
maxRepeat: effectiveMaxRepeat,
|
|
17444
17446
|
errorClass,
|
|
17445
|
-
triggered: repeatCount >
|
|
17447
|
+
triggered: repeatCount > effectiveMaxRepeat || coarseTriggered,
|
|
17446
17448
|
tracked: true
|
|
17447
17449
|
};
|
|
17448
17450
|
}
|
|
17449
17451
|
const strictFingerprint = `${toolCall.function.name}|${argShape}|${errorClass}`;
|
|
17450
17452
|
const coarseFingerprint = `${toolCall.function.name}|${errorClass}`;
|
|
17451
|
-
return evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerprint, counts, coarseCounts, maxRepeat, coarseMaxRepeat);
|
|
17453
|
+
return evaluateWithFingerprints(toolCall.function.name, errorClass, strictFingerprint, coarseFingerprint, counts, coarseCounts, maxRepeat, coarseMaxRepeat);
|
|
17452
17454
|
},
|
|
17453
17455
|
evaluateValidation(toolCall, validationSignature) {
|
|
17454
17456
|
const normalizedSignature = normalizeValidationSignature(validationSignature);
|
|
17455
17457
|
const strictFingerprint = `${toolCall.function.name}|schema:${normalizedSignature}|validation`;
|
|
17456
17458
|
const coarseFingerprint = `${toolCall.function.name}|validation`;
|
|
17457
|
-
return evaluateWithFingerprints("validation", strictFingerprint, coarseFingerprint, validationCounts, validationCoarseCounts, maxRepeat, coarseMaxRepeat);
|
|
17459
|
+
return evaluateWithFingerprints(toolCall.function.name, "validation", strictFingerprint, coarseFingerprint, validationCounts, validationCoarseCounts, maxRepeat, coarseMaxRepeat);
|
|
17458
17460
|
},
|
|
17459
17461
|
resetFingerprint(fingerprint) {
|
|
17460
17462
|
counts.delete(fingerprint);
|
|
@@ -17685,7 +17687,7 @@ function normalizeValidationSignature(signature) {
|
|
|
17685
17687
|
const normalized = signature.trim().toLowerCase();
|
|
17686
17688
|
return normalized.length > 0 ? normalized : "invalid";
|
|
17687
17689
|
}
|
|
17688
|
-
function evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerprint, strictCounts, coarseCounts, maxRepeat, coarseMaxRepeat) {
|
|
17690
|
+
function evaluateWithFingerprints(toolName, errorClass, strictFingerprint, coarseFingerprint, strictCounts, coarseCounts, maxRepeat, coarseMaxRepeat) {
|
|
17689
17691
|
if (errorClass === "success") {
|
|
17690
17692
|
return {
|
|
17691
17693
|
fingerprint: strictFingerprint,
|
|
@@ -17698,9 +17700,20 @@ function evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerpri
|
|
|
17698
17700
|
}
|
|
17699
17701
|
const strictRepeatCount = (strictCounts.get(strictFingerprint) ?? 0) + 1;
|
|
17700
17702
|
strictCounts.set(strictFingerprint, strictRepeatCount);
|
|
17703
|
+
const strictTriggered = strictRepeatCount > maxRepeat;
|
|
17704
|
+
const isExplorationTool = EXPLORATION_TOOLS.has(toolName.toLowerCase());
|
|
17705
|
+
if (isExplorationTool) {
|
|
17706
|
+
return {
|
|
17707
|
+
fingerprint: strictFingerprint,
|
|
17708
|
+
repeatCount: strictRepeatCount,
|
|
17709
|
+
maxRepeat,
|
|
17710
|
+
errorClass,
|
|
17711
|
+
triggered: strictTriggered,
|
|
17712
|
+
tracked: true
|
|
17713
|
+
};
|
|
17714
|
+
}
|
|
17701
17715
|
const coarseRepeatCount = (coarseCounts.get(coarseFingerprint) ?? 0) + 1;
|
|
17702
17716
|
coarseCounts.set(coarseFingerprint, coarseRepeatCount);
|
|
17703
|
-
const strictTriggered = strictRepeatCount > maxRepeat;
|
|
17704
17717
|
const coarseTriggered = coarseRepeatCount > coarseMaxRepeat;
|
|
17705
17718
|
const preferCoarseFingerprint = coarseTriggered && !strictTriggered;
|
|
17706
17719
|
return {
|
|
@@ -17791,7 +17804,7 @@ function containsAny(text, patterns) {
|
|
|
17791
17804
|
function isRecord4(value) {
|
|
17792
17805
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17793
17806
|
}
|
|
17794
|
-
var UNKNOWN_AS_SUCCESS_TOOLS, COARSE_LIMIT_MULTIPLIER = 3;
|
|
17807
|
+
var UNKNOWN_AS_SUCCESS_TOOLS, EXPLORATION_TOOLS, COARSE_LIMIT_MULTIPLIER = 3, EXPLORATION_LIMIT_MULTIPLIER = 5;
|
|
17795
17808
|
var init_tool_loop_guard = __esm(() => {
|
|
17796
17809
|
UNKNOWN_AS_SUCCESS_TOOLS = new Set([
|
|
17797
17810
|
"bash",
|
|
@@ -17803,9 +17816,19 @@ var init_tool_loop_guard = __esm(() => {
|
|
|
17803
17816
|
"ls",
|
|
17804
17817
|
"glob",
|
|
17805
17818
|
"stat",
|
|
17806
|
-
"webfetch",
|
|
17807
17819
|
"mkdir",
|
|
17808
|
-
"rm"
|
|
17820
|
+
"rm",
|
|
17821
|
+
"webfetch",
|
|
17822
|
+
"semsearch",
|
|
17823
|
+
"readlints"
|
|
17824
|
+
]);
|
|
17825
|
+
EXPLORATION_TOOLS = new Set([
|
|
17826
|
+
"read",
|
|
17827
|
+
"grep",
|
|
17828
|
+
"glob",
|
|
17829
|
+
"ls",
|
|
17830
|
+
"stat",
|
|
17831
|
+
"semsearch"
|
|
17809
17832
|
]);
|
|
17810
17833
|
});
|
|
17811
17834
|
|
package/dist/plugin-entry.js
CHANGED
|
@@ -17431,30 +17431,32 @@ function createToolLoopGuard(messages, maxRepeat) {
|
|
|
17431
17431
|
const successFingerprint = `${toolCall.function.name}|values:${valueSignature}|success`;
|
|
17432
17432
|
const repeatCount = (counts.get(successFingerprint) ?? 0) + 1;
|
|
17433
17433
|
counts.set(successFingerprint, repeatCount);
|
|
17434
|
+
const isExplorationTool = EXPLORATION_TOOLS.has(toolCall.function.name.toLowerCase());
|
|
17435
|
+
const effectiveMaxRepeat = isExplorationTool ? maxRepeat * EXPLORATION_LIMIT_MULTIPLIER : maxRepeat;
|
|
17434
17436
|
const coarseSuccessFingerprint = deriveSuccessCoarseFingerprint(toolCall.function.name, toolCall.function.arguments);
|
|
17435
17437
|
const coarseRepeatCount = coarseSuccessFingerprint ? (coarseCounts.get(coarseSuccessFingerprint) ?? 0) + 1 : 0;
|
|
17436
17438
|
if (coarseSuccessFingerprint) {
|
|
17437
17439
|
coarseCounts.set(coarseSuccessFingerprint, coarseRepeatCount);
|
|
17438
17440
|
}
|
|
17439
|
-
const coarseTriggered = coarseSuccessFingerprint ? coarseRepeatCount >
|
|
17441
|
+
const coarseTriggered = coarseSuccessFingerprint ? coarseRepeatCount > effectiveMaxRepeat : false;
|
|
17440
17442
|
return {
|
|
17441
17443
|
fingerprint: coarseTriggered ? coarseSuccessFingerprint : successFingerprint,
|
|
17442
17444
|
repeatCount: coarseTriggered ? coarseRepeatCount : repeatCount,
|
|
17443
|
-
maxRepeat,
|
|
17445
|
+
maxRepeat: effectiveMaxRepeat,
|
|
17444
17446
|
errorClass,
|
|
17445
|
-
triggered: repeatCount >
|
|
17447
|
+
triggered: repeatCount > effectiveMaxRepeat || coarseTriggered,
|
|
17446
17448
|
tracked: true
|
|
17447
17449
|
};
|
|
17448
17450
|
}
|
|
17449
17451
|
const strictFingerprint = `${toolCall.function.name}|${argShape}|${errorClass}`;
|
|
17450
17452
|
const coarseFingerprint = `${toolCall.function.name}|${errorClass}`;
|
|
17451
|
-
return evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerprint, counts, coarseCounts, maxRepeat, coarseMaxRepeat);
|
|
17453
|
+
return evaluateWithFingerprints(toolCall.function.name, errorClass, strictFingerprint, coarseFingerprint, counts, coarseCounts, maxRepeat, coarseMaxRepeat);
|
|
17452
17454
|
},
|
|
17453
17455
|
evaluateValidation(toolCall, validationSignature) {
|
|
17454
17456
|
const normalizedSignature = normalizeValidationSignature(validationSignature);
|
|
17455
17457
|
const strictFingerprint = `${toolCall.function.name}|schema:${normalizedSignature}|validation`;
|
|
17456
17458
|
const coarseFingerprint = `${toolCall.function.name}|validation`;
|
|
17457
|
-
return evaluateWithFingerprints("validation", strictFingerprint, coarseFingerprint, validationCounts, validationCoarseCounts, maxRepeat, coarseMaxRepeat);
|
|
17459
|
+
return evaluateWithFingerprints(toolCall.function.name, "validation", strictFingerprint, coarseFingerprint, validationCounts, validationCoarseCounts, maxRepeat, coarseMaxRepeat);
|
|
17458
17460
|
},
|
|
17459
17461
|
resetFingerprint(fingerprint) {
|
|
17460
17462
|
counts.delete(fingerprint);
|
|
@@ -17685,7 +17687,7 @@ function normalizeValidationSignature(signature) {
|
|
|
17685
17687
|
const normalized = signature.trim().toLowerCase();
|
|
17686
17688
|
return normalized.length > 0 ? normalized : "invalid";
|
|
17687
17689
|
}
|
|
17688
|
-
function evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerprint, strictCounts, coarseCounts, maxRepeat, coarseMaxRepeat) {
|
|
17690
|
+
function evaluateWithFingerprints(toolName, errorClass, strictFingerprint, coarseFingerprint, strictCounts, coarseCounts, maxRepeat, coarseMaxRepeat) {
|
|
17689
17691
|
if (errorClass === "success") {
|
|
17690
17692
|
return {
|
|
17691
17693
|
fingerprint: strictFingerprint,
|
|
@@ -17698,9 +17700,20 @@ function evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerpri
|
|
|
17698
17700
|
}
|
|
17699
17701
|
const strictRepeatCount = (strictCounts.get(strictFingerprint) ?? 0) + 1;
|
|
17700
17702
|
strictCounts.set(strictFingerprint, strictRepeatCount);
|
|
17703
|
+
const strictTriggered = strictRepeatCount > maxRepeat;
|
|
17704
|
+
const isExplorationTool = EXPLORATION_TOOLS.has(toolName.toLowerCase());
|
|
17705
|
+
if (isExplorationTool) {
|
|
17706
|
+
return {
|
|
17707
|
+
fingerprint: strictFingerprint,
|
|
17708
|
+
repeatCount: strictRepeatCount,
|
|
17709
|
+
maxRepeat,
|
|
17710
|
+
errorClass,
|
|
17711
|
+
triggered: strictTriggered,
|
|
17712
|
+
tracked: true
|
|
17713
|
+
};
|
|
17714
|
+
}
|
|
17701
17715
|
const coarseRepeatCount = (coarseCounts.get(coarseFingerprint) ?? 0) + 1;
|
|
17702
17716
|
coarseCounts.set(coarseFingerprint, coarseRepeatCount);
|
|
17703
|
-
const strictTriggered = strictRepeatCount > maxRepeat;
|
|
17704
17717
|
const coarseTriggered = coarseRepeatCount > coarseMaxRepeat;
|
|
17705
17718
|
const preferCoarseFingerprint = coarseTriggered && !strictTriggered;
|
|
17706
17719
|
return {
|
|
@@ -17791,7 +17804,7 @@ function containsAny(text, patterns) {
|
|
|
17791
17804
|
function isRecord4(value) {
|
|
17792
17805
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17793
17806
|
}
|
|
17794
|
-
var UNKNOWN_AS_SUCCESS_TOOLS, COARSE_LIMIT_MULTIPLIER = 3;
|
|
17807
|
+
var UNKNOWN_AS_SUCCESS_TOOLS, EXPLORATION_TOOLS, COARSE_LIMIT_MULTIPLIER = 3, EXPLORATION_LIMIT_MULTIPLIER = 5;
|
|
17795
17808
|
var init_tool_loop_guard = __esm(() => {
|
|
17796
17809
|
UNKNOWN_AS_SUCCESS_TOOLS = new Set([
|
|
17797
17810
|
"bash",
|
|
@@ -17803,9 +17816,19 @@ var init_tool_loop_guard = __esm(() => {
|
|
|
17803
17816
|
"ls",
|
|
17804
17817
|
"glob",
|
|
17805
17818
|
"stat",
|
|
17806
|
-
"webfetch",
|
|
17807
17819
|
"mkdir",
|
|
17808
|
-
"rm"
|
|
17820
|
+
"rm",
|
|
17821
|
+
"webfetch",
|
|
17822
|
+
"semsearch",
|
|
17823
|
+
"readlints"
|
|
17824
|
+
]);
|
|
17825
|
+
EXPLORATION_TOOLS = new Set([
|
|
17826
|
+
"read",
|
|
17827
|
+
"grep",
|
|
17828
|
+
"glob",
|
|
17829
|
+
"ls",
|
|
17830
|
+
"stat",
|
|
17831
|
+
"semsearch"
|
|
17809
17832
|
]);
|
|
17810
17833
|
});
|
|
17811
17834
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rama_nigg/open-cursor",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.8",
|
|
4
4
|
"description": "No prompt limits. No broken streams. Full thinking + tool support. Your Cursor subscription, properly integrated.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/plugin-entry.js",
|
|
@@ -10,6 +10,7 @@ type ToolLoopErrorClass =
|
|
|
10
10
|
| "unknown";
|
|
11
11
|
|
|
12
12
|
const UNKNOWN_AS_SUCCESS_TOOLS = new Set([
|
|
13
|
+
// Core filesystem tools
|
|
13
14
|
"bash",
|
|
14
15
|
"shell",
|
|
15
16
|
"read",
|
|
@@ -19,9 +20,27 @@ const UNKNOWN_AS_SUCCESS_TOOLS = new Set([
|
|
|
19
20
|
"ls",
|
|
20
21
|
"glob",
|
|
21
22
|
"stat",
|
|
22
|
-
"webfetch",
|
|
23
23
|
"mkdir",
|
|
24
24
|
"rm",
|
|
25
|
+
// Web/network tools
|
|
26
|
+
"webfetch",
|
|
27
|
+
// cursor-agent specific tools (passthrough, but should not trigger loop guard)
|
|
28
|
+
// Discovered via tests/experiments/ harness - see docs/cursor-agent-tools.md
|
|
29
|
+
"semsearch", // semantic code search
|
|
30
|
+
"readlints", // lint/diagnostic reader
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
// Exploratory tools that commonly iterate over many files/patterns.
|
|
34
|
+
// These are exempt from COARSE fingerprint tracking (tool|errorClass) to allow
|
|
35
|
+
// legitimate multi-file exploration. Strict fingerprints (tool|args|errorClass)
|
|
36
|
+
// still apply to catch identical repeated failures.
|
|
37
|
+
const EXPLORATION_TOOLS = new Set([
|
|
38
|
+
"read",
|
|
39
|
+
"grep",
|
|
40
|
+
"glob",
|
|
41
|
+
"ls",
|
|
42
|
+
"stat",
|
|
43
|
+
"semsearch",
|
|
25
44
|
]);
|
|
26
45
|
|
|
27
46
|
export interface ToolLoopGuardDecision {
|
|
@@ -56,6 +75,7 @@ export function parseToolLoopMaxRepeat(
|
|
|
56
75
|
// to allow legitimate exploration across different files/targets while still
|
|
57
76
|
// catching spray-and-pray patterns.
|
|
58
77
|
const COARSE_LIMIT_MULTIPLIER = 3;
|
|
78
|
+
const EXPLORATION_LIMIT_MULTIPLIER = 5;
|
|
59
79
|
|
|
60
80
|
export function createToolLoopGuard(
|
|
61
81
|
messages: Array<unknown>,
|
|
@@ -94,6 +114,16 @@ export function createToolLoopGuard(
|
|
|
94
114
|
const repeatCount = (counts.get(successFingerprint) ?? 0) + 1;
|
|
95
115
|
counts.set(successFingerprint, repeatCount);
|
|
96
116
|
|
|
117
|
+
// Exploration tools (read, grep, glob, etc.) get a higher limit because
|
|
118
|
+
// re-reading the same file across turns is legitimate behavior (verifying
|
|
119
|
+
// edits, checking state, etc.). Use 5x multiplier for these tools.
|
|
120
|
+
const isExplorationTool = EXPLORATION_TOOLS.has(
|
|
121
|
+
toolCall.function.name.toLowerCase(),
|
|
122
|
+
);
|
|
123
|
+
const effectiveMaxRepeat = isExplorationTool
|
|
124
|
+
? maxRepeat * EXPLORATION_LIMIT_MULTIPLIER
|
|
125
|
+
: maxRepeat;
|
|
126
|
+
|
|
97
127
|
// Some tools (notably edit/write) can get stuck in "successful" loops where
|
|
98
128
|
// the model keeps re-issuing the same operation with slightly different
|
|
99
129
|
// content (e.g. trailing newline differences). Track a coarse signature for
|
|
@@ -110,14 +140,14 @@ export function createToolLoopGuard(
|
|
|
110
140
|
coarseCounts.set(coarseSuccessFingerprint, coarseRepeatCount);
|
|
111
141
|
}
|
|
112
142
|
const coarseTriggered = coarseSuccessFingerprint
|
|
113
|
-
? coarseRepeatCount >
|
|
143
|
+
? coarseRepeatCount > effectiveMaxRepeat
|
|
114
144
|
: false;
|
|
115
145
|
return {
|
|
116
146
|
fingerprint: coarseTriggered ? coarseSuccessFingerprint! : successFingerprint,
|
|
117
147
|
repeatCount: coarseTriggered ? coarseRepeatCount : repeatCount,
|
|
118
|
-
maxRepeat,
|
|
148
|
+
maxRepeat: effectiveMaxRepeat,
|
|
119
149
|
errorClass,
|
|
120
|
-
triggered: repeatCount >
|
|
150
|
+
triggered: repeatCount > effectiveMaxRepeat || coarseTriggered,
|
|
121
151
|
tracked: true,
|
|
122
152
|
};
|
|
123
153
|
}
|
|
@@ -125,6 +155,7 @@ export function createToolLoopGuard(
|
|
|
125
155
|
const coarseFingerprint = `${toolCall.function.name}|${errorClass}`;
|
|
126
156
|
|
|
127
157
|
return evaluateWithFingerprints(
|
|
158
|
+
toolCall.function.name,
|
|
128
159
|
errorClass,
|
|
129
160
|
strictFingerprint,
|
|
130
161
|
coarseFingerprint,
|
|
@@ -140,6 +171,7 @@ export function createToolLoopGuard(
|
|
|
140
171
|
const strictFingerprint = `${toolCall.function.name}|schema:${normalizedSignature}|validation`;
|
|
141
172
|
const coarseFingerprint = `${toolCall.function.name}|validation`;
|
|
142
173
|
return evaluateWithFingerprints(
|
|
174
|
+
toolCall.function.name,
|
|
143
175
|
"validation",
|
|
144
176
|
strictFingerprint,
|
|
145
177
|
coarseFingerprint,
|
|
@@ -456,6 +488,7 @@ function normalizeValidationSignature(signature: string): string {
|
|
|
456
488
|
}
|
|
457
489
|
|
|
458
490
|
function evaluateWithFingerprints(
|
|
491
|
+
toolName: string,
|
|
459
492
|
errorClass: ToolLoopErrorClass,
|
|
460
493
|
strictFingerprint: string,
|
|
461
494
|
coarseFingerprint: string,
|
|
@@ -477,9 +510,22 @@ function evaluateWithFingerprints(
|
|
|
477
510
|
|
|
478
511
|
const strictRepeatCount = (strictCounts.get(strictFingerprint) ?? 0) + 1;
|
|
479
512
|
strictCounts.set(strictFingerprint, strictRepeatCount);
|
|
513
|
+
const strictTriggered = strictRepeatCount > maxRepeat;
|
|
514
|
+
|
|
515
|
+
const isExplorationTool = EXPLORATION_TOOLS.has(toolName.toLowerCase());
|
|
516
|
+
if (isExplorationTool) {
|
|
517
|
+
return {
|
|
518
|
+
fingerprint: strictFingerprint,
|
|
519
|
+
repeatCount: strictRepeatCount,
|
|
520
|
+
maxRepeat,
|
|
521
|
+
errorClass,
|
|
522
|
+
triggered: strictTriggered,
|
|
523
|
+
tracked: true,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
|
|
480
527
|
const coarseRepeatCount = (coarseCounts.get(coarseFingerprint) ?? 0) + 1;
|
|
481
528
|
coarseCounts.set(coarseFingerprint, coarseRepeatCount);
|
|
482
|
-
const strictTriggered = strictRepeatCount > maxRepeat;
|
|
483
529
|
const coarseTriggered = coarseRepeatCount > coarseMaxRepeat;
|
|
484
530
|
const preferCoarseFingerprint = coarseTriggered && !strictTriggered;
|
|
485
531
|
return {
|