projscan 1.6.1 → 1.7.0
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/core/applyFix.js +57 -4
- package/dist/core/applyFix.js.map +1 -1
- package/dist/core/codeGraph.js +6 -2
- package/dist/core/codeGraph.js.map +1 -1
- package/dist/core/fileInspector.js +42 -7
- package/dist/core/fileInspector.js.map +1 -1
- package/dist/core/languages/LanguageAdapter.d.ts +1 -1
- package/dist/core/languages/cppAdapter.d.ts +2 -0
- package/dist/core/languages/cppAdapter.js +145 -0
- package/dist/core/languages/cppAdapter.js.map +1 -0
- package/dist/core/languages/cppCallSites.d.ts +13 -0
- package/dist/core/languages/cppCallSites.js +62 -0
- package/dist/core/languages/cppCallSites.js.map +1 -0
- package/dist/core/languages/cppCyclomatic.d.ts +25 -0
- package/dist/core/languages/cppCyclomatic.js +82 -0
- package/dist/core/languages/cppCyclomatic.js.map +1 -0
- package/dist/core/languages/cppExports.d.ts +13 -0
- package/dist/core/languages/cppExports.js +120 -0
- package/dist/core/languages/cppExports.js.map +1 -0
- package/dist/core/languages/cppFunctions.d.ts +30 -0
- package/dist/core/languages/cppFunctions.js +242 -0
- package/dist/core/languages/cppFunctions.js.map +1 -0
- package/dist/core/languages/cppImports.d.ts +25 -0
- package/dist/core/languages/cppImports.js +77 -0
- package/dist/core/languages/cppImports.js.map +1 -0
- package/dist/core/languages/cppManifests.d.ts +18 -0
- package/dist/core/languages/cppManifests.js +41 -0
- package/dist/core/languages/cppManifests.js.map +1 -0
- package/dist/core/languages/kotlinAdapter.d.ts +2 -0
- package/dist/core/languages/kotlinAdapter.js +141 -0
- package/dist/core/languages/kotlinAdapter.js.map +1 -0
- package/dist/core/languages/kotlinCallSites.d.ts +15 -0
- package/dist/core/languages/kotlinCallSites.js +62 -0
- package/dist/core/languages/kotlinCallSites.js.map +1 -0
- package/dist/core/languages/kotlinCyclomatic.d.ts +24 -0
- package/dist/core/languages/kotlinCyclomatic.js +54 -0
- package/dist/core/languages/kotlinCyclomatic.js.map +1 -0
- package/dist/core/languages/kotlinExports.d.ts +13 -0
- package/dist/core/languages/kotlinExports.js +103 -0
- package/dist/core/languages/kotlinExports.js.map +1 -0
- package/dist/core/languages/kotlinFunctions.d.ts +27 -0
- package/dist/core/languages/kotlinFunctions.js +147 -0
- package/dist/core/languages/kotlinFunctions.js.map +1 -0
- package/dist/core/languages/kotlinImports.d.ts +25 -0
- package/dist/core/languages/kotlinImports.js +74 -0
- package/dist/core/languages/kotlinImports.js.map +1 -0
- package/dist/core/languages/kotlinManifests.d.ts +20 -0
- package/dist/core/languages/kotlinManifests.js +46 -0
- package/dist/core/languages/kotlinManifests.js.map +1 -0
- package/dist/core/languages/registry.js +14 -1
- package/dist/core/languages/registry.js.map +1 -1
- package/dist/core/languages/treeSitterLoader.js +19 -1
- package/dist/core/languages/treeSitterLoader.js.map +1 -1
- package/dist/core/memory.d.ts +30 -0
- package/dist/core/memory.js +42 -0
- package/dist/core/memory.js.map +1 -1
- package/dist/core/prDiff.js +3 -1
- package/dist/core/prDiff.js.map +1 -1
- package/dist/core/review.js +42 -6
- package/dist/core/review.js.map +1 -1
- package/dist/core/searchIndex.js +8 -4
- package/dist/core/searchIndex.js.map +1 -1
- package/dist/core/session.d.ts +5 -0
- package/dist/core/session.js +18 -8
- package/dist/core/session.js.map +1 -1
- package/dist/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/grammars/tree-sitter-kotlin.wasm +0 -0
- package/dist/mcp/server.js +57 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/sessionTouchScanner.js +8 -2
- package/dist/mcp/sessionTouchScanner.js.map +1 -1
- package/dist/mcp/tools/costSummary.d.ts +26 -0
- package/dist/mcp/tools/costSummary.js +143 -0
- package/dist/mcp/tools/costSummary.js.map +1 -0
- package/dist/mcp/tools/fixSuggest.js +23 -2
- package/dist/mcp/tools/fixSuggest.js.map +1 -1
- package/dist/mcp/tools/memory.js +37 -4
- package/dist/mcp/tools/memory.js.map +1 -1
- package/dist/mcp/tools.js +2 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/tool-manifest.json +18 -4
- package/dist/utils/concurrency.d.ts +23 -0
- package/dist/utils/concurrency.js +37 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/package.json +5 -2
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { loadSession } from '../../core/session.js';
|
|
2
|
+
/**
|
|
3
|
+
* 1.7+ — `projscan_cost_summary`. Aggregate token-cost analytics
|
|
4
|
+
* derived from the session event log. Builds on the `_cost` sidecar
|
|
5
|
+
* (1.5+) and per-event recording (1.7+) to give the agent a single
|
|
6
|
+
* dashboard view of where its context budget is going.
|
|
7
|
+
*
|
|
8
|
+
* Response shape:
|
|
9
|
+
* sessionId : string — current session id (or null when empty)
|
|
10
|
+
* totalCalls : number — tool-call events with a recorded cost
|
|
11
|
+
* totalEstimatedTokens : number — sum of all recorded estimatedTokens
|
|
12
|
+
* averageTokens : number — mean across all recorded calls
|
|
13
|
+
* topSpenders : [{ tool, totalTokens, callCount, averageTokens }]
|
|
14
|
+
* — ranked by totalTokens desc, top 10
|
|
15
|
+
* perToolCatalog : [{ tool, observedTypicalTokens, observedP95Tokens,
|
|
16
|
+
* callCount, expectedTokens }]
|
|
17
|
+
* — for every distinct tool that fired,
|
|
18
|
+
* observed statistics + a static
|
|
19
|
+
* "expected" baseline (see
|
|
20
|
+
* STATIC_EXPECTED_TOKENS) for
|
|
21
|
+
* pre-call budgeting.
|
|
22
|
+
*
|
|
23
|
+
* Read-only. Does not record an event for itself (avoids the
|
|
24
|
+
* read-of-the-read pollution).
|
|
25
|
+
*/
|
|
26
|
+
export const costSummaryTool = {
|
|
27
|
+
name: 'projscan_cost_summary',
|
|
28
|
+
description: 'Aggregate token-cost analytics from the current session\'s tool-call history. Returns total tokens spent, top spenders, per-tool typical/p95 estimates, and a static expected-cost catalog so the agent can budget pre-call. Pairs with the `_cost` sidecar attached to every tool result. Read-only. Note: the session event log is bounded at 500 entries, so the view reflects recent activity rather than the full lifetime of the session — for long-running sessions, older calls are dropped.',
|
|
29
|
+
inputSchema: {
|
|
30
|
+
type: 'object',
|
|
31
|
+
properties: {
|
|
32
|
+
top: {
|
|
33
|
+
type: 'number',
|
|
34
|
+
description: 'Optional. Number of top spenders to return. Default: 10.',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
handler: async (args, rootPath) => {
|
|
39
|
+
const top = typeof args.top === 'number' && Number.isFinite(args.top) && args.top > 0
|
|
40
|
+
? Math.min(50, Math.floor(args.top))
|
|
41
|
+
: 10;
|
|
42
|
+
const { session } = await loadSession(rootPath);
|
|
43
|
+
const buckets = bucketize(session.events);
|
|
44
|
+
let totalCalls = 0;
|
|
45
|
+
let totalEstimatedTokens = 0;
|
|
46
|
+
for (const bucket of buckets.values()) {
|
|
47
|
+
totalCalls += bucket.callCount;
|
|
48
|
+
totalEstimatedTokens += bucket.totalTokens;
|
|
49
|
+
}
|
|
50
|
+
const ranked = [...buckets.values()].sort((a, b) => b.totalTokens - a.totalTokens);
|
|
51
|
+
const topSpenders = ranked.slice(0, top).map((b) => ({
|
|
52
|
+
tool: b.tool,
|
|
53
|
+
totalTokens: b.totalTokens,
|
|
54
|
+
callCount: b.callCount,
|
|
55
|
+
averageTokens: b.callCount > 0 ? Math.round(b.totalTokens / b.callCount) : 0,
|
|
56
|
+
}));
|
|
57
|
+
const perToolCatalog = ranked.map((b) => {
|
|
58
|
+
const sorted = [...b.tokenSamples].sort((x, y) => x - y);
|
|
59
|
+
const median = sorted.length === 0 ? 0 : sorted[Math.floor(sorted.length / 2)];
|
|
60
|
+
const p95 = sorted.length === 0
|
|
61
|
+
? 0
|
|
62
|
+
: sorted[Math.min(sorted.length - 1, Math.floor(sorted.length * 0.95))];
|
|
63
|
+
return {
|
|
64
|
+
tool: b.tool,
|
|
65
|
+
observedTypicalTokens: median,
|
|
66
|
+
observedP95Tokens: p95,
|
|
67
|
+
callCount: b.callCount,
|
|
68
|
+
expectedTokens: STATIC_EXPECTED_TOKENS[b.tool] ?? null,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
sessionId: session.id,
|
|
73
|
+
totalCalls,
|
|
74
|
+
totalEstimatedTokens,
|
|
75
|
+
averageTokens: totalCalls > 0 ? Math.round(totalEstimatedTokens / totalCalls) : 0,
|
|
76
|
+
topSpenders,
|
|
77
|
+
perToolCatalog,
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
function bucketize(events) {
|
|
82
|
+
const buckets = new Map();
|
|
83
|
+
for (const ev of events) {
|
|
84
|
+
if (!ev.kind.startsWith('tool-call:'))
|
|
85
|
+
continue;
|
|
86
|
+
const tokens = readEstimatedTokens(ev);
|
|
87
|
+
if (tokens === null)
|
|
88
|
+
continue; // Older sessions: pre-1.7 events without tokens.
|
|
89
|
+
const tool = ev.kind.slice('tool-call:'.length);
|
|
90
|
+
let bucket = buckets.get(tool);
|
|
91
|
+
if (!bucket) {
|
|
92
|
+
bucket = { tool, callCount: 0, totalTokens: 0, tokenSamples: [] };
|
|
93
|
+
buckets.set(tool, bucket);
|
|
94
|
+
}
|
|
95
|
+
bucket.callCount += 1;
|
|
96
|
+
bucket.totalTokens += tokens;
|
|
97
|
+
bucket.tokenSamples.push(tokens);
|
|
98
|
+
}
|
|
99
|
+
return buckets;
|
|
100
|
+
}
|
|
101
|
+
function readEstimatedTokens(ev) {
|
|
102
|
+
const data = ev.data;
|
|
103
|
+
if (!data)
|
|
104
|
+
return null;
|
|
105
|
+
const v = data.estimatedTokens;
|
|
106
|
+
return typeof v === 'number' && Number.isFinite(v) ? v : null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Static "expected" cost catalog — rough order-of-magnitude tokens for
|
|
110
|
+
* each tool's full (un-budgeted) response, derived from observed
|
|
111
|
+
* default-shape outputs against a mid-sized repo (~1k files). These
|
|
112
|
+
* are not promises; they're guidance for an agent picking a
|
|
113
|
+
* `max_cost_tokens` budget pre-call. Adjust occasionally as tools evolve.
|
|
114
|
+
*/
|
|
115
|
+
const STATIC_EXPECTED_TOKENS = {
|
|
116
|
+
projscan_doctor: 4500,
|
|
117
|
+
projscan_review: 6500,
|
|
118
|
+
projscan_pr_diff: 3500,
|
|
119
|
+
projscan_taint: 4000,
|
|
120
|
+
projscan_impact: 3000,
|
|
121
|
+
projscan_workspace_graph: 5500,
|
|
122
|
+
projscan_workspaces: 1200,
|
|
123
|
+
projscan_hotspots: 2200,
|
|
124
|
+
projscan_coupling: 2500,
|
|
125
|
+
projscan_coverage: 3000,
|
|
126
|
+
projscan_dependencies: 2500,
|
|
127
|
+
projscan_outdated: 1800,
|
|
128
|
+
projscan_audit: 1500,
|
|
129
|
+
projscan_upgrade: 1000,
|
|
130
|
+
projscan_search: 2500,
|
|
131
|
+
projscan_graph: 4500,
|
|
132
|
+
projscan_structure: 3000,
|
|
133
|
+
projscan_analyze: 3500,
|
|
134
|
+
projscan_explain: 1500,
|
|
135
|
+
projscan_explain_issue: 800,
|
|
136
|
+
projscan_fix_suggest: 800,
|
|
137
|
+
projscan_apply_fix: 1500,
|
|
138
|
+
projscan_file: 2000,
|
|
139
|
+
projscan_session: 500,
|
|
140
|
+
projscan_memory: 1500,
|
|
141
|
+
projscan_cost_summary: 1000,
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=costSummary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"costSummary.js","sourceRoot":"","sources":["../../../src/mcp/tools/costSummary.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { scanRepository } from '../../core/repositoryScanner.js';
|
|
2
2
|
import { collectIssues } from '../../core/issueEngine.js';
|
|
3
3
|
import { findIssue, suggestFixForIssue, syntheticIssue, } from '../../core/fixSuggest.js';
|
|
4
|
+
import { computeRuleConfidence, computeRuleConfidenceScore, loadMemory, } from '../../core/memory.js';
|
|
5
|
+
/**
|
|
6
|
+
* 1.7+ — Build a confidence sidecar from Project Memory's per-rule
|
|
7
|
+
* fix-rate. Returned alongside every fix suggestion so the agent can
|
|
8
|
+
* deprioritize rules the user has historically ignored. Best-effort —
|
|
9
|
+
* if memory is missing or unreadable, returns "medium".
|
|
10
|
+
*/
|
|
11
|
+
async function attachConfidence(rootPath, ruleId) {
|
|
12
|
+
try {
|
|
13
|
+
const memory = await loadMemory(rootPath);
|
|
14
|
+
return {
|
|
15
|
+
level: computeRuleConfidence(memory, ruleId),
|
|
16
|
+
score: computeRuleConfidenceScore(memory, ruleId),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return { level: 'medium', score: 0.5 };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
4
23
|
export const fixSuggestTool = {
|
|
5
24
|
name: 'projscan_fix_suggest',
|
|
6
25
|
description: 'Given an issue id (from projscan_doctor / projscan_analyze) OR a file + rule pair, return a structured action prompt: headline, why it matters, where to change, one-paragraph instruction the agent can execute, optional suggested test. Rule-driven; no LLM inside projscan. Use this to close the diagnose -> fix loop.',
|
|
@@ -41,12 +60,14 @@ export const fixSuggestTool = {
|
|
|
41
60
|
return { matched: false, reason: `No open issue with id "${issueId}" in current doctor run.` };
|
|
42
61
|
}
|
|
43
62
|
const fix = await suggestFixForIssue(found, rootPath);
|
|
44
|
-
|
|
63
|
+
const confidence = await attachConfidence(rootPath, found.id);
|
|
64
|
+
return { matched: true, fix, confidence };
|
|
45
65
|
}
|
|
46
66
|
if (file && rule) {
|
|
47
67
|
const synthetic = syntheticIssue(rule, file, severity);
|
|
48
68
|
const fix = await suggestFixForIssue(synthetic, rootPath);
|
|
49
|
-
|
|
69
|
+
const confidence = await attachConfidence(rootPath, synthetic.id);
|
|
70
|
+
return { matched: true, fix, synthetic: true, confidence };
|
|
50
71
|
}
|
|
51
72
|
return {
|
|
52
73
|
matched: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixSuggest.js","sourceRoot":"","sources":["../../../src/mcp/tools/fixSuggest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,cAAc,GACf,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"fixSuggest.js","sourceRoot":"","sources":["../../../src/mcp/tools/fixSuggest.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/tools/memory.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { findAcceptedHotspots, findStableRules, forgetHotspot, forgetRule, loadMemory, saveMemory, } from '../../core/memory.js';
|
|
1
|
+
import { computeRuleConfidence, computeRuleConfidenceScore, findAcceptedHotspots, findStableRules, forgetHotspot, forgetRule, loadMemory, saveMemory, } from '../../core/memory.js';
|
|
2
2
|
/**
|
|
3
3
|
* `projscan_memory` (1.5+) — surface the local Project Memory store
|
|
4
4
|
* so an agent (or the user via the CLI) can see which issues this
|
|
@@ -24,8 +24,8 @@ export const memoryTool = {
|
|
|
24
24
|
properties: {
|
|
25
25
|
action: {
|
|
26
26
|
type: 'string',
|
|
27
|
-
enum: ['current', 'stable', 'runs', 'accepted', 'forget', 'forget-hotspot'],
|
|
28
|
-
description: 'Subaction. "current" returns aggregate counts. "stable" returns long-running rules with a config-snippet suggestion. "runs" returns every tracked rule. "accepted" (1.5+) returns files Project Memory marks as accepted load-bearing debt (top-K hotspot for ≥ 5 runs over ≥ 7 days without improving). "forget" drops one rule. "forget-hotspot" drops one file from hotspot memory.',
|
|
27
|
+
enum: ['current', 'stable', 'runs', 'accepted', 'confidence', 'forget', 'forget-hotspot'],
|
|
28
|
+
description: 'Subaction. "current" returns aggregate counts. "stable" returns long-running rules with a config-snippet suggestion. "runs" returns every tracked rule. "accepted" (1.5+) returns files Project Memory marks as accepted load-bearing debt (top-K hotspot for ≥ 5 runs over ≥ 7 days without improving). "confidence" (1.7+) returns each tracked rule labelled high/medium/low based on observed fix-rate — high = user has fixed instances; low = persistently ignored. "forget" drops one rule. "forget-hotspot" drops one file from hotspot memory.',
|
|
29
29
|
},
|
|
30
30
|
rule: {
|
|
31
31
|
type: 'string',
|
|
@@ -49,6 +49,8 @@ export const memoryTool = {
|
|
|
49
49
|
return runsView(memory);
|
|
50
50
|
case 'accepted':
|
|
51
51
|
return acceptedView(memory);
|
|
52
|
+
case 'confidence':
|
|
53
|
+
return confidenceView(memory);
|
|
52
54
|
case 'forget': {
|
|
53
55
|
const rule = typeof args.rule === 'string' ? args.rule : '';
|
|
54
56
|
if (!rule)
|
|
@@ -68,7 +70,7 @@ export const memoryTool = {
|
|
|
68
70
|
return { action: 'forget-hotspot', file, dropped: existed };
|
|
69
71
|
}
|
|
70
72
|
default:
|
|
71
|
-
throw new Error(`Unknown action "${action}". Valid actions: current, stable, runs, accepted, forget, forget-hotspot.`);
|
|
73
|
+
throw new Error(`Unknown action "${action}". Valid actions: current, stable, runs, accepted, confidence, forget, forget-hotspot.`);
|
|
72
74
|
}
|
|
73
75
|
},
|
|
74
76
|
};
|
|
@@ -131,4 +133,35 @@ function runsView(memory) {
|
|
|
131
133
|
rules: all,
|
|
132
134
|
};
|
|
133
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* 1.7+ — per-rule confidence view. For each tracked rule, compute the
|
|
138
|
+
* derived `level` (high / medium / low) and a numeric `score` in [0, 1].
|
|
139
|
+
* Sorted by score descending so the agent sees the most actionable
|
|
140
|
+
* (highest-confidence) suggestions first. Includes a one-line summary
|
|
141
|
+
* counting rules per level so the agent can decide at a glance whether
|
|
142
|
+
* to call out a "noisy rules" deprioritization.
|
|
143
|
+
*/
|
|
144
|
+
function confidenceView(memory) {
|
|
145
|
+
const ranked = Object.keys(memory.rules)
|
|
146
|
+
.map((ruleId) => {
|
|
147
|
+
const obs = memory.rules[ruleId];
|
|
148
|
+
return {
|
|
149
|
+
ruleId,
|
|
150
|
+
level: computeRuleConfidence(memory, ruleId),
|
|
151
|
+
score: Number(computeRuleConfidenceScore(memory, ruleId).toFixed(3)),
|
|
152
|
+
runCount: obs.runCount,
|
|
153
|
+
fixedCount: obs.fixedCount,
|
|
154
|
+
};
|
|
155
|
+
})
|
|
156
|
+
.sort((a, b) => b.score - a.score);
|
|
157
|
+
const counts = { high: 0, medium: 0, low: 0 };
|
|
158
|
+
for (const r of ranked)
|
|
159
|
+
counts[r.level] += 1;
|
|
160
|
+
return {
|
|
161
|
+
totalRuns: memory.totalRuns,
|
|
162
|
+
rulesTracked: ranked.length,
|
|
163
|
+
counts,
|
|
164
|
+
rules: ranked,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
134
167
|
//# sourceMappingURL=memory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/mcp/tools/memory.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,UAAU,EACV,UAAU,EACV,UAAU,GAEX,MAAM,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAY;IACjC,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,4PAA4P;IAC9P,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/mcp/tools/memory.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/tools.js
CHANGED
|
@@ -33,6 +33,7 @@ import { memoryTool } from './tools/memory.js';
|
|
|
33
33
|
import { workspaceGraphTool } from './tools/workspaceGraph.js';
|
|
34
34
|
import { applyFixTool } from './tools/applyFix.js';
|
|
35
35
|
import { taintTool } from './tools/taint.js';
|
|
36
|
+
import { costSummaryTool } from './tools/costSummary.js';
|
|
36
37
|
const tools = [
|
|
37
38
|
analyzeTool,
|
|
38
39
|
doctorTool,
|
|
@@ -59,6 +60,7 @@ const tools = [
|
|
|
59
60
|
workspaceGraphTool,
|
|
60
61
|
applyFixTool,
|
|
61
62
|
taintTool,
|
|
63
|
+
costSummaryTool,
|
|
62
64
|
];
|
|
63
65
|
export function getToolDefinitions() {
|
|
64
66
|
return tools.map(({ name, description, inputSchema }) => ({ name, description, inputSchema }));
|
package/dist/mcp/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAMzD,MAAM,KAAK,GAAc;IACvB,WAAW;IACX,UAAU;IACV,YAAY;IACZ,WAAW;IACX,QAAQ;IACR,aAAa;IACb,gBAAgB;IAChB,YAAY;IACZ,SAAS;IACT,WAAW;IACX,YAAY;IACZ,SAAS;IACT,YAAY;IACZ,cAAc;IACd,UAAU;IACV,UAAU;IACV,cAAc;IACd,gBAAgB;IAChB,UAAU;IACV,UAAU;IACV,WAAW;IACX,UAAU;IACV,kBAAkB;IAClB,YAAY;IACZ,SAAS;IACT,eAAe;CAChB,CAAC;AAEF,MAAM,UAAU,kBAAkB;IAChC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;AACjG,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,OAAO,CAAC;AACrD,CAAC"}
|
package/dist/tool-manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projscan",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"mcpProtocolVersion": "2025-03-26",
|
|
5
|
-
"generatedAt": "2026-05-
|
|
6
|
-
"toolCount":
|
|
5
|
+
"generatedAt": "2026-05-07T21:35:24.182Z",
|
|
6
|
+
"toolCount": 26,
|
|
7
7
|
"tools": [
|
|
8
8
|
{
|
|
9
9
|
"name": "projscan_analyze",
|
|
@@ -544,10 +544,11 @@
|
|
|
544
544
|
"stable",
|
|
545
545
|
"runs",
|
|
546
546
|
"accepted",
|
|
547
|
+
"confidence",
|
|
547
548
|
"forget",
|
|
548
549
|
"forget-hotspot"
|
|
549
550
|
],
|
|
550
|
-
"description": "Subaction. \"current\" returns aggregate counts. \"stable\" returns long-running rules with a config-snippet suggestion. \"runs\" returns every tracked rule. \"accepted\" (1.5+) returns files Project Memory marks as accepted load-bearing debt (top-K hotspot for ≥ 5 runs over ≥ 7 days without improving). \"forget\" drops one rule. \"forget-hotspot\" drops one file from hotspot memory."
|
|
551
|
+
"description": "Subaction. \"current\" returns aggregate counts. \"stable\" returns long-running rules with a config-snippet suggestion. \"runs\" returns every tracked rule. \"accepted\" (1.5+) returns files Project Memory marks as accepted load-bearing debt (top-K hotspot for ≥ 5 runs over ≥ 7 days without improving). \"confidence\" (1.7+) returns each tracked rule labelled high/medium/low based on observed fix-rate — high = user has fixed instances; low = persistently ignored. \"forget\" drops one rule. \"forget-hotspot\" drops one file from hotspot memory."
|
|
551
552
|
},
|
|
552
553
|
"rule": {
|
|
553
554
|
"type": "string",
|
|
@@ -641,6 +642,19 @@
|
|
|
641
642
|
}
|
|
642
643
|
}
|
|
643
644
|
}
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
"name": "projscan_cost_summary",
|
|
648
|
+
"description": "Aggregate token-cost analytics from the current session's tool-call history. Returns total tokens spent, top spenders, per-tool typical/p95 estimates, and a static expected-cost catalog so the agent can budget pre-call. Pairs with the `_cost` sidecar attached to every tool result. Read-only. Note: the session event log is bounded at 500 entries, so the view reflects recent activity rather than the full lifetime of the session — for long-running sessions, older calls are dropped.",
|
|
649
|
+
"inputSchema": {
|
|
650
|
+
"type": "object",
|
|
651
|
+
"properties": {
|
|
652
|
+
"top": {
|
|
653
|
+
"type": "number",
|
|
654
|
+
"description": "Optional. Number of top spenders to return. Default: 10."
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
644
658
|
}
|
|
645
659
|
]
|
|
646
660
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded-concurrency map (1.6.2+). Like `Promise.all(items.map(fn))` but
|
|
3
|
+
* caps the number of in-flight tasks. Used for I/O-heavy hot paths where
|
|
4
|
+
* an unbounded `Promise.all` would open thousands of file descriptors at
|
|
5
|
+
* once and trip the OS open-files ulimit (macOS default is 256).
|
|
6
|
+
*
|
|
7
|
+
* Implementation: a simple chunked-batch loop. Concurrency = batch size;
|
|
8
|
+
* each batch awaits before the next starts. This is intentionally simpler
|
|
9
|
+
* than a token-pool / p-limit-style queue — for our workloads (cold scan
|
|
10
|
+
* of N files) the difference is negligible and the chunked form has zero
|
|
11
|
+
* dependencies + obvious behavior.
|
|
12
|
+
*
|
|
13
|
+
* Returns results in the same order as the input. Errors propagate from
|
|
14
|
+
* the first failing task within a batch (matches Promise.all semantics).
|
|
15
|
+
*/
|
|
16
|
+
export declare function mapWithConcurrency<T, R>(items: T[], concurrency: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Sensible default for I/O-bound tasks. Well under macOS's 256 ulimit
|
|
19
|
+
* with headroom for other open FDs (the parent process, the spawned git
|
|
20
|
+
* subprocesses in PR review, etc.). Tunable per-call when a workload
|
|
21
|
+
* has different needs.
|
|
22
|
+
*/
|
|
23
|
+
export declare const DEFAULT_FILE_IO_CONCURRENCY = 128;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded-concurrency map (1.6.2+). Like `Promise.all(items.map(fn))` but
|
|
3
|
+
* caps the number of in-flight tasks. Used for I/O-heavy hot paths where
|
|
4
|
+
* an unbounded `Promise.all` would open thousands of file descriptors at
|
|
5
|
+
* once and trip the OS open-files ulimit (macOS default is 256).
|
|
6
|
+
*
|
|
7
|
+
* Implementation: a simple chunked-batch loop. Concurrency = batch size;
|
|
8
|
+
* each batch awaits before the next starts. This is intentionally simpler
|
|
9
|
+
* than a token-pool / p-limit-style queue — for our workloads (cold scan
|
|
10
|
+
* of N files) the difference is negligible and the chunked form has zero
|
|
11
|
+
* dependencies + obvious behavior.
|
|
12
|
+
*
|
|
13
|
+
* Returns results in the same order as the input. Errors propagate from
|
|
14
|
+
* the first failing task within a batch (matches Promise.all semantics).
|
|
15
|
+
*/
|
|
16
|
+
export async function mapWithConcurrency(items, concurrency, fn) {
|
|
17
|
+
const limit = Math.max(1, concurrency);
|
|
18
|
+
if (items.length === 0)
|
|
19
|
+
return [];
|
|
20
|
+
const out = new Array(items.length);
|
|
21
|
+
for (let i = 0; i < items.length; i += limit) {
|
|
22
|
+
const batch = items.slice(i, i + limit);
|
|
23
|
+
const results = await Promise.all(batch.map((item, j) => fn(item, i + j)));
|
|
24
|
+
for (let j = 0; j < results.length; j++) {
|
|
25
|
+
out[i + j] = results[j];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sensible default for I/O-bound tasks. Well under macOS's 256 ulimit
|
|
32
|
+
* with headroom for other open FDs (the parent process, the spawned git
|
|
33
|
+
* subprocesses in PR review, etc.). Tunable per-call when a workload
|
|
34
|
+
* has different needs.
|
|
35
|
+
*/
|
|
36
|
+
export const DEFAULT_FILE_IO_CONCURRENCY = 128;
|
|
37
|
+
//# sourceMappingURL=concurrency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../../src/utils/concurrency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAU,EACV,WAAmB,EACnB,EAA0C;IAE1C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projscan",
|
|
3
3
|
"mcpName": "io.github.abhiyoheswaran1/projscan",
|
|
4
|
-
"version": "1.
|
|
5
|
-
"description": "Agent-first code intelligence. MCP server (2025-03-26) with AST parsing for JavaScript, TypeScript, Python, Go, Java, Ruby, Rust, PHP, and C
|
|
4
|
+
"version": "1.7.0",
|
|
5
|
+
"description": "Agent-first code intelligence. MCP server (2025-03-26) with AST parsing for JavaScript, TypeScript, Python, Go, Java, Ruby, Rust, PHP, C#, Kotlin, and C++; code graph, file + per-function AST cyclomatic complexity, per-function fan-in + fan-out, coupling + cycle detection, structural PR diff with HTML reporter, coverage report with HTML reporter, one-call PR review (projscan_review) with new-taint-flow detection, rule-driven fix suggestions + mechanical apply layer with rollback (projscan_apply_fix, projscan_fix_suggest, projscan_explain_issue), source-to-sink taint analysis (projscan_taint), transitive blast-radius analysis with cross-repo mode (projscan_impact for files and symbols), cross-repo workspace registration + intelligence (projscan_workspace_graph), per-function semantic search chunks (sub-file embeddings), per-rule confidence + cost-summary analytics (projscan_cost_summary), monorepo workspace awareness with cross-package import policy + per-package dependencies / outdated / audit, BM25 + optional semantic search, cursor pagination, progress notifications, context-budgeted output, and a stable-surface CI guard. CLI on the side.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
@@ -84,6 +84,9 @@
|
|
|
84
84
|
"@types/node": "^22.0.0",
|
|
85
85
|
"@xenova/transformers": "^2.17.0",
|
|
86
86
|
"eslint": "^10.0.3",
|
|
87
|
+
"tree-sitter-cli": "^0.26.8",
|
|
88
|
+
"tree-sitter-cpp": "^0.23.4",
|
|
89
|
+
"tree-sitter-kotlin": "^0.3.8",
|
|
87
90
|
"typescript": "^5.6.0",
|
|
88
91
|
"typescript-eslint": "^8.57.0",
|
|
89
92
|
"vitest": "^2.1.0"
|