@zokizuan/satori-mcp 3.2.0 → 3.4.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/handlers.d.ts
CHANGED
|
@@ -16,6 +16,9 @@ export declare class ToolHandlers {
|
|
|
16
16
|
constructor(context: Context, snapshotManager: SnapshotManager, syncManager: SyncManager, runtimeFingerprint: IndexFingerprint, now?: () => number, callGraphManager?: CallGraphSidecarManager);
|
|
17
17
|
private buildReindexInstruction;
|
|
18
18
|
private buildReindexHint;
|
|
19
|
+
private summarizeFingerprint;
|
|
20
|
+
private buildCompatibilityDiagnostics;
|
|
21
|
+
private buildCompatibilityStatusLines;
|
|
19
22
|
private buildRequiresReindexPayload;
|
|
20
23
|
private buildRequiresReindexSearchResponse;
|
|
21
24
|
private buildRequiresReindexCallGraphPayload;
|
|
@@ -46,6 +49,9 @@ export declare class ToolHandlers {
|
|
|
46
49
|
private getOutlineStatusForLanguage;
|
|
47
50
|
private sortFileOutlineSymbols;
|
|
48
51
|
private buildSearchPassWarning;
|
|
52
|
+
private isSearchPassFaultInjectionEnabled;
|
|
53
|
+
private getForcedFailedSearchPassId;
|
|
54
|
+
private shouldForceSearchPassFailure;
|
|
49
55
|
private mapCallGraphStatus;
|
|
50
56
|
private getContextIgnorePatterns;
|
|
51
57
|
private rebuildCallGraphForIndex;
|
|
@@ -196,7 +202,19 @@ export declare class ToolHandlers {
|
|
|
196
202
|
}[];
|
|
197
203
|
isError: boolean;
|
|
198
204
|
}>;
|
|
199
|
-
handleGetIndexingStatus(args: any): Promise<
|
|
205
|
+
handleGetIndexingStatus(args: any): Promise<{
|
|
206
|
+
content: {
|
|
207
|
+
type: string;
|
|
208
|
+
text: string;
|
|
209
|
+
}[];
|
|
210
|
+
isError: boolean;
|
|
211
|
+
} | {
|
|
212
|
+
content: {
|
|
213
|
+
type: string;
|
|
214
|
+
text: string;
|
|
215
|
+
}[];
|
|
216
|
+
isError?: undefined;
|
|
217
|
+
}>;
|
|
200
218
|
/**
|
|
201
219
|
* Handle sync request - manually trigger incremental sync for a codebase
|
|
202
220
|
*/
|
package/dist/core/handlers.js
CHANGED
|
@@ -119,6 +119,46 @@ export class ToolHandlers {
|
|
|
119
119
|
}
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
|
+
summarizeFingerprint(fingerprint) {
|
|
123
|
+
return `${fingerprint.embeddingProvider}/${fingerprint.embeddingModel}/${fingerprint.embeddingDimension}/${fingerprint.vectorStoreProvider}/${fingerprint.schemaVersion}`;
|
|
124
|
+
}
|
|
125
|
+
buildCompatibilityDiagnostics(codebasePath) {
|
|
126
|
+
const info = typeof this.snapshotManager.getCodebaseInfo === 'function'
|
|
127
|
+
? this.snapshotManager.getCodebaseInfo(codebasePath)
|
|
128
|
+
: undefined;
|
|
129
|
+
const statusAtCheck = info?.status
|
|
130
|
+
|| (typeof this.snapshotManager.getCodebaseStatus === 'function'
|
|
131
|
+
? this.snapshotManager.getCodebaseStatus(codebasePath)
|
|
132
|
+
: 'not_found');
|
|
133
|
+
const diagnostics = {
|
|
134
|
+
runtimeFingerprint: this.runtimeFingerprint,
|
|
135
|
+
statusAtCheck
|
|
136
|
+
};
|
|
137
|
+
if (info?.indexFingerprint) {
|
|
138
|
+
diagnostics.indexedFingerprint = info.indexFingerprint;
|
|
139
|
+
}
|
|
140
|
+
if (info?.fingerprintSource) {
|
|
141
|
+
diagnostics.fingerprintSource = info.fingerprintSource;
|
|
142
|
+
}
|
|
143
|
+
if (info?.reindexReason) {
|
|
144
|
+
diagnostics.reindexReason = info.reindexReason;
|
|
145
|
+
}
|
|
146
|
+
return diagnostics;
|
|
147
|
+
}
|
|
148
|
+
buildCompatibilityStatusLines(codebasePath) {
|
|
149
|
+
const diagnostics = this.buildCompatibilityDiagnostics(codebasePath);
|
|
150
|
+
let lines = `\n🧬 Runtime fingerprint: ${this.summarizeFingerprint(diagnostics.runtimeFingerprint)}`;
|
|
151
|
+
lines += diagnostics.indexedFingerprint
|
|
152
|
+
? `\n🧬 Indexed fingerprint: ${this.summarizeFingerprint(diagnostics.indexedFingerprint)}`
|
|
153
|
+
: `\n🧬 Indexed fingerprint: unavailable`;
|
|
154
|
+
if (diagnostics.fingerprintSource) {
|
|
155
|
+
lines += `\n🧬 Fingerprint source: ${diagnostics.fingerprintSource}`;
|
|
156
|
+
}
|
|
157
|
+
if (diagnostics.reindexReason) {
|
|
158
|
+
lines += `\n🧬 Reindex reason: ${diagnostics.reindexReason}`;
|
|
159
|
+
}
|
|
160
|
+
return lines;
|
|
161
|
+
}
|
|
122
162
|
buildRequiresReindexPayload(codebasePath, detail, searchContext) {
|
|
123
163
|
const detailLine = detail ? `${detail}\n\n` : '';
|
|
124
164
|
const base = searchContext ? {
|
|
@@ -140,7 +180,8 @@ export class ToolHandlers {
|
|
|
140
180
|
message: `${detailLine}The index at '${codebasePath}' is incompatible with the current runtime and must be rebuilt. Please run manage_index with {\"action\":\"reindex\",\"path\":\"${codebasePath}\"}.`,
|
|
141
181
|
hints: {
|
|
142
182
|
reindex: this.buildReindexHint(codebasePath)
|
|
143
|
-
}
|
|
183
|
+
},
|
|
184
|
+
compatibility: this.buildCompatibilityDiagnostics(codebasePath)
|
|
144
185
|
};
|
|
145
186
|
}
|
|
146
187
|
buildRequiresReindexSearchResponse(codebasePath, detail, searchContext) {
|
|
@@ -172,7 +213,8 @@ export class ToolHandlers {
|
|
|
172
213
|
message: `${detailLine}The index at '${codebasePath}' is incompatible with the current runtime and must be rebuilt. Please run manage_index with {"action":"reindex","path":"${codebasePath}"}.`,
|
|
173
214
|
hints: {
|
|
174
215
|
reindex: this.buildReindexHint(codebasePath)
|
|
175
|
-
}
|
|
216
|
+
},
|
|
217
|
+
compatibility: this.buildCompatibilityDiagnostics(codebasePath)
|
|
176
218
|
};
|
|
177
219
|
}
|
|
178
220
|
getMatchingBlockedRoot(absolutePath) {
|
|
@@ -498,6 +540,28 @@ export class ToolHandlers {
|
|
|
498
540
|
buildSearchPassWarning(passId) {
|
|
499
541
|
return `SEARCH_PASS_FAILED:${passId} - ${passId} semantic search pass failed; results may be degraded.`;
|
|
500
542
|
}
|
|
543
|
+
isSearchPassFaultInjectionEnabled() {
|
|
544
|
+
return process.env.NODE_ENV === 'test';
|
|
545
|
+
}
|
|
546
|
+
getForcedFailedSearchPassId() {
|
|
547
|
+
if (!this.isSearchPassFaultInjectionEnabled()) {
|
|
548
|
+
return undefined;
|
|
549
|
+
}
|
|
550
|
+
const raw = typeof process.env.SATORI_TEST_FAIL_SEARCH_PASS === 'string'
|
|
551
|
+
? process.env.SATORI_TEST_FAIL_SEARCH_PASS.trim().toLowerCase()
|
|
552
|
+
: '';
|
|
553
|
+
if (raw === 'primary' || raw === 'expanded' || raw === 'both') {
|
|
554
|
+
return raw;
|
|
555
|
+
}
|
|
556
|
+
return undefined;
|
|
557
|
+
}
|
|
558
|
+
shouldForceSearchPassFailure(passId) {
|
|
559
|
+
const forced = this.getForcedFailedSearchPassId();
|
|
560
|
+
if (!forced) {
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
return forced === 'both' || forced === passId;
|
|
564
|
+
}
|
|
501
565
|
mapCallGraphStatus(graph) {
|
|
502
566
|
if (graph.supported) {
|
|
503
567
|
return 'ok';
|
|
@@ -1386,7 +1450,11 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
|
|
|
1386
1450
|
{ id: 'expanded', query: expandedQuery },
|
|
1387
1451
|
];
|
|
1388
1452
|
searchDiagnostics.searchPassCount = passDescriptors.length;
|
|
1389
|
-
const passSettled = await Promise.allSettled(passDescriptors.map((pass) => {
|
|
1453
|
+
const passSettled = await Promise.allSettled(passDescriptors.map(async (pass) => {
|
|
1454
|
+
const passId = pass.id;
|
|
1455
|
+
if (this.shouldForceSearchPassFailure(passId)) {
|
|
1456
|
+
throw new Error(`FORCED_TEST_SEARCH_PASS_FAILURE:${passId}`);
|
|
1457
|
+
}
|
|
1390
1458
|
return this.context.semanticSearch(effectiveRoot, pass.query, candidateLimit, 0.3);
|
|
1391
1459
|
}));
|
|
1392
1460
|
const searchWarnings = [];
|
|
@@ -2105,7 +2173,17 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
|
|
|
2105
2173
|
// Check indexing status using new status system
|
|
2106
2174
|
const statusGate = this.enforceFingerprintGate(absolutePath);
|
|
2107
2175
|
if (statusGate.blockedResponse) {
|
|
2108
|
-
|
|
2176
|
+
const statusMessage = this.buildReindexInstruction(absolutePath, statusGate.message);
|
|
2177
|
+
const compatibilityStatus = this.buildCompatibilityStatusLines(absolutePath);
|
|
2178
|
+
const pathInfo = codebasePath !== absolutePath
|
|
2179
|
+
? `\nNote: Input path '${codebasePath}' was resolved to absolute path '${absolutePath}'`
|
|
2180
|
+
: '';
|
|
2181
|
+
return {
|
|
2182
|
+
content: [{
|
|
2183
|
+
type: "text",
|
|
2184
|
+
text: statusMessage + compatibilityStatus + pathInfo
|
|
2185
|
+
}]
|
|
2186
|
+
};
|
|
2109
2187
|
}
|
|
2110
2188
|
const status = this.snapshotManager.getCodebaseStatus(absolutePath);
|
|
2111
2189
|
const info = this.snapshotManager.getCodebaseInfo(absolutePath);
|
|
@@ -2178,10 +2256,11 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
|
|
|
2178
2256
|
const pathInfo = codebasePath !== absolutePath
|
|
2179
2257
|
? `\nNote: Input path '${codebasePath}' was resolved to absolute path '${absolutePath}'`
|
|
2180
2258
|
: '';
|
|
2259
|
+
const compatibilityStatus = this.buildCompatibilityStatusLines(absolutePath);
|
|
2181
2260
|
return {
|
|
2182
2261
|
content: [{
|
|
2183
2262
|
type: "text",
|
|
2184
|
-
text: statusMessage + pathInfo
|
|
2263
|
+
text: statusMessage + compatibilityStatus + pathInfo
|
|
2185
2264
|
}]
|
|
2186
2265
|
};
|
|
2187
2266
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FreshnessDecision } from "./sync.js";
|
|
2
2
|
import { SearchGroupBy, SearchResultMode, SearchScope } from "./search-constants.js";
|
|
3
|
+
import { FingerprintSource, IndexFingerprint } from "../config.js";
|
|
3
4
|
export type StalenessBucket = "fresh" | "aging" | "stale" | "unknown";
|
|
4
5
|
export interface SearchSpan {
|
|
5
6
|
startLine: number;
|
|
@@ -57,6 +58,13 @@ export interface SearchGroupResult {
|
|
|
57
58
|
topChunkScore: number;
|
|
58
59
|
};
|
|
59
60
|
}
|
|
61
|
+
export interface FingerprintCompatibilityDiagnostics {
|
|
62
|
+
runtimeFingerprint: IndexFingerprint;
|
|
63
|
+
indexedFingerprint?: IndexFingerprint;
|
|
64
|
+
fingerprintSource?: FingerprintSource;
|
|
65
|
+
reindexReason?: "legacy_unverified_fingerprint" | "fingerprint_mismatch" | "missing_fingerprint";
|
|
66
|
+
statusAtCheck?: "indexed" | "indexing" | "indexfailed" | "sync_completed" | "requires_reindex" | "not_found";
|
|
67
|
+
}
|
|
60
68
|
interface SearchBaseResponseEnvelope {
|
|
61
69
|
status: "ok" | "requires_reindex" | "not_indexed";
|
|
62
70
|
path: string;
|
|
@@ -70,6 +78,7 @@ interface SearchBaseResponseEnvelope {
|
|
|
70
78
|
warnings?: string[];
|
|
71
79
|
message?: string;
|
|
72
80
|
hints?: Record<string, unknown>;
|
|
81
|
+
compatibility?: FingerprintCompatibilityDiagnostics;
|
|
73
82
|
}
|
|
74
83
|
export interface SearchGroupedResponseEnvelope extends SearchBaseResponseEnvelope {
|
|
75
84
|
resultMode: "grouped";
|
package/dist/tools/call_graph.js
CHANGED
|
@@ -21,7 +21,15 @@ export const callGraphTool = {
|
|
|
21
21
|
description: () => 'Traverse the prebuilt TS/Python call graph sidecar for callers/callees/bidirectional symbol relationships.',
|
|
22
22
|
inputSchemaZod: () => callGraphInputSchema,
|
|
23
23
|
execute: async (args, ctx) => {
|
|
24
|
-
const
|
|
24
|
+
const normalizedArgs = (args && typeof args === 'object')
|
|
25
|
+
? { ...args }
|
|
26
|
+
: (args || {});
|
|
27
|
+
if (normalizedArgs
|
|
28
|
+
&& typeof normalizedArgs === 'object'
|
|
29
|
+
&& normalizedArgs.direction === 'bidirectional') {
|
|
30
|
+
normalizedArgs.direction = 'both';
|
|
31
|
+
}
|
|
32
|
+
const parsed = callGraphInputSchema.safeParse(normalizedArgs);
|
|
25
33
|
if (!parsed.success) {
|
|
26
34
|
return {
|
|
27
35
|
content: [{
|