flowseeker 0.1.7
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/CHANGELOG.md +111 -0
- package/COMPATIBILITY.md +281 -0
- package/LICENSE +21 -0
- package/README.md +375 -0
- package/dist/adapters/frameworkEdges.js +586 -0
- package/dist/agent/approvalPolicy.js +81 -0
- package/dist/agent/commandRunner.js +166 -0
- package/dist/agent/flowCommandRunner.js +124 -0
- package/dist/agent/mcpToolRunner.js +167 -0
- package/dist/auth/githubAuth.js +71 -0
- package/dist/auth/modelList.js +127 -0
- package/dist/auth/oauthHandler.js +377 -0
- package/dist/chat/nativeChatParticipant.js +616 -0
- package/dist/cli/mcpServer.js +383 -0
- package/dist/cli/runEvaluation.js +789 -0
- package/dist/cli/runReplay.js +481 -0
- package/dist/commands/checkHostCompatibility.js +149 -0
- package/dist/commands/copyAgentPrompt.js +52 -0
- package/dist/commands/copyContext.js +54 -0
- package/dist/commands/explainSelectionRelevance.js +57 -0
- package/dist/commands/findRelevantContext.js +127 -0
- package/dist/commands/openEvidence.js +49 -0
- package/dist/commands/openMcpConfig.js +81 -0
- package/dist/commands/openRelatedTests.js +54 -0
- package/dist/commands/rebuildIndex.js +45 -0
- package/dist/commands/runEvaluationSuite.js +323 -0
- package/dist/commands/runReplaySuite.js +228 -0
- package/dist/config/defaultConfig.js +72 -0
- package/dist/config/loadConfig.js +84 -0
- package/dist/config/loadConfigFromPath.js +60 -0
- package/dist/extension.js +513 -0
- package/dist/gateway/agentPrompts.js +176 -0
- package/dist/gateway/aiGateway.js +1255 -0
- package/dist/gateway/aiProviders.js +901 -0
- package/dist/gateway/contextExpansion.js +331 -0
- package/dist/gateway/editProposalStore.js +238 -0
- package/dist/gateway/planProposalStore.js +28 -0
- package/dist/index/cacheStore.js +51 -0
- package/dist/index/chunker.js +45 -0
- package/dist/index/dependencyExtractor.js +107 -0
- package/dist/index/fileDiscovery.js +177 -0
- package/dist/index/structuredExtractor.js +256 -0
- package/dist/index/workspaceIndex.js +518 -0
- package/dist/mcp/mcpConfig.js +154 -0
- package/dist/mcp/mcpProvider.js +109 -0
- package/dist/mcp/mcpTools.js +215 -0
- package/dist/pipeline/agentPrompt.js +79 -0
- package/dist/pipeline/agentPromptHeadless.js +85 -0
- package/dist/pipeline/contextBlueprint.js +346 -0
- package/dist/pipeline/contextPack.js +80 -0
- package/dist/pipeline/diffPreview.js +79 -0
- package/dist/pipeline/evaluationMetrics.js +154 -0
- package/dist/pipeline/evidenceGraph.js +389 -0
- package/dist/pipeline/feedback.js +215 -0
- package/dist/pipeline/fileGroups.js +84 -0
- package/dist/pipeline/fileScanner.js +866 -0
- package/dist/pipeline/nodeScan.js +219 -0
- package/dist/pipeline/ranker.js +563 -0
- package/dist/pipeline/responseLanguage.js +39 -0
- package/dist/pipeline/retrievalPlan.js +163 -0
- package/dist/pipeline/runHeadless.js +54 -0
- package/dist/pipeline/runPipeline.js +114 -0
- package/dist/pipeline/solvePacket.js +382 -0
- package/dist/pipeline/subsystem.js +257 -0
- package/dist/pipeline/taskUnderstanding.js +453 -0
- package/dist/pipeline/tokenSavings.js +146 -0
- package/dist/pipeline/universalScan.js +216 -0
- package/dist/pipeline/verifyAfterApply.js +233 -0
- package/dist/runtime/capabilities.js +71 -0
- package/dist/runtime/hostDetect.js +98 -0
- package/dist/runtime/hostTier.js +68 -0
- package/dist/runtime/statusBar.js +80 -0
- package/dist/skills/skillRegistry.js +208 -0
- package/dist/types.js +3 -0
- package/dist/ui/chatViewProvider.js +3899 -0
- package/dist/ui/resultTreeProvider.js +174 -0
- package/dist/usage/quotaTracker.js +358 -0
- package/dist/utils/async.js +30 -0
- package/dist/utils/logger.js +64 -0
- package/dist/utils/text.js +364 -0
- package/dist/utils/updateChecker.js +140 -0
- package/package.json +561 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runEvaluationSuite = runEvaluationSuite;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const vscode = __importStar(require("vscode"));
|
|
39
|
+
const evaluationMetrics_1 = require("../pipeline/evaluationMetrics");
|
|
40
|
+
const fileGroups_1 = require("../pipeline/fileGroups");
|
|
41
|
+
const runPipeline_1 = require("../pipeline/runPipeline");
|
|
42
|
+
const tokenSavings_1 = require("../pipeline/tokenSavings");
|
|
43
|
+
const logger_1 = require("../utils/logger");
|
|
44
|
+
async function runEvaluationSuite() {
|
|
45
|
+
const folders = vscode.workspace.workspaceFolders;
|
|
46
|
+
if (!folders || folders.length === 0) {
|
|
47
|
+
(0, logger_1.logInfo)("Run Evaluation Suite stopped because no workspace folder is open.");
|
|
48
|
+
vscode.window.showWarningMessage("Open a workspace folder before running FlowSeeker evaluation.");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const suiteFiles = await findSuiteFiles();
|
|
53
|
+
if (suiteFiles.length === 0) {
|
|
54
|
+
vscode.window.showWarningMessage("No FlowSeeker eval suites found. Add JSON suites under .flowseeker/evals/.");
|
|
55
|
+
(0, logger_1.logInfo)("No eval suites found under .flowseeker/evals/.");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const suites = await readSuites(suiteFiles);
|
|
59
|
+
const totalCases = suites.reduce((sum, suite) => sum + suite.cases.length, 0);
|
|
60
|
+
if (totalCases === 0) {
|
|
61
|
+
vscode.window.showWarningMessage("FlowSeeker eval suites were found, but none contain cases.");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
(0, logger_1.logInfo)(`Starting evaluation. Suites: ${suites.length}; cases: ${totalCases}; workspace: ${folders.map((folder) => folder.uri.fsPath).join("; ")}`);
|
|
65
|
+
const caseResults = await vscode.window.withProgress({
|
|
66
|
+
location: vscode.ProgressLocation.Notification,
|
|
67
|
+
title: "FlowSeeker is running eval suites",
|
|
68
|
+
cancellable: true
|
|
69
|
+
}, async (progress, token) => {
|
|
70
|
+
const results = [];
|
|
71
|
+
let completed = 0;
|
|
72
|
+
for (const suite of suites) {
|
|
73
|
+
for (const caseDef of suite.cases) {
|
|
74
|
+
if (token.isCancellationRequested) {
|
|
75
|
+
(0, logger_1.logInfo)("Evaluation cancelled by user.");
|
|
76
|
+
return results;
|
|
77
|
+
}
|
|
78
|
+
progress.report({
|
|
79
|
+
message: `${suite.name}: ${caseDef.id}`,
|
|
80
|
+
increment: totalCases > 0 ? 100 / totalCases : undefined
|
|
81
|
+
});
|
|
82
|
+
const startedAt = Date.now();
|
|
83
|
+
const result = await (0, runPipeline_1.runFlowSeeker)(caseDef.task, { token });
|
|
84
|
+
const durationMs = Date.now() - startedAt;
|
|
85
|
+
const evaluated = evaluateCase(suite.name, caseDef, result, durationMs);
|
|
86
|
+
results.push(evaluated);
|
|
87
|
+
completed += 1;
|
|
88
|
+
(0, logger_1.logInfo)(formatCaseLog(evaluated, completed, totalCases));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
});
|
|
93
|
+
if (caseResults.length === 0) {
|
|
94
|
+
vscode.window.showInformationMessage("FlowSeeker evaluation produced no results.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const reportUri = await writeReport(folders[0].uri, suites, caseResults);
|
|
98
|
+
(0, logger_1.logInfo)(`Evaluation complete. Report: ${reportUri.fsPath}`);
|
|
99
|
+
vscode.window.showInformationMessage(`FlowSeeker evaluation complete. Report saved: ${path.basename(reportUri.fsPath)}`);
|
|
100
|
+
await vscode.commands.executeCommand("vscode.open", reportUri);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
(0, logger_1.logError)("Run Evaluation Suite failed.", error);
|
|
104
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
105
|
+
vscode.window.showErrorMessage(`FlowSeeker evaluation failed: ${message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function findSuiteFiles() {
|
|
109
|
+
const found = await vscode.workspace.findFiles(".flowseeker/evals/**/*.json", "**/node_modules/**", 100);
|
|
110
|
+
const direct = await vscode.workspace.findFiles(".flowseeker/eval.json", "**/node_modules/**", 1);
|
|
111
|
+
const byKey = new Map();
|
|
112
|
+
for (const uri of direct.concat(found)) {
|
|
113
|
+
byKey.set(uri.toString(), uri);
|
|
114
|
+
}
|
|
115
|
+
return Array.from(byKey.values()).sort((left, right) => left.fsPath.localeCompare(right.fsPath));
|
|
116
|
+
}
|
|
117
|
+
async function readSuites(uris) {
|
|
118
|
+
const suites = [];
|
|
119
|
+
for (const uri of uris) {
|
|
120
|
+
const bytes = await vscode.workspace.fs.readFile(uri);
|
|
121
|
+
const parsed = JSON.parse(new TextDecoder("utf-8").decode(bytes));
|
|
122
|
+
if (!parsed.name || !Array.isArray(parsed.cases)) {
|
|
123
|
+
throw new Error(`Invalid eval suite: ${uri.fsPath}`);
|
|
124
|
+
}
|
|
125
|
+
const cases = parsed.cases.map((item, index) => {
|
|
126
|
+
if (!item?.id || !item?.task) {
|
|
127
|
+
throw new Error(`Invalid eval case at ${uri.fsPath}#${index + 1}: id and task are required.`);
|
|
128
|
+
}
|
|
129
|
+
return item;
|
|
130
|
+
});
|
|
131
|
+
suites.push({
|
|
132
|
+
name: parsed.name,
|
|
133
|
+
description: parsed.description,
|
|
134
|
+
cases
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return suites;
|
|
138
|
+
}
|
|
139
|
+
function evaluateCase(suiteName, caseDef, result, durationMs) {
|
|
140
|
+
const passAtK = caseDef.passAtK ?? 10;
|
|
141
|
+
const expectedMetrics = (0, evaluationMetrics_1.computeExpectedPathMetrics)(result.units, caseDef.expectedPaths ?? [], passAtK, caseDef.expectedMode ?? "any");
|
|
142
|
+
const hardAvoidHitsTop10 = findAvoidHits(result.units.slice(0, 10), caseDef.avoidPaths ?? [], "hard");
|
|
143
|
+
const contrastAvoidHitsTop10 = findAvoidHits(result.units.slice(0, 10), caseDef.avoidPaths ?? [], "contrast");
|
|
144
|
+
return {
|
|
145
|
+
suiteName,
|
|
146
|
+
caseDef,
|
|
147
|
+
result,
|
|
148
|
+
durationMs,
|
|
149
|
+
firstHitRank: expectedMetrics.firstUnitHitRank,
|
|
150
|
+
firstFileHitRank: expectedMetrics.firstFileHitRank,
|
|
151
|
+
expectedMetrics,
|
|
152
|
+
hitAt5: expectedMetrics.coverageAt5 > 0,
|
|
153
|
+
hitAt10: expectedMetrics.coverageAt10 > 0,
|
|
154
|
+
hitAt20: expectedMetrics.coverageAt20 > 0,
|
|
155
|
+
hitAt40: expectedMetrics.coverageAt40 > 0,
|
|
156
|
+
pass: expectedMetrics.pass,
|
|
157
|
+
avoidHitsTop10: uniqueStrings([...hardAvoidHitsTop10, ...contrastAvoidHitsTop10]),
|
|
158
|
+
hardAvoidHitsTop10,
|
|
159
|
+
contrastAvoidHitsTop10,
|
|
160
|
+
rankingQuality: (0, evaluationMetrics_1.computeRankingQualityMetrics)(result)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function findAvoidHits(units, avoidPaths, mode = "hard") {
|
|
164
|
+
if (avoidPaths.length === 0) {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
return uniqueStrings(units
|
|
168
|
+
.filter((unit) => avoidPaths.some((avoidPath) => (0, evaluationMetrics_1.pathMatches)(unit.relativePath, avoidPath)))
|
|
169
|
+
.filter((unit) => mode === "contrast" ? unit.contrastContext : !unit.contrastContext)
|
|
170
|
+
.map((unit) => unit.relativePath));
|
|
171
|
+
}
|
|
172
|
+
async function writeReport(rootUri, suites, results) {
|
|
173
|
+
const reportsDir = vscode.Uri.joinPath(rootUri, ".flowseeker", "reports");
|
|
174
|
+
await vscode.workspace.fs.createDirectory(reportsDir);
|
|
175
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
176
|
+
const reportUri = vscode.Uri.joinPath(reportsDir, `eval-${timestamp}.md`);
|
|
177
|
+
const report = renderReport(suites, results);
|
|
178
|
+
await vscode.workspace.fs.writeFile(reportUri, new TextEncoder().encode(report));
|
|
179
|
+
return reportUri;
|
|
180
|
+
}
|
|
181
|
+
function renderReport(suites, results) {
|
|
182
|
+
const labeled = results.filter((result) => result.pass !== "unlabeled");
|
|
183
|
+
const passed = labeled.filter((result) => result.pass === true);
|
|
184
|
+
const hitAt5 = count(results, (result) => result.hitAt5);
|
|
185
|
+
const hitAt10 = count(results, (result) => result.hitAt10);
|
|
186
|
+
const hitAt20 = count(results, (result) => result.hitAt20);
|
|
187
|
+
const hitAt40 = count(results, (result) => result.hitAt40);
|
|
188
|
+
const avgDurationMs = average(results.map((result) => result.durationMs));
|
|
189
|
+
const avgMrr = average(labeled.map((result) => (result.firstFileHitRank ? 1 / result.firstFileHitRank : 0)));
|
|
190
|
+
const lines = [
|
|
191
|
+
"# FlowSeeker Evaluation Report",
|
|
192
|
+
"",
|
|
193
|
+
`Generated: ${new Date().toISOString()}`,
|
|
194
|
+
`Suites: ${suites.length}`,
|
|
195
|
+
`Cases: ${results.length}`,
|
|
196
|
+
`Labeled cases: ${labeled.length}`,
|
|
197
|
+
`Pass@caseK: ${passed.length}/${labeled.length}`,
|
|
198
|
+
`Hit@5: ${hitAt5}/${results.length}`,
|
|
199
|
+
`Hit@10: ${hitAt10}/${results.length}`,
|
|
200
|
+
`Hit@20: ${hitAt20}/${results.length}`,
|
|
201
|
+
`Hit@40: ${hitAt40}/${results.length}`,
|
|
202
|
+
`MRR: ${avgMrr.toFixed(3)}`,
|
|
203
|
+
`Average duration: ${(avgDurationMs / 1000).toFixed(2)}s`,
|
|
204
|
+
`Token savings: ${formatTokenSavingsSummary(results)}`,
|
|
205
|
+
"",
|
|
206
|
+
"## Suites",
|
|
207
|
+
"",
|
|
208
|
+
...suites.map((suite) => `- ${suite.name}${suite.description ? ` - ${suite.description}` : ""}`),
|
|
209
|
+
"",
|
|
210
|
+
"## Cases",
|
|
211
|
+
""
|
|
212
|
+
];
|
|
213
|
+
for (const result of results) {
|
|
214
|
+
lines.push(...renderCase(result));
|
|
215
|
+
}
|
|
216
|
+
return `${lines.join("\n")}\n`;
|
|
217
|
+
}
|
|
218
|
+
function renderCase(result) {
|
|
219
|
+
const status = result.pass === "unlabeled" ? "UNLABELED" : result.pass ? "PASS" : "FAIL";
|
|
220
|
+
const firstHit = result.firstHitRank ? String(result.firstHitRank) : "none";
|
|
221
|
+
const firstFileHit = result.firstFileHitRank ? String(result.firstFileHitRank) : "none";
|
|
222
|
+
const stats = result.result.stats;
|
|
223
|
+
const topFiles = (0, fileGroups_1.aggregateEvidenceFiles)(result.result.units).slice(0, 15);
|
|
224
|
+
return [
|
|
225
|
+
`### ${status} - ${result.suiteName}/${result.caseDef.id}`,
|
|
226
|
+
"",
|
|
227
|
+
`Task: ${result.caseDef.task}`,
|
|
228
|
+
...(result.caseDef.notes ? [`Notes: ${result.caseDef.notes}`] : []),
|
|
229
|
+
`Intent: ${result.result.profile.intent}`,
|
|
230
|
+
`Keywords: ${result.result.profile.keywords.join(", ") || "none"}`,
|
|
231
|
+
`Strategies: ${result.result.profile.strategies.join(", ") || "none"}`,
|
|
232
|
+
`Expected paths: ${(result.caseDef.expectedPaths ?? []).join(", ") || "none"}`,
|
|
233
|
+
`Expected mode: ${result.caseDef.expectedMode ?? "any"}`,
|
|
234
|
+
`Avoid paths: ${(result.caseDef.avoidPaths ?? []).join(", ") || "none"}`,
|
|
235
|
+
`First expected unit rank: ${firstHit}`,
|
|
236
|
+
`First expected file rank: ${firstFileHit}`,
|
|
237
|
+
`Coverage@5/10/20/40: ${result.expectedMetrics.coverageAt5}/${result.expectedMetrics.expectedCount}, ${result.expectedMetrics.coverageAt10}/${result.expectedMetrics.expectedCount}, ${result.expectedMetrics.coverageAt20}/${result.expectedMetrics.expectedCount}, ${result.expectedMetrics.coverageAt40}/${result.expectedMetrics.expectedCount}`,
|
|
238
|
+
`Missing expected at 10: ${result.expectedMetrics.missingAt10.join(", ") || "none"}`,
|
|
239
|
+
`Missing expected at 20: ${result.expectedMetrics.missingAt20.join(", ") || "none"}`,
|
|
240
|
+
`Avoid hits in top 10: ${result.hardAvoidHitsTop10.join(", ") || "none"}`,
|
|
241
|
+
`Contrast avoid hits in top 10: ${result.contrastAvoidHitsTop10.join(", ") || "none"}`,
|
|
242
|
+
`Token savings: ${formatCaseTokenSavings(result)}`,
|
|
243
|
+
`Context coverage: ${formatContextCoverage(result.result)}`,
|
|
244
|
+
`Ranking quality: uniqueTop10Files=${result.rankingQuality.uniqueTop10Files}, duplicateEvidenceTop10=${result.rankingQuality.duplicateEvidenceTop10}, slotCoverageTop10=${result.rankingQuality.slotCoverageTop10}/${result.rankingQuality.requiredSlotCount}${result.rankingQuality.missingRequiredSlotsTop10.length ? `, missingSlots=${result.rankingQuality.missingRequiredSlotsTop10.join("|")}` : ""}, contrastContextTop10=${result.rankingQuality.contrastContextTop10}, primarySubsystem=${result.rankingQuality.primarySubsystemTop10 ?? "none"}, subsystemPurityTop10=${result.rankingQuality.subsystemPurityTop10.toFixed(2)}, symbolEvidenceTop10=${result.rankingQuality.symbolEvidenceTop10}`,
|
|
245
|
+
`Duration: ${(result.durationMs / 1000).toFixed(2)}s`,
|
|
246
|
+
`Scan: discovered=${stats.discoveredFiles}, scanned=${stats.scannedFiles}, skipped=${stats.skippedFiles}, bytes=${formatBytes(stats.scannedBytes)}, rawEvidence=${stats.rawEvidenceCount}, ranked=${stats.rankedEvidenceCount}, capped=${stats.capped}, stoppedEarly=${stats.stoppedEarly}${stats.stopReason ? ` (${stats.stopReason})` : ""}${formatIndexStats(stats)}`,
|
|
247
|
+
"",
|
|
248
|
+
"Top files:",
|
|
249
|
+
"",
|
|
250
|
+
...topFiles.map((group, index) => `${index + 1}. ${group.relativePath} [${group.role}/${group.slot}] score=${group.score.toFixed(1)} evidence=${group.unitCount} dup=${group.duplicateUnitCount} contrast=${group.contrastContext} subsystem=${group.subsystem ?? "none"} kinds=${group.kinds.join(",")}`),
|
|
251
|
+
"",
|
|
252
|
+
"Top evidence:",
|
|
253
|
+
"",
|
|
254
|
+
...result.result.units.slice(0, 15).map((unit, index) => {
|
|
255
|
+
const range = unit.range ? `:${unit.range.startLine}-${unit.range.endLine}` : "";
|
|
256
|
+
const passes = unit.retrievalPasses.length > 0 ? unit.retrievalPasses.join("+") : "none";
|
|
257
|
+
const meta = [unit.isDuplicate ? "duplicate" : "", unit.contrastContext ? "contrast" : "", unit.frameworkEdgeReason ? "framework" : ""].filter(Boolean).join(",");
|
|
258
|
+
return `${index + 1}. ${unit.relativePath}${range} [${unit.role}/${unit.kind}/${unit.slot ?? "unknown"}${meta ? `/${meta}` : ""}] score=${unit.score.toFixed(1)} passes=${passes}`;
|
|
259
|
+
}),
|
|
260
|
+
""
|
|
261
|
+
];
|
|
262
|
+
}
|
|
263
|
+
function formatCaseLog(result, completed, total) {
|
|
264
|
+
const status = result.pass === "unlabeled" ? "UNLABELED" : result.pass ? "PASS" : "FAIL";
|
|
265
|
+
const firstHit = result.firstFileHitRank ? `file rank ${result.firstFileHitRank}` : "no expected file hit";
|
|
266
|
+
return `Eval ${completed}/${total} ${status} ${result.suiteName}/${result.caseDef.id}: ${firstHit}; ${(0, tokenSavings_1.formatTokenSavingsLine)(result.result.tokenSavings)}; ${formatContextCoverage(result.result)}; duration ${(result.durationMs / 1000).toFixed(2)}s; raw evidence ${result.result.stats.rawEvidenceCount}.`;
|
|
267
|
+
}
|
|
268
|
+
function formatTokenSavingsSummary(results) {
|
|
269
|
+
const metrics = results.map((result) => result.result.tokenSavings).filter((item) => item !== undefined && item.status !== "unavailable");
|
|
270
|
+
if (metrics.length === 0) {
|
|
271
|
+
return "unavailable";
|
|
272
|
+
}
|
|
273
|
+
const avgReduction = average(metrics.map((item) => item.reductionPercent));
|
|
274
|
+
const avgPacketTokens = average(metrics.map((item) => item.solvePacketTokensEstimate));
|
|
275
|
+
const avgWorkspaceTokens = average(metrics.map((item) => item.workspaceTokensEstimate));
|
|
276
|
+
const partial = metrics.filter((item) => item.status === "partial").length;
|
|
277
|
+
return `avg=${(0, tokenSavings_1.formatReductionPercent)(avgReduction)}, packetAvg=${(0, tokenSavings_1.formatTokenCount)(avgPacketTokens)}, workspaceAvg=${(0, tokenSavings_1.formatTokenCount)(avgWorkspaceTokens)}, partial=${partial}/${metrics.length}`;
|
|
278
|
+
}
|
|
279
|
+
function formatCaseTokenSavings(result) {
|
|
280
|
+
const metrics = result.result.tokenSavings;
|
|
281
|
+
if (!metrics || metrics.status === "unavailable") {
|
|
282
|
+
return "unavailable";
|
|
283
|
+
}
|
|
284
|
+
const note = metrics.reason ? `; note=${metrics.reason}` : "";
|
|
285
|
+
const warnings = metrics.proofWarnings.length > 0 ? `; warnings=${metrics.proofWarnings.join(" | ")}` : "";
|
|
286
|
+
return `Solve Packet ${(0, tokenSavings_1.formatTokenCount)(metrics.solvePacketTokensEstimate)} / workspace ${(0, tokenSavings_1.formatTokenCount)(metrics.workspaceTokensEstimate)} tokens, candidates=${(0, tokenSavings_1.formatTokenCount)(metrics.candidateTokensEstimate)}, reduction ${(0, tokenSavings_1.formatReductionPercent)(metrics.reductionPercent)}, method=${metrics.method}, tokenizer=${metrics.tokenizer}, basis=${metrics.basis}, status=${metrics.status}, proof=${metrics.proofStatus}, files=${metrics.rankedFileCount}/${metrics.workspaceFileCount}${note}${warnings}`;
|
|
287
|
+
}
|
|
288
|
+
function formatContextCoverage(result) {
|
|
289
|
+
const coverage = result.contextCoverage;
|
|
290
|
+
if (!coverage) {
|
|
291
|
+
return "coverage unavailable";
|
|
292
|
+
}
|
|
293
|
+
const missing = coverage.missingRequiredSlots.length > 0 ? `, missing=${coverage.missingRequiredSlots.join("|")}` : "";
|
|
294
|
+
return `coverage ${coverage.foundRequiredSlots.length}/${coverage.requiredSlots.length} required (${coverage.requiredCoveragePercent.toFixed(0)}%)${missing}`;
|
|
295
|
+
}
|
|
296
|
+
function boolText(value) {
|
|
297
|
+
return value ? "yes" : "no";
|
|
298
|
+
}
|
|
299
|
+
function uniqueStrings(values) {
|
|
300
|
+
return Array.from(new Set(values));
|
|
301
|
+
}
|
|
302
|
+
function count(items, predicate) {
|
|
303
|
+
return items.filter(predicate).length;
|
|
304
|
+
}
|
|
305
|
+
function average(values) {
|
|
306
|
+
if (values.length === 0) {
|
|
307
|
+
return 0;
|
|
308
|
+
}
|
|
309
|
+
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
310
|
+
}
|
|
311
|
+
function formatBytes(bytes) {
|
|
312
|
+
if (bytes < 1024 * 1024) {
|
|
313
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
314
|
+
}
|
|
315
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
316
|
+
}
|
|
317
|
+
function formatIndexStats(stats) {
|
|
318
|
+
if (stats.indexedFiles === undefined) {
|
|
319
|
+
return "";
|
|
320
|
+
}
|
|
321
|
+
return `, indexed=${stats.indexedFiles}, candidates=${stats.candidateFiles ?? "unknown"}, indexReused=${stats.indexReusedFiles ?? 0}, indexUpdated=${stats.indexUpdatedFiles ?? 0}`;
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=runEvaluationSuite.js.map
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runReplaySuite = runReplaySuite;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const vscode = __importStar(require("vscode"));
|
|
39
|
+
const feedback_1 = require("../pipeline/feedback");
|
|
40
|
+
const fileGroups_1 = require("../pipeline/fileGroups");
|
|
41
|
+
const runPipeline_1 = require("../pipeline/runPipeline");
|
|
42
|
+
const tokenSavings_1 = require("../pipeline/tokenSavings");
|
|
43
|
+
const logger_1 = require("../utils/logger");
|
|
44
|
+
async function runReplaySuite() {
|
|
45
|
+
const folders = vscode.workspace.workspaceFolders;
|
|
46
|
+
if (!folders || folders.length === 0) {
|
|
47
|
+
(0, logger_1.logInfo)("Run Real-World Replay stopped because no workspace folder is open.");
|
|
48
|
+
vscode.window.showWarningMessage("Open a workspace folder before running FlowSeeker replay.");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const root = folders[0];
|
|
52
|
+
try {
|
|
53
|
+
const records = await (0, feedback_1.readFeedbackRecords)(root.uri.fsPath);
|
|
54
|
+
if (records.length === 0) {
|
|
55
|
+
vscode.window.showInformationMessage("No FlowSeeker feedback found yet. Run a chat request and mark the packet as Relevant, Missing file, Not relevant, or AI needed more.");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
(0, logger_1.logInfo)(`Starting real-world replay from feedback. Cases: ${records.length}; workspace: ${root.uri.fsPath}`);
|
|
59
|
+
const results = await vscode.window.withProgress({
|
|
60
|
+
location: vscode.ProgressLocation.Notification,
|
|
61
|
+
title: "FlowSeeker is replaying real-world feedback",
|
|
62
|
+
cancellable: true
|
|
63
|
+
}, async (progress, token) => {
|
|
64
|
+
const replayResults = [];
|
|
65
|
+
let completed = 0;
|
|
66
|
+
for (const { record } of records) {
|
|
67
|
+
if (token.isCancellationRequested) {
|
|
68
|
+
(0, logger_1.logInfo)("Real-world replay cancelled by user.");
|
|
69
|
+
return replayResults;
|
|
70
|
+
}
|
|
71
|
+
progress.report({
|
|
72
|
+
message: `${completed + 1}/${records.length}: ${record.run.task.slice(0, 64)}`,
|
|
73
|
+
increment: records.length > 0 ? 100 / records.length : undefined
|
|
74
|
+
});
|
|
75
|
+
const startedAt = Date.now();
|
|
76
|
+
const result = await (0, runPipeline_1.runFlowSeeker)(record.run.task, { token });
|
|
77
|
+
const replayResult = evaluateReplay(record, result, Date.now() - startedAt);
|
|
78
|
+
replayResults.push(replayResult);
|
|
79
|
+
completed += 1;
|
|
80
|
+
(0, logger_1.logInfo)(formatReplayLog(replayResult, completed, records.length));
|
|
81
|
+
}
|
|
82
|
+
return replayResults;
|
|
83
|
+
});
|
|
84
|
+
if (results.length === 0) {
|
|
85
|
+
vscode.window.showInformationMessage("FlowSeeker replay produced no results.");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const reportUri = await writeReplayReport(root.uri, results);
|
|
89
|
+
(0, logger_1.logInfo)(`Real-world replay complete. Report: ${reportUri.fsPath}`);
|
|
90
|
+
vscode.window.showInformationMessage(`FlowSeeker replay complete. Report saved: ${path.basename(reportUri.fsPath)}`);
|
|
91
|
+
await vscode.commands.executeCommand("vscode.open", reportUri);
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
(0, logger_1.logError)("Run Real-World Replay failed.", error);
|
|
95
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
96
|
+
vscode.window.showErrorMessage(`FlowSeeker replay failed: ${message}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function evaluateReplay(feedback, result, durationMs) {
|
|
100
|
+
const contextGapReported = feedback.kind === "missing_file" || feedback.kind === "agent_needed_more_context" || feedback.outcome?.aiNeededMoreContext === true;
|
|
101
|
+
const positiveFeedback = feedback.kind === "relevant" || feedback.outcome?.planAccepted === true || feedback.outcome?.fixVerified === true;
|
|
102
|
+
const negativeFeedback = feedback.kind === "not_relevant" || contextGapReported;
|
|
103
|
+
return {
|
|
104
|
+
feedback,
|
|
105
|
+
result,
|
|
106
|
+
durationMs,
|
|
107
|
+
contextGapReported,
|
|
108
|
+
positiveFeedback,
|
|
109
|
+
negativeFeedback
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function writeReplayReport(rootUri, results) {
|
|
113
|
+
const reportsDir = vscode.Uri.joinPath(rootUri, ".flowseeker", "reports");
|
|
114
|
+
await vscode.workspace.fs.createDirectory(reportsDir);
|
|
115
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
116
|
+
const reportUri = vscode.Uri.joinPath(reportsDir, `real-world-replay-${timestamp}.md`);
|
|
117
|
+
await vscode.workspace.fs.writeFile(reportUri, new TextEncoder().encode(renderReport(results)));
|
|
118
|
+
return reportUri;
|
|
119
|
+
}
|
|
120
|
+
function renderReport(results) {
|
|
121
|
+
const lines = [
|
|
122
|
+
"# FlowSeeker Real-World Replay Report",
|
|
123
|
+
"",
|
|
124
|
+
`Generated: ${new Date().toISOString()}`,
|
|
125
|
+
`Cases: ${results.length}`,
|
|
126
|
+
"",
|
|
127
|
+
"## Summary",
|
|
128
|
+
"",
|
|
129
|
+
formatSummary(results),
|
|
130
|
+
formatTokenSavingsSummary(results),
|
|
131
|
+
"",
|
|
132
|
+
"## Meaning",
|
|
133
|
+
"",
|
|
134
|
+
"- `Context gap reported` comes from local user/agent feedback.",
|
|
135
|
+
"- `Current top files` are from replaying the same task against the current workspace.",
|
|
136
|
+
"- `Original top files` are from the saved feedback snapshot, so drift is visible after ranking changes.",
|
|
137
|
+
"- Source snippets are not stored in feedback records.",
|
|
138
|
+
"",
|
|
139
|
+
"## Cases",
|
|
140
|
+
""
|
|
141
|
+
];
|
|
142
|
+
for (const result of results) {
|
|
143
|
+
lines.push(...renderCase(result));
|
|
144
|
+
}
|
|
145
|
+
return `${lines.join("\n")}\n`;
|
|
146
|
+
}
|
|
147
|
+
function renderCase(result) {
|
|
148
|
+
const feedback = result.feedback;
|
|
149
|
+
const topCurrent = (0, fileGroups_1.aggregateEvidenceFiles)(result.result.units).slice(0, 12);
|
|
150
|
+
const originalTop = feedback.run.topFiles.slice(0, 8);
|
|
151
|
+
const coverage = result.result.contextCoverage;
|
|
152
|
+
const stats = result.result.stats;
|
|
153
|
+
return [
|
|
154
|
+
`### ${feedbackKindLabel(feedback.kind)} - ${feedback.run.task}`,
|
|
155
|
+
"",
|
|
156
|
+
`Feedback time: ${feedback.createdAt}`,
|
|
157
|
+
`Feedback note: ${feedback.note ?? "none"}`,
|
|
158
|
+
`Context gap reported: ${yesNo(result.contextGapReported)}`,
|
|
159
|
+
`Positive feedback: ${yesNo(result.positiveFeedback)}`,
|
|
160
|
+
`Current intent: ${result.result.profile.intent}`,
|
|
161
|
+
`Original intent: ${feedback.run.intent}`,
|
|
162
|
+
`Current token savings: ${formatCaseTokenSavings(result.result.tokenSavings)}`,
|
|
163
|
+
feedback.run.tokenSavings ? `Original token savings: ${(0, tokenSavings_1.formatTokenCount)(feedback.run.tokenSavings.solvePacketTokensEstimate)} / ${(0, tokenSavings_1.formatTokenCount)(feedback.run.tokenSavings.workspaceTokensEstimate)} saved=${(0, tokenSavings_1.formatReductionPercent)(feedback.run.tokenSavings.reductionPercent)} tokenizer=${feedback.run.tokenSavings.tokenizer}` : "Original token savings: unavailable",
|
|
164
|
+
coverage ? `Current context coverage: ${coverage.foundRequiredSlots.length}/${coverage.requiredSlots.length} required (${coverage.requiredCoveragePercent.toFixed(0)}%)${coverage.missingRequiredSlots.length ? ` missing=${coverage.missingRequiredSlots.join("|")}` : ""}` : "Current context coverage: unavailable",
|
|
165
|
+
`Duration: ${(result.durationMs / 1000).toFixed(2)}s`,
|
|
166
|
+
`Scan: discovered=${stats.discoveredFiles}, scanned=${stats.scannedFiles}, skipped=${stats.skippedFiles}, rawEvidence=${stats.rawEvidenceCount}, ranked=${stats.rankedEvidenceCount}, capped=${stats.capped}, stoppedEarly=${stats.stoppedEarly}${stats.stopReason ? ` (${stats.stopReason})` : ""}`,
|
|
167
|
+
"",
|
|
168
|
+
"Current top files:",
|
|
169
|
+
"",
|
|
170
|
+
...topCurrent.map((group, index) => `${index + 1}. ${group.relativePath} [${group.role}/${group.slot}] score=${group.score.toFixed(1)} evidence=${group.unitCount}`),
|
|
171
|
+
"",
|
|
172
|
+
"Original top files:",
|
|
173
|
+
"",
|
|
174
|
+
...originalTop.map((file, index) => `${index + 1}. ${file.relativePath} [${file.role}/${file.slot ?? "unknown"}] score=${file.score.toFixed(1)} evidence=${file.evidence}`),
|
|
175
|
+
""
|
|
176
|
+
];
|
|
177
|
+
}
|
|
178
|
+
function formatSummary(results) {
|
|
179
|
+
const positive = results.filter((result) => result.positiveFeedback).length;
|
|
180
|
+
const negative = results.filter((result) => result.negativeFeedback).length;
|
|
181
|
+
const gaps = results.filter((result) => result.contextGapReported).length;
|
|
182
|
+
const avgCoverage = average(results.map((result) => result.result.contextCoverage?.requiredCoveragePercent ?? 0));
|
|
183
|
+
const avgDuration = average(results.map((result) => result.durationMs));
|
|
184
|
+
return `cases=${results.length}, positiveFeedback=${positive}/${results.length}, negativeFeedback=${negative}/${results.length}, contextGapReported=${gaps}/${results.length}, requiredCoverageAvg=${avgCoverage.toFixed(1)}%, avg=${(avgDuration / 1000).toFixed(2)}s`;
|
|
185
|
+
}
|
|
186
|
+
function formatTokenSavingsSummary(results) {
|
|
187
|
+
const metrics = results.map((result) => result.result.tokenSavings).filter((item) => item !== undefined && item.status !== "unavailable");
|
|
188
|
+
if (metrics.length === 0) {
|
|
189
|
+
return "tokenSavings=unavailable";
|
|
190
|
+
}
|
|
191
|
+
const avgReduction = average(metrics.map((item) => item.reductionPercent));
|
|
192
|
+
const avgPacketTokens = average(metrics.map((item) => item.solvePacketTokensEstimate));
|
|
193
|
+
const avgWorkspaceTokens = average(metrics.map((item) => item.workspaceTokensEstimate));
|
|
194
|
+
const partial = metrics.filter((item) => item.status === "partial").length;
|
|
195
|
+
return `tokenSavings avg=${(0, tokenSavings_1.formatReductionPercent)(avgReduction)}, packetAvg=${(0, tokenSavings_1.formatTokenCount)(avgPacketTokens)}, workspaceAvg=${(0, tokenSavings_1.formatTokenCount)(avgWorkspaceTokens)}, partial=${partial}/${metrics.length}`;
|
|
196
|
+
}
|
|
197
|
+
function formatCaseTokenSavings(metrics) {
|
|
198
|
+
if (!metrics || metrics.status === "unavailable") {
|
|
199
|
+
return "unavailable";
|
|
200
|
+
}
|
|
201
|
+
const warnings = metrics.proofWarnings.length > 0 ? `; warnings=${metrics.proofWarnings.join(" | ")}` : "";
|
|
202
|
+
return `${(0, tokenSavings_1.formatTokenCount)(metrics.solvePacketTokensEstimate)} / ${(0, tokenSavings_1.formatTokenCount)(metrics.workspaceTokensEstimate)} saved=${(0, tokenSavings_1.formatReductionPercent)(metrics.reductionPercent)} tokenizer=${metrics.tokenizer} proof=${metrics.proofStatus}${warnings}`;
|
|
203
|
+
}
|
|
204
|
+
function formatReplayLog(result, completed, total) {
|
|
205
|
+
return `Replay ${completed}/${total} ${result.feedback.kind}: gap=${yesNo(result.contextGapReported)}; ${formatCaseTokenSavings(result.result.tokenSavings)}; duration ${(result.durationMs / 1000).toFixed(2)}s.`;
|
|
206
|
+
}
|
|
207
|
+
function feedbackKindLabel(kind) {
|
|
208
|
+
switch (kind) {
|
|
209
|
+
case "relevant":
|
|
210
|
+
return "RELEVANT";
|
|
211
|
+
case "missing_file":
|
|
212
|
+
return "MISSING CONTEXT";
|
|
213
|
+
case "not_relevant":
|
|
214
|
+
return "NOT RELEVANT";
|
|
215
|
+
case "agent_needed_more_context":
|
|
216
|
+
return "AI NEEDED MORE CONTEXT";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function yesNo(value) {
|
|
220
|
+
return value ? "yes" : "no";
|
|
221
|
+
}
|
|
222
|
+
function average(values) {
|
|
223
|
+
if (values.length === 0) {
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=runReplaySuite.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultConfig = void 0;
|
|
4
|
+
exports.mergeConfig = mergeConfig;
|
|
5
|
+
exports.defaultConfig = {
|
|
6
|
+
project: {
|
|
7
|
+
name: "FlowSeeker Workspace",
|
|
8
|
+
include: ["**/*"],
|
|
9
|
+
exclude: ["node_modules", "vendor", "dist", "build", "out", ".git", "coverage", ".next", "target", ".vscode-test", ".turbo", ".gradle", ".dart_tool", ".venv", "venv", "__pycache__", ".mypy_cache", ".pytest_cache", ".flowseeker", ".flowseeker/cache", ".flowseeker/reports", ".flowseeker/feedback", ".flowseeker/evals", ".flowseeker/eval*.json", "logs", "tmp", "temp", "drizzle/meta", "storage/framework", "bootstrap/cache", "**/_gen*.py", "**/_gen*.sh", "**/_bulk_write.js", "**/*.snap", "**/*snapshot*.json"],
|
|
10
|
+
maxFileSizeKb: 800
|
|
11
|
+
},
|
|
12
|
+
index: {
|
|
13
|
+
enableWorkspaceIndex: true,
|
|
14
|
+
enableTreeSitter: true,
|
|
15
|
+
enableLsp: false,
|
|
16
|
+
enableGitHistory: false,
|
|
17
|
+
chunkSizeLines: 80,
|
|
18
|
+
chunkOverlapLines: 12,
|
|
19
|
+
enableDependencyExpansion: true,
|
|
20
|
+
maxSeedCandidateFiles: 250,
|
|
21
|
+
maxDependencyExpansionFiles: 400,
|
|
22
|
+
maxIndexedCandidateFiles: 800
|
|
23
|
+
},
|
|
24
|
+
ai: {
|
|
25
|
+
enabled: false,
|
|
26
|
+
provider: "openai",
|
|
27
|
+
model: "gpt-5.2",
|
|
28
|
+
baseUrl: "",
|
|
29
|
+
useDirectProvider: false,
|
|
30
|
+
apiKeyEnv: "FLOWSEEKER_API_KEY",
|
|
31
|
+
maxInputTokens: 6000,
|
|
32
|
+
outputLanguage: "auto"
|
|
33
|
+
},
|
|
34
|
+
pipeline: {
|
|
35
|
+
maxCandidates: 40,
|
|
36
|
+
maxContextTokens: 4000,
|
|
37
|
+
graphDepth: 2,
|
|
38
|
+
minConfidence: 0.45,
|
|
39
|
+
maxFiles: 5000,
|
|
40
|
+
maxTotalBytesMb: 120,
|
|
41
|
+
maxScanMs: 30000,
|
|
42
|
+
maxRawEvidence: 1000
|
|
43
|
+
},
|
|
44
|
+
synonyms: {
|
|
45
|
+
mail: ["email", "smtp", "mailer", "sendmail", "notification"],
|
|
46
|
+
payment: ["billing", "invoice", "checkout", "transaction", "stripe"],
|
|
47
|
+
auth: ["login", "session", "jwt", "token", "permission", "role"],
|
|
48
|
+
queue: ["job", "worker", "dispatch", "schedule", "retry"],
|
|
49
|
+
verify: ["verified", "verification", "confirm", "confirmation", "activate", "activation", "email_verified", "emailverified"],
|
|
50
|
+
welcome: ["onboarding", "greeting", "registration", "registered", "signup", "sign_up"],
|
|
51
|
+
timestamp: ["time", "date", "datetime", "time_zone", "timezone", "tz", "utc", "created_at", "updated_at", "submitted_at", "scheduled_at"],
|
|
52
|
+
timezone: ["time_zone", "tz", "utc", "locale", "local_time", "localtime", "browser", "client"],
|
|
53
|
+
browser: ["client", "frontend", "navigator", "locale", "time_zone", "timezone", "tz"],
|
|
54
|
+
schedule: ["scheduled", "scheduled_at", "delay", "delayed", "queue_at"],
|
|
55
|
+
review: ["investigate", "trace", "check", "audit", "inspect"],
|
|
56
|
+
document: ["file", "attachment", "submission", "upload", "document_type", "type"],
|
|
57
|
+
upload: ["submit", "submission", "file", "attachment", "storage", "disk"],
|
|
58
|
+
export: ["download", "report", "csv", "excel", "xlsx", "file"],
|
|
59
|
+
validation: ["validator", "request", "rule", "rules", "schema", "input"],
|
|
60
|
+
permission: ["authorize", "policy", "role", "guard", "middleware", "acl"]
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
function mergeConfig(base, override) {
|
|
64
|
+
return {
|
|
65
|
+
project: { ...base.project, ...override.project },
|
|
66
|
+
index: { ...base.index, ...override.index },
|
|
67
|
+
ai: { ...base.ai, ...override.ai },
|
|
68
|
+
pipeline: { ...base.pipeline, ...override.pipeline },
|
|
69
|
+
synonyms: { ...base.synonyms, ...override.synonyms }
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=defaultConfig.js.map
|