@bryan-thompson/inspector-assessment-client 1.25.4 → 1.25.5
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/dist/assets/{OAuthCallback-DE62cdTZ.js → OAuthCallback-Dl4GYls3.js} +1 -1
- package/dist/assets/{OAuthDebugCallback-CWjFdCIE.js → OAuthDebugCallback-BdJ38Z-r.js} +1 -1
- package/dist/assets/{index-Df9Sx1jt.css → index-cHhcEXbr.css} +4 -0
- package/dist/assets/{index-PCQVSwHa.js → index-pfUiTdQb.js} +4 -4
- package/dist/index.html +2 -2
- package/lib/lib/assessment/coreTypes.d.ts +65 -0
- package/lib/lib/assessment/coreTypes.d.ts.map +1 -1
- package/lib/lib/assessment/extendedTypes.d.ts +127 -0
- package/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
- package/lib/lib/assessment/resultTypes.d.ts +45 -0
- package/lib/lib/assessment/resultTypes.d.ts.map +1 -1
- package/lib/services/assessment/AssessmentOrchestrator.d.ts +3 -7
- package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
- package/lib/services/assessment/AssessmentOrchestrator.js +13 -2
- package/lib/services/assessment/TestDataGenerator.d.ts +9 -1
- package/lib/services/assessment/TestDataGenerator.d.ts.map +1 -1
- package/lib/services/assessment/TestDataGenerator.js +32 -6
- package/lib/services/assessment/TestScenarioEngine.d.ts +9 -1
- package/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -1
- package/lib/services/assessment/TestScenarioEngine.js +17 -14
- package/lib/services/assessment/config/annotationPatterns.d.ts +3 -1
- package/lib/services/assessment/config/annotationPatterns.d.ts.map +1 -1
- package/lib/services/assessment/config/annotationPatterns.js +5 -2
- package/lib/services/assessment/config/architecturePatterns.d.ts +101 -0
- package/lib/services/assessment/config/architecturePatterns.d.ts.map +1 -0
- package/lib/services/assessment/config/architecturePatterns.js +248 -0
- package/lib/services/assessment/config/performanceConfig.d.ts +122 -0
- package/lib/services/assessment/config/performanceConfig.d.ts.map +1 -0
- package/lib/services/assessment/config/performanceConfig.js +154 -0
- package/lib/services/assessment/config/sanitizationPatterns.d.ts +63 -0
- package/lib/services/assessment/config/sanitizationPatterns.d.ts.map +1 -0
- package/lib/services/assessment/config/sanitizationPatterns.js +223 -0
- package/lib/services/assessment/lib/claudeCodeBridge.d.ts +3 -1
- package/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -1
- package/lib/services/assessment/lib/claudeCodeBridge.js +5 -3
- package/lib/services/assessment/lib/concurrencyLimit.d.ts +6 -2
- package/lib/services/assessment/lib/concurrencyLimit.d.ts.map +1 -1
- package/lib/services/assessment/lib/concurrencyLimit.js +13 -6
- package/lib/services/assessment/lib/errors.d.ts +90 -0
- package/lib/services/assessment/lib/errors.d.ts.map +1 -0
- package/lib/services/assessment/lib/errors.js +136 -0
- package/lib/services/assessment/lib/timeoutUtils.d.ts +69 -0
- package/lib/services/assessment/lib/timeoutUtils.d.ts.map +1 -0
- package/lib/services/assessment/lib/timeoutUtils.js +103 -0
- package/lib/services/assessment/modules/BaseAssessor.d.ts +43 -8
- package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/BaseAssessor.js +103 -34
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts +38 -1
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.js +185 -19
- package/lib/services/assessment/modules/DocumentationAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/DocumentationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/DocumentationAssessor.js +11 -0
- package/lib/services/assessment/modules/ErrorHandlingAssessor.js +1 -1
- package/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/FunctionalityAssessor.js +6 -3
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts +3 -0
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +14 -2
- package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ManifestValidationAssessor.js +7 -2
- package/lib/services/assessment/modules/PromptAssessor.d.ts +1 -0
- package/lib/services/assessment/modules/PromptAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/PromptAssessor.js +26 -16
- package/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ProtocolComplianceAssessor.js +6 -2
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.js +15 -0
- package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ResourceAssessor.js +8 -2
- package/lib/services/assessment/modules/SecurityAssessor.d.ts +3 -171
- package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/SecurityAssessor.js +25 -1480
- package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +27 -28
- package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ToolAnnotationAssessor.js +340 -863
- package/lib/services/assessment/modules/UsabilityAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/UsabilityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/UsabilityAssessor.js +11 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts +57 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.js +176 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts +67 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.js +239 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts +46 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.js +394 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts +64 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.js +304 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts +43 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +276 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts +122 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.js +388 -0
- package/lib/services/assessment/modules/annotations/index.d.ts +13 -0
- package/lib/services/assessment/modules/annotations/index.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/index.js +15 -0
- package/lib/services/assessment/modules/index.d.ts +10 -0
- package/lib/services/assessment/modules/index.d.ts.map +1 -1
- package/lib/services/assessment/modules/index.js +13 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts +125 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.js +345 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts +33 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +128 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts +67 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +372 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +178 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +1207 -0
- package/lib/services/assessment/modules/securityTests/index.d.ts +8 -0
- package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/index.js +7 -0
- package/lib/services/assessment/tool-classifier-patterns.d.ts +1 -0
- package/lib/services/assessment/tool-classifier-patterns.d.ts.map +1 -1
- package/lib/services/assessment/tool-classifier-patterns.js +17 -0
- package/package.json +1 -1
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavior Inference
|
|
3
|
+
* Infers expected tool behavior from name patterns and descriptions
|
|
4
|
+
*
|
|
5
|
+
* Extracted from ToolAnnotationAssessor.ts for maintainability.
|
|
6
|
+
* Handles persistence model detection and behavior classification.
|
|
7
|
+
*
|
|
8
|
+
* Enhanced in Issue #57 with multi-signal inference from descriptions and schemas.
|
|
9
|
+
*/
|
|
10
|
+
import { analyzeDescription } from "./DescriptionAnalyzer.js";
|
|
11
|
+
import { analyzeInputSchema, analyzeOutputSchema, } from "./SchemaAnalyzer.js";
|
|
12
|
+
import { getDefaultCompiledPatterns, matchToolPattern, checkDescriptionForImmediatePersistence, } from "../../config/annotationPatterns.js";
|
|
13
|
+
import { isRunKeywordExempt } from "./AnnotationDeceptionDetector.js";
|
|
14
|
+
/**
|
|
15
|
+
* Infer expected behavior from tool name and description
|
|
16
|
+
* Returns confidence level and ambiguity flag for better handling
|
|
17
|
+
*/
|
|
18
|
+
export function inferBehavior(toolName, description, compiledPatterns, persistenceContext) {
|
|
19
|
+
const patterns = compiledPatterns ?? getDefaultCompiledPatterns();
|
|
20
|
+
const lowerDesc = (description || "").toLowerCase();
|
|
21
|
+
// Issue #18: Early check for run + analysis suffix pattern
|
|
22
|
+
// Tools like "runAccessibilityAudit" are genuinely read-only (fetch analysis data)
|
|
23
|
+
// Check this BEFORE pattern matching to override the generic "run_" write pattern
|
|
24
|
+
if (isRunKeywordExempt(toolName)) {
|
|
25
|
+
return {
|
|
26
|
+
expectedReadOnly: true,
|
|
27
|
+
expectedDestructive: false,
|
|
28
|
+
reason: `Tool name contains 'run' with analysis suffix (audit, check, scan, etc.) - this is a read-only analysis operation`,
|
|
29
|
+
confidence: "medium",
|
|
30
|
+
isAmbiguous: false,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Use the configurable pattern matching system
|
|
34
|
+
const patternMatch = matchToolPattern(toolName, patterns);
|
|
35
|
+
// Handle pattern match results
|
|
36
|
+
switch (patternMatch.category) {
|
|
37
|
+
case "ambiguous":
|
|
38
|
+
// Ambiguous patterns - don't make strong assertions
|
|
39
|
+
return {
|
|
40
|
+
expectedReadOnly: false,
|
|
41
|
+
expectedDestructive: false,
|
|
42
|
+
reason: `Tool name matches ambiguous pattern '${patternMatch.pattern}' - behavior varies by implementation context`,
|
|
43
|
+
confidence: "low",
|
|
44
|
+
isAmbiguous: true,
|
|
45
|
+
};
|
|
46
|
+
case "destructive":
|
|
47
|
+
return {
|
|
48
|
+
expectedReadOnly: false,
|
|
49
|
+
expectedDestructive: true,
|
|
50
|
+
reason: `Tool name matches destructive pattern: ${patternMatch.pattern}`,
|
|
51
|
+
confidence: "high",
|
|
52
|
+
isAmbiguous: false,
|
|
53
|
+
};
|
|
54
|
+
case "readOnly":
|
|
55
|
+
return {
|
|
56
|
+
expectedReadOnly: true,
|
|
57
|
+
expectedDestructive: false,
|
|
58
|
+
reason: `Tool name matches read-only pattern: ${patternMatch.pattern}`,
|
|
59
|
+
confidence: "high",
|
|
60
|
+
isAmbiguous: false,
|
|
61
|
+
};
|
|
62
|
+
case "write": {
|
|
63
|
+
// CREATE operations are NEVER destructive - they only ADD new data
|
|
64
|
+
// Only UPDATE/MODIFY operations can be considered destructive when they modify existing data
|
|
65
|
+
const isCreateOperation = /^(create|add|insert|new|generate)[_-]/i.test(toolName);
|
|
66
|
+
if (isCreateOperation) {
|
|
67
|
+
return {
|
|
68
|
+
expectedReadOnly: false,
|
|
69
|
+
expectedDestructive: false,
|
|
70
|
+
reason: `Tool name matches create pattern: ${patternMatch.pattern} - create operations only add data and are not destructive`,
|
|
71
|
+
confidence: "high",
|
|
72
|
+
isAmbiguous: false,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Three-Tier Classification: Check persistence model for UPDATE/MODIFY operations
|
|
76
|
+
// If immediate persistence detected, update operations should be marked destructive
|
|
77
|
+
const descriptionCheck = checkDescriptionForImmediatePersistence(description || "");
|
|
78
|
+
// Priority 1: Description explicitly indicates deferred persistence
|
|
79
|
+
if (descriptionCheck.indicatesDeferred) {
|
|
80
|
+
return {
|
|
81
|
+
expectedReadOnly: false,
|
|
82
|
+
expectedDestructive: false,
|
|
83
|
+
reason: `Tool name matches write pattern (${patternMatch.pattern}), description indicates deferred/in-memory operation`,
|
|
84
|
+
confidence: "medium",
|
|
85
|
+
isAmbiguous: false,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Priority 2: Description explicitly indicates immediate persistence
|
|
89
|
+
if (descriptionCheck.indicatesImmediate) {
|
|
90
|
+
return {
|
|
91
|
+
expectedReadOnly: false,
|
|
92
|
+
expectedDestructive: true,
|
|
93
|
+
reason: `Tool name matches write pattern (${patternMatch.pattern}), description indicates immediate persistence to storage (${descriptionCheck.matchedPatterns.slice(0, 2).join(", ")})`,
|
|
94
|
+
confidence: "medium",
|
|
95
|
+
isAmbiguous: false,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Priority 3: Server-level persistence model (no save operations = immediate)
|
|
99
|
+
if (persistenceContext?.model === "immediate") {
|
|
100
|
+
return {
|
|
101
|
+
expectedReadOnly: false,
|
|
102
|
+
expectedDestructive: true,
|
|
103
|
+
reason: `Tool name matches write pattern (${patternMatch.pattern}), server has no save operations → write operations likely persist immediately`,
|
|
104
|
+
confidence: "medium",
|
|
105
|
+
isAmbiguous: false,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// Priority 4: Server has save operations = deferred (in-memory until save)
|
|
109
|
+
if (persistenceContext?.model === "deferred") {
|
|
110
|
+
return {
|
|
111
|
+
expectedReadOnly: false,
|
|
112
|
+
expectedDestructive: false,
|
|
113
|
+
reason: `Tool name matches write pattern (${patternMatch.pattern}), server has save operations → write operations likely in-memory until explicit save`,
|
|
114
|
+
confidence: "medium",
|
|
115
|
+
isAmbiguous: false,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// Default: Unknown persistence model - conservative approach (not destructive)
|
|
119
|
+
return {
|
|
120
|
+
expectedReadOnly: false,
|
|
121
|
+
expectedDestructive: false,
|
|
122
|
+
reason: `Tool name matches write pattern: ${patternMatch.pattern}`,
|
|
123
|
+
confidence: "medium",
|
|
124
|
+
isAmbiguous: false,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
case "unknown":
|
|
128
|
+
default:
|
|
129
|
+
// Fall through to description-based analysis
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
// Check description for hints (medium confidence)
|
|
133
|
+
if (lowerDesc.includes("delete") || lowerDesc.includes("remove")) {
|
|
134
|
+
return {
|
|
135
|
+
expectedReadOnly: false,
|
|
136
|
+
expectedDestructive: true,
|
|
137
|
+
reason: "Description mentions delete/remove operations",
|
|
138
|
+
confidence: "medium",
|
|
139
|
+
isAmbiguous: false,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// Check for read-only indicators, but write operations take precedence
|
|
143
|
+
const hasReadIndicators = lowerDesc.includes("read") ||
|
|
144
|
+
lowerDesc.includes("get") ||
|
|
145
|
+
lowerDesc.includes("fetch");
|
|
146
|
+
const hasWriteIndicators = lowerDesc.includes("update") ||
|
|
147
|
+
lowerDesc.includes("create") ||
|
|
148
|
+
lowerDesc.includes("increment") ||
|
|
149
|
+
lowerDesc.includes("modify") ||
|
|
150
|
+
lowerDesc.includes("set") ||
|
|
151
|
+
lowerDesc.includes("change");
|
|
152
|
+
if (hasReadIndicators && !hasWriteIndicators) {
|
|
153
|
+
return {
|
|
154
|
+
expectedReadOnly: true,
|
|
155
|
+
expectedDestructive: false,
|
|
156
|
+
reason: "Description suggests read-only operation",
|
|
157
|
+
confidence: "medium",
|
|
158
|
+
isAmbiguous: false,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
// Default: assume write with low confidence (ambiguous)
|
|
162
|
+
return {
|
|
163
|
+
expectedReadOnly: false,
|
|
164
|
+
expectedDestructive: false,
|
|
165
|
+
reason: "Could not infer behavior from name pattern",
|
|
166
|
+
confidence: "low",
|
|
167
|
+
isAmbiguous: true,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Enhanced behavior inference using multiple signals.
|
|
172
|
+
*
|
|
173
|
+
* Analyzes tool name patterns, descriptions, and schemas to provide
|
|
174
|
+
* a more accurate behavior inference with aggregated confidence.
|
|
175
|
+
*
|
|
176
|
+
* Part of Issue #57: Architecture detection and behavior inference modules
|
|
177
|
+
*
|
|
178
|
+
* @param toolName - Name of the tool
|
|
179
|
+
* @param description - Tool description (optional)
|
|
180
|
+
* @param inputSchema - Input parameter schema (optional)
|
|
181
|
+
* @param outputSchema - Output/return schema (optional)
|
|
182
|
+
* @param compiledPatterns - Compiled regex patterns for name matching
|
|
183
|
+
* @param persistenceContext - Server-level persistence context
|
|
184
|
+
* @returns EnhancedBehaviorInferenceResult with multi-signal analysis
|
|
185
|
+
*/
|
|
186
|
+
export function inferBehaviorEnhanced(toolName, description, inputSchema, outputSchema, compiledPatterns, persistenceContext) {
|
|
187
|
+
// Get the basic name-pattern inference
|
|
188
|
+
const baseResult = inferBehavior(toolName, description, compiledPatterns, persistenceContext);
|
|
189
|
+
// Initialize signals collection
|
|
190
|
+
const signals = {};
|
|
191
|
+
// Convert base result to name pattern signal
|
|
192
|
+
signals.namePatternSignal = {
|
|
193
|
+
expectedReadOnly: baseResult.expectedReadOnly,
|
|
194
|
+
expectedDestructive: baseResult.expectedDestructive,
|
|
195
|
+
confidence: confidenceToNumber(baseResult.confidence),
|
|
196
|
+
evidence: [baseResult.reason],
|
|
197
|
+
};
|
|
198
|
+
// Analyze description if provided
|
|
199
|
+
if (description && description.trim().length > 0) {
|
|
200
|
+
signals.descriptionSignal = analyzeDescription(description);
|
|
201
|
+
}
|
|
202
|
+
// Analyze input schema if provided
|
|
203
|
+
if (inputSchema) {
|
|
204
|
+
signals.inputSchemaSignal = analyzeInputSchema(inputSchema);
|
|
205
|
+
}
|
|
206
|
+
// Analyze output schema if provided
|
|
207
|
+
if (outputSchema) {
|
|
208
|
+
signals.outputSchemaSignal = analyzeOutputSchema(outputSchema);
|
|
209
|
+
}
|
|
210
|
+
// Aggregate signals to determine final result
|
|
211
|
+
const aggregated = aggregateSignals(signals);
|
|
212
|
+
// Preserve persistence model info from base result if present
|
|
213
|
+
let finalReason = aggregated.reason;
|
|
214
|
+
if (baseResult.reason.includes("deferred") ||
|
|
215
|
+
baseResult.reason.includes("immediate persistence")) {
|
|
216
|
+
// Append persistence context to aggregated reason
|
|
217
|
+
const persistenceInfo = baseResult.reason.includes("deferred")
|
|
218
|
+
? " (deferred persistence model)"
|
|
219
|
+
: " (immediate persistence model)";
|
|
220
|
+
finalReason = aggregated.reason + persistenceInfo;
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
expectedReadOnly: aggregated.expectedReadOnly,
|
|
224
|
+
expectedDestructive: aggregated.expectedDestructive,
|
|
225
|
+
reason: finalReason,
|
|
226
|
+
confidence: numberToConfidence(aggregated.confidence),
|
|
227
|
+
isAmbiguous: aggregated.isAmbiguous,
|
|
228
|
+
signals,
|
|
229
|
+
aggregatedConfidence: aggregated.confidence,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Convert string confidence to numeric value (0-100).
|
|
234
|
+
*/
|
|
235
|
+
function confidenceToNumber(confidence) {
|
|
236
|
+
switch (confidence) {
|
|
237
|
+
case "high":
|
|
238
|
+
return 90;
|
|
239
|
+
case "medium":
|
|
240
|
+
return 70;
|
|
241
|
+
case "low":
|
|
242
|
+
return 40;
|
|
243
|
+
default:
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Convert numeric confidence (0-100) to string confidence level.
|
|
249
|
+
*/
|
|
250
|
+
function numberToConfidence(confidence) {
|
|
251
|
+
if (confidence >= 80)
|
|
252
|
+
return "high";
|
|
253
|
+
if (confidence >= 50)
|
|
254
|
+
return "medium";
|
|
255
|
+
return "low";
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Aggregate multiple signals into a final inference result.
|
|
259
|
+
*
|
|
260
|
+
* Signal aggregation rules:
|
|
261
|
+
* 1. Destructive signals take priority if confidence >= 70
|
|
262
|
+
* 2. Read-only signals are aggregated when no destructive signals
|
|
263
|
+
* 3. Conflicting signals decrease overall confidence
|
|
264
|
+
* 4. Multiple agreeing signals increase confidence
|
|
265
|
+
*/
|
|
266
|
+
function aggregateSignals(signals) {
|
|
267
|
+
const activeSignals = Object.entries(signals).filter(([_, signal]) => signal && signal.confidence > 0);
|
|
268
|
+
if (activeSignals.length === 0) {
|
|
269
|
+
return {
|
|
270
|
+
expectedReadOnly: false,
|
|
271
|
+
expectedDestructive: false,
|
|
272
|
+
reason: "No signals detected",
|
|
273
|
+
confidence: 0,
|
|
274
|
+
isAmbiguous: true,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
// If only one weak signal exists, treat as ambiguous
|
|
278
|
+
if (activeSignals.length === 1 && activeSignals[0][1].confidence < 50) {
|
|
279
|
+
return {
|
|
280
|
+
expectedReadOnly: false,
|
|
281
|
+
expectedDestructive: false,
|
|
282
|
+
reason: "Only weak signal detected - behavior is ambiguous",
|
|
283
|
+
confidence: activeSignals[0][1].confidence,
|
|
284
|
+
isAmbiguous: true,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
// Count signals by behavior type
|
|
288
|
+
let readOnlySignals = [];
|
|
289
|
+
let destructiveSignals = [];
|
|
290
|
+
let writeSignals = [];
|
|
291
|
+
for (const [name, signal] of activeSignals) {
|
|
292
|
+
if (signal.expectedDestructive) {
|
|
293
|
+
destructiveSignals.push({ name, signal });
|
|
294
|
+
}
|
|
295
|
+
else if (signal.expectedReadOnly) {
|
|
296
|
+
readOnlySignals.push({ name, signal });
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
writeSignals.push({ name, signal });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
// Determine final behavior
|
|
303
|
+
let expectedReadOnly = false;
|
|
304
|
+
let expectedDestructive = false;
|
|
305
|
+
let reason;
|
|
306
|
+
let confidence;
|
|
307
|
+
let isAmbiguous = false;
|
|
308
|
+
// Priority 1: Strong destructive signals
|
|
309
|
+
const strongDestructive = destructiveSignals.filter((s) => s.signal.confidence >= 70);
|
|
310
|
+
if (strongDestructive.length > 0) {
|
|
311
|
+
expectedDestructive = true;
|
|
312
|
+
const avgConfidence = strongDestructive.reduce((sum, s) => sum + s.signal.confidence, 0) /
|
|
313
|
+
strongDestructive.length;
|
|
314
|
+
// Gentle boost for multiple signals (prevents saturation at 100)
|
|
315
|
+
const boostMultiplier = Math.max(0, strongDestructive.length - 1);
|
|
316
|
+
confidence = Math.min(100, avgConfidence + boostMultiplier * 3);
|
|
317
|
+
reason = `Destructive behavior detected from: ${strongDestructive.map((s) => formatSignalName(s.name)).join(", ")}`;
|
|
318
|
+
// Check for conflicts
|
|
319
|
+
if (readOnlySignals.length > 0) {
|
|
320
|
+
confidence -= 10;
|
|
321
|
+
reason += ` (conflicts with read-only signals)`;
|
|
322
|
+
isAmbiguous = true;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// Priority 2: Read-only vs Write signals
|
|
326
|
+
// If there are strong write signals, they should take precedence
|
|
327
|
+
else if (readOnlySignals.length > 0) {
|
|
328
|
+
const strongWriteSignals = writeSignals.filter((s) => s.signal.confidence >= 70);
|
|
329
|
+
// Write signals of high confidence override read-only (multi-operation tools)
|
|
330
|
+
if (strongWriteSignals.length > 0) {
|
|
331
|
+
const writeAvg = strongWriteSignals.reduce((sum, s) => sum + s.signal.confidence, 0) /
|
|
332
|
+
strongWriteSignals.length;
|
|
333
|
+
const readAvg = readOnlySignals.reduce((sum, s) => sum + s.signal.confidence, 0) /
|
|
334
|
+
readOnlySignals.length;
|
|
335
|
+
// When both read-only and write signals present, it's always a conflict
|
|
336
|
+
// Mark as ambiguous and let the dominant signal determine behavior
|
|
337
|
+
isAmbiguous = true;
|
|
338
|
+
if (writeAvg >= readAvg * 0.9) {
|
|
339
|
+
// Write is dominant - but still a conflict
|
|
340
|
+
expectedReadOnly = false;
|
|
341
|
+
confidence = Math.max(0, Math.round(writeAvg - 10)); // Reduce due to conflict, prevent underflow
|
|
342
|
+
reason = `Write behavior detected from: ${strongWriteSignals.map((s) => formatSignalName(s.name)).join(", ")} (conflicts with read-only signals)`;
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
// Read-only is dominant - still a conflict
|
|
346
|
+
expectedReadOnly = true;
|
|
347
|
+
confidence = Math.max(0, Math.round(readAvg - 15)); // Reduce due to conflict, prevent underflow
|
|
348
|
+
reason = `Read-only behavior detected from: ${readOnlySignals.map((s) => formatSignalName(s.name)).join(", ")} (conflicts with write signals)`;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
// Pure read-only, no write conflicts
|
|
353
|
+
expectedReadOnly = true;
|
|
354
|
+
const avgConfidence = readOnlySignals.reduce((sum, s) => sum + s.signal.confidence, 0) /
|
|
355
|
+
readOnlySignals.length;
|
|
356
|
+
// Gentle boost for multiple signals (prevents saturation at 100)
|
|
357
|
+
const boostMultiplier = Math.max(0, readOnlySignals.length - 1);
|
|
358
|
+
confidence = Math.min(100, avgConfidence + boostMultiplier * 3);
|
|
359
|
+
reason = `Read-only behavior detected from: ${readOnlySignals.map((s) => formatSignalName(s.name)).join(", ")}`;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// Priority 3: Write signals (not destructive)
|
|
363
|
+
else if (writeSignals.length > 0) {
|
|
364
|
+
const avgConfidence = writeSignals.reduce((sum, s) => sum + s.signal.confidence, 0) /
|
|
365
|
+
writeSignals.length;
|
|
366
|
+
confidence = avgConfidence;
|
|
367
|
+
reason = `Write behavior detected from: ${writeSignals.map((s) => formatSignalName(s.name)).join(", ")}`;
|
|
368
|
+
}
|
|
369
|
+
// Fallback: No clear signals
|
|
370
|
+
else {
|
|
371
|
+
confidence = 30;
|
|
372
|
+
reason = "No clear behavior signals detected";
|
|
373
|
+
isAmbiguous = true;
|
|
374
|
+
}
|
|
375
|
+
// Ensure confidence is in valid range
|
|
376
|
+
confidence = Math.max(0, Math.min(100, confidence));
|
|
377
|
+
return {
|
|
378
|
+
expectedReadOnly,
|
|
379
|
+
expectedDestructive,
|
|
380
|
+
reason,
|
|
381
|
+
confidence: Math.round(confidence),
|
|
382
|
+
isAmbiguous,
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Format signal name for display.
|
|
387
|
+
*/
|
|
388
|
+
function formatSignalName(name) {
|
|
389
|
+
return name
|
|
390
|
+
.replace(/Signal$/, "")
|
|
391
|
+
.replace(/([A-Z])/g, " $1")
|
|
392
|
+
.trim()
|
|
393
|
+
.toLowerCase();
|
|
394
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Description Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Analyzes tool descriptions for behavioral keywords to infer expected behavior.
|
|
5
|
+
* This provides a more robust inference than name-pattern matching alone.
|
|
6
|
+
*
|
|
7
|
+
* Part of Issue #57: Architecture detection and behavior inference modules
|
|
8
|
+
*/
|
|
9
|
+
import type { InferenceSignal } from "../../../../lib/assessment/extendedTypes.js";
|
|
10
|
+
/**
|
|
11
|
+
* Keyword categories with confidence levels.
|
|
12
|
+
* Keywords in 'high' have strong semantic association with the behavior.
|
|
13
|
+
* Keywords in 'medium' are indicative but may have context-dependent meanings.
|
|
14
|
+
* Keywords in 'low' are weak indicators.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DESCRIPTION_BEHAVIOR_KEYWORDS: {
|
|
17
|
+
readOnly: {
|
|
18
|
+
high: string[];
|
|
19
|
+
medium: string[];
|
|
20
|
+
low: string[];
|
|
21
|
+
};
|
|
22
|
+
destructive: {
|
|
23
|
+
high: string[];
|
|
24
|
+
medium: string[];
|
|
25
|
+
low: string[];
|
|
26
|
+
};
|
|
27
|
+
write: {
|
|
28
|
+
high: string[];
|
|
29
|
+
medium: string[];
|
|
30
|
+
low: string[];
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Analyze a tool description for behavioral signals.
|
|
35
|
+
*
|
|
36
|
+
* @param description - Tool description to analyze
|
|
37
|
+
* @returns InferenceSignal with read-only/destructive expectations
|
|
38
|
+
*/
|
|
39
|
+
export declare function analyzeDescription(description: string): InferenceSignal;
|
|
40
|
+
/**
|
|
41
|
+
* Quick check if description contains read-only indicators.
|
|
42
|
+
* Useful for fast filtering before full analysis.
|
|
43
|
+
*
|
|
44
|
+
* @param description - Tool description to check
|
|
45
|
+
* @returns True if any read-only keywords are present
|
|
46
|
+
*/
|
|
47
|
+
export declare function hasReadOnlyIndicators(description: string): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Quick check if description contains destructive indicators.
|
|
50
|
+
* Useful for fast filtering before full analysis.
|
|
51
|
+
*
|
|
52
|
+
* @param description - Tool description to check
|
|
53
|
+
* @returns True if any destructive keywords are present
|
|
54
|
+
*/
|
|
55
|
+
export declare function hasDestructiveIndicators(description: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Quick check if description contains write indicators.
|
|
58
|
+
* Useful for fast filtering before full analysis.
|
|
59
|
+
*
|
|
60
|
+
* @param description - Tool description to check
|
|
61
|
+
* @returns True if any write keywords are present
|
|
62
|
+
*/
|
|
63
|
+
export declare function hasWriteIndicators(description: string): boolean;
|
|
64
|
+
//# sourceMappingURL=DescriptionAnalyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DescriptionAnalyzer.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/annotations/DescriptionAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;CAoGzC,CAAC;AAiFF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CA6GvE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAYlE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAYrE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAY/D"}
|