preflight-mcp 0.1.2 → 0.1.3
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 +35 -142
- package/README.zh-CN.md +141 -124
- package/dist/ast/treeSitter.js +588 -0
- package/dist/bundle/analysis.js +47 -0
- package/dist/bundle/context7.js +65 -36
- package/dist/bundle/facts.js +829 -0
- package/dist/bundle/githubArchive.js +49 -28
- package/dist/bundle/overview.js +226 -48
- package/dist/bundle/service.js +27 -126
- package/dist/config.js +29 -3
- package/dist/context7/client.js +5 -2
- package/dist/evidence/dependencyGraph.js +826 -0
- package/dist/http/server.js +109 -0
- package/dist/search/sqliteFts.js +150 -10
- package/dist/server.js +84 -295
- package/dist/trace/service.js +108 -0
- package/dist/trace/store.js +170 -0
- package/package.json +4 -2
- package/dist/bundle/deepwiki.js +0 -206
package/dist/bundle/context7.js
CHANGED
|
@@ -138,15 +138,34 @@ async function writeJson(targetPath, obj) {
|
|
|
138
138
|
await ensureDir(path.dirname(targetPath));
|
|
139
139
|
await fs.writeFile(targetPath, JSON.stringify(obj, null, 2) + '\n', 'utf8');
|
|
140
140
|
}
|
|
141
|
+
async function sleep(ms) {
|
|
142
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
143
|
+
}
|
|
141
144
|
async function callOrThrow(client, name, args) {
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
const maxRetries = 3;
|
|
146
|
+
let lastError;
|
|
147
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
148
|
+
try {
|
|
149
|
+
const res = await client.callTool({ name, arguments: args });
|
|
150
|
+
if (res.isError) {
|
|
151
|
+
throw new Error(textFromToolResult(res) || `${name} failed`);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
text: textFromToolResult(res),
|
|
155
|
+
structured: res.structuredContent,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
160
|
+
// Don't retry on last attempt
|
|
161
|
+
if (attempt < maxRetries - 1) {
|
|
162
|
+
// Exponential backoff: 1s, 2s, 4s
|
|
163
|
+
const delayMs = Math.pow(2, attempt) * 1000;
|
|
164
|
+
await sleep(delayMs);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
145
167
|
}
|
|
146
|
-
|
|
147
|
-
text: textFromToolResult(res),
|
|
148
|
-
structured: res.structuredContent,
|
|
149
|
-
};
|
|
168
|
+
throw lastError || new Error(`${name} failed after ${maxRetries} retries`);
|
|
150
169
|
}
|
|
151
170
|
async function resolveContext7Id(client, input) {
|
|
152
171
|
const notes = [];
|
|
@@ -154,38 +173,48 @@ async function resolveContext7Id(client, input) {
|
|
|
154
173
|
if (trimmed.startsWith('/')) {
|
|
155
174
|
return { id: trimmed, notes };
|
|
156
175
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
const maxRetries = 3;
|
|
177
|
+
let lastError;
|
|
178
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
179
|
+
try {
|
|
180
|
+
const res = await client.callTool({
|
|
181
|
+
name: 'resolve-library-id',
|
|
182
|
+
arguments: { libraryName: trimmed },
|
|
183
|
+
});
|
|
184
|
+
if (res.isError) {
|
|
185
|
+
notes.push(`resolve-library-id error: ${textFromToolResult(res)}`);
|
|
186
|
+
return { notes };
|
|
187
|
+
}
|
|
188
|
+
const text = textFromToolResult(res);
|
|
189
|
+
// Prefer parsing the structured list output for better selection.
|
|
190
|
+
const parsed = parseResolveEntries(text);
|
|
191
|
+
const chosen = chooseBestEntry(parsed, trimmed);
|
|
192
|
+
if (chosen.id) {
|
|
193
|
+
notes.push(...chosen.notes);
|
|
194
|
+
return { id: chosen.id, notes };
|
|
195
|
+
}
|
|
196
|
+
// Fallback: regex/structured extraction.
|
|
197
|
+
const ids = extractContext7IdsFromResult(res);
|
|
198
|
+
if (ids.length === 0) {
|
|
199
|
+
notes.push('resolve-library-id returned no Context7 IDs');
|
|
200
|
+
return { notes };
|
|
201
|
+
}
|
|
202
|
+
if (ids.length > 1) {
|
|
203
|
+
notes.push(`resolve-library-id returned multiple IDs; using first: ${ids[0]}`);
|
|
204
|
+
}
|
|
205
|
+
return { id: ids[0], notes };
|
|
179
206
|
}
|
|
180
|
-
|
|
181
|
-
|
|
207
|
+
catch (err) {
|
|
208
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
209
|
+
// Don't retry on last attempt
|
|
210
|
+
if (attempt < maxRetries - 1) {
|
|
211
|
+
const delayMs = Math.pow(2, attempt) * 1000;
|
|
212
|
+
await sleep(delayMs);
|
|
213
|
+
}
|
|
182
214
|
}
|
|
183
|
-
return { id: ids[0], notes };
|
|
184
|
-
}
|
|
185
|
-
catch (err) {
|
|
186
|
-
notes.push(`resolve-library-id threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
187
|
-
return { notes };
|
|
188
215
|
}
|
|
216
|
+
notes.push(`resolve-library-id failed after ${maxRetries} retries: ${lastError?.message ?? 'unknown error'}`);
|
|
217
|
+
return { notes };
|
|
189
218
|
}
|
|
190
219
|
export async function ingestContext7Libraries(params) {
|
|
191
220
|
const libs = (params.libraries ?? []).map((s) => s.trim()).filter(Boolean);
|