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.
Files changed (82) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/COMPATIBILITY.md +281 -0
  3. package/LICENSE +21 -0
  4. package/README.md +375 -0
  5. package/dist/adapters/frameworkEdges.js +586 -0
  6. package/dist/agent/approvalPolicy.js +81 -0
  7. package/dist/agent/commandRunner.js +166 -0
  8. package/dist/agent/flowCommandRunner.js +124 -0
  9. package/dist/agent/mcpToolRunner.js +167 -0
  10. package/dist/auth/githubAuth.js +71 -0
  11. package/dist/auth/modelList.js +127 -0
  12. package/dist/auth/oauthHandler.js +377 -0
  13. package/dist/chat/nativeChatParticipant.js +616 -0
  14. package/dist/cli/mcpServer.js +383 -0
  15. package/dist/cli/runEvaluation.js +789 -0
  16. package/dist/cli/runReplay.js +481 -0
  17. package/dist/commands/checkHostCompatibility.js +149 -0
  18. package/dist/commands/copyAgentPrompt.js +52 -0
  19. package/dist/commands/copyContext.js +54 -0
  20. package/dist/commands/explainSelectionRelevance.js +57 -0
  21. package/dist/commands/findRelevantContext.js +127 -0
  22. package/dist/commands/openEvidence.js +49 -0
  23. package/dist/commands/openMcpConfig.js +81 -0
  24. package/dist/commands/openRelatedTests.js +54 -0
  25. package/dist/commands/rebuildIndex.js +45 -0
  26. package/dist/commands/runEvaluationSuite.js +323 -0
  27. package/dist/commands/runReplaySuite.js +228 -0
  28. package/dist/config/defaultConfig.js +72 -0
  29. package/dist/config/loadConfig.js +84 -0
  30. package/dist/config/loadConfigFromPath.js +60 -0
  31. package/dist/extension.js +513 -0
  32. package/dist/gateway/agentPrompts.js +176 -0
  33. package/dist/gateway/aiGateway.js +1255 -0
  34. package/dist/gateway/aiProviders.js +901 -0
  35. package/dist/gateway/contextExpansion.js +331 -0
  36. package/dist/gateway/editProposalStore.js +238 -0
  37. package/dist/gateway/planProposalStore.js +28 -0
  38. package/dist/index/cacheStore.js +51 -0
  39. package/dist/index/chunker.js +45 -0
  40. package/dist/index/dependencyExtractor.js +107 -0
  41. package/dist/index/fileDiscovery.js +177 -0
  42. package/dist/index/structuredExtractor.js +256 -0
  43. package/dist/index/workspaceIndex.js +518 -0
  44. package/dist/mcp/mcpConfig.js +154 -0
  45. package/dist/mcp/mcpProvider.js +109 -0
  46. package/dist/mcp/mcpTools.js +215 -0
  47. package/dist/pipeline/agentPrompt.js +79 -0
  48. package/dist/pipeline/agentPromptHeadless.js +85 -0
  49. package/dist/pipeline/contextBlueprint.js +346 -0
  50. package/dist/pipeline/contextPack.js +80 -0
  51. package/dist/pipeline/diffPreview.js +79 -0
  52. package/dist/pipeline/evaluationMetrics.js +154 -0
  53. package/dist/pipeline/evidenceGraph.js +389 -0
  54. package/dist/pipeline/feedback.js +215 -0
  55. package/dist/pipeline/fileGroups.js +84 -0
  56. package/dist/pipeline/fileScanner.js +866 -0
  57. package/dist/pipeline/nodeScan.js +219 -0
  58. package/dist/pipeline/ranker.js +563 -0
  59. package/dist/pipeline/responseLanguage.js +39 -0
  60. package/dist/pipeline/retrievalPlan.js +163 -0
  61. package/dist/pipeline/runHeadless.js +54 -0
  62. package/dist/pipeline/runPipeline.js +114 -0
  63. package/dist/pipeline/solvePacket.js +382 -0
  64. package/dist/pipeline/subsystem.js +257 -0
  65. package/dist/pipeline/taskUnderstanding.js +453 -0
  66. package/dist/pipeline/tokenSavings.js +146 -0
  67. package/dist/pipeline/universalScan.js +216 -0
  68. package/dist/pipeline/verifyAfterApply.js +233 -0
  69. package/dist/runtime/capabilities.js +71 -0
  70. package/dist/runtime/hostDetect.js +98 -0
  71. package/dist/runtime/hostTier.js +68 -0
  72. package/dist/runtime/statusBar.js +80 -0
  73. package/dist/skills/skillRegistry.js +208 -0
  74. package/dist/types.js +3 -0
  75. package/dist/ui/chatViewProvider.js +3899 -0
  76. package/dist/ui/resultTreeProvider.js +174 -0
  77. package/dist/usage/quotaTracker.js +358 -0
  78. package/dist/utils/async.js +30 -0
  79. package/dist/utils/logger.js +64 -0
  80. package/dist/utils/text.js +364 -0
  81. package/dist/utils/updateChecker.js +140 -0
  82. package/package.json +561 -0
@@ -0,0 +1,481 @@
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
+ const fs = __importStar(require("fs/promises"));
37
+ const path = __importStar(require("path"));
38
+ const loadConfigFromPath_1 = require("../config/loadConfigFromPath");
39
+ const defaultConfig_1 = require("../config/defaultConfig");
40
+ const evaluationMetrics_1 = require("../pipeline/evaluationMetrics");
41
+ const feedback_1 = require("../pipeline/feedback");
42
+ const fileGroups_1 = require("../pipeline/fileGroups");
43
+ const runHeadless_1 = require("../pipeline/runHeadless");
44
+ const tokenSavings_1 = require("../pipeline/tokenSavings");
45
+ const text_1 = require("../utils/text");
46
+ void main().catch((error) => {
47
+ const message = error instanceof Error ? error.stack ?? error.message : String(error);
48
+ console.error(message);
49
+ process.exitCode = 1;
50
+ });
51
+ async function main() {
52
+ const options = parseArgs(process.argv.slice(2));
53
+ const loaded = await loadReplayManifest(options);
54
+ const manifest = loaded.manifest;
55
+ validateManifest(manifest, loaded.source);
56
+ const startedAt = Date.now();
57
+ const results = [];
58
+ console.log(`FlowSeeker real-world replay: ${manifest.name ?? loaded.source}`);
59
+ console.log(`${loaded.kind}: ${loaded.source}`);
60
+ for (const workspace of manifest.workspaces) {
61
+ const workspacePath = path.resolve(workspace.path);
62
+ const workspaceName = workspace.name ?? path.basename(workspacePath);
63
+ const config = (0, defaultConfig_1.mergeConfig)(await (0, loadConfigFromPath_1.loadConfigFromPath)(workspacePath), workspace.config ?? {});
64
+ const cases = filterCases(await loadCases(workspacePath, workspace), options.caseId);
65
+ if (cases.length === 0) {
66
+ continue;
67
+ }
68
+ console.log(`\nWorkspace: ${workspaceName}`);
69
+ console.log(`Path: ${workspacePath}`);
70
+ console.log(`Cases: ${cases.length}`);
71
+ for (const caseDef of cases) {
72
+ const startedCaseAt = Date.now();
73
+ console.log(`- ${caseDef.id}: ${caseDef.task}`);
74
+ const result = await (0, runHeadless_1.runFlowSeekerHeadless)(workspacePath, caseDef.task, config, {
75
+ onProgress: options.verbose ? (message) => console.log(` ${message}`) : undefined
76
+ });
77
+ const evaluated = evaluateCase(workspaceName, workspacePath, caseDef, result, Date.now() - startedCaseAt);
78
+ results.push(evaluated);
79
+ console.log(` ${formatCaseConsole(evaluated)}`);
80
+ }
81
+ }
82
+ if (options.caseId && results.length === 0) {
83
+ throw new Error(`No replay case matched --case-id '${options.caseId}'.`);
84
+ }
85
+ const reportPath = path.resolve(options.reportPath ?? manifest.reportPath ?? defaultReportPath());
86
+ await fs.mkdir(path.dirname(reportPath), { recursive: true });
87
+ await fs.writeFile(reportPath, renderReport(manifest, results, Date.now() - startedAt), "utf8");
88
+ console.log(`\nReport: ${reportPath}`);
89
+ console.log(formatSummary(results));
90
+ console.log(formatTokenSavingsSummary(results));
91
+ if (options.failOnMiss && results.some((result) => result.pass === false)) {
92
+ process.exitCode = 1;
93
+ }
94
+ if (options.failOnGap && results.some((result) => result.contextGapReported)) {
95
+ process.exitCode = 1;
96
+ }
97
+ }
98
+ function parseArgs(args) {
99
+ const options = {
100
+ failOnGap: false,
101
+ failOnMiss: false,
102
+ verbose: false
103
+ };
104
+ for (let index = 0; index < args.length; index += 1) {
105
+ const arg = args[index];
106
+ if (arg === "--manifest" || arg === "-m") {
107
+ options.manifestPath = requireValue(args, index, arg);
108
+ index += 1;
109
+ continue;
110
+ }
111
+ if (arg === "--workspace" || arg === "-w") {
112
+ options.workspacePath = requireValue(args, index, arg);
113
+ index += 1;
114
+ continue;
115
+ }
116
+ if (arg === "--name") {
117
+ options.workspaceName = requireValue(args, index, arg);
118
+ index += 1;
119
+ continue;
120
+ }
121
+ if (arg === "--task" || arg === "-t") {
122
+ options.task = requireValue(args, index, arg);
123
+ index += 1;
124
+ continue;
125
+ }
126
+ if (arg === "--case-id") {
127
+ options.caseId = requireValue(args, index, arg);
128
+ index += 1;
129
+ continue;
130
+ }
131
+ if (arg === "--feedback-dir") {
132
+ options.feedbackDir = requireValue(args, index, arg);
133
+ index += 1;
134
+ continue;
135
+ }
136
+ if (arg === "--report" || arg === "-r") {
137
+ options.reportPath = requireValue(args, index, arg);
138
+ index += 1;
139
+ continue;
140
+ }
141
+ if (arg === "--fail-on-gap") {
142
+ options.failOnGap = true;
143
+ continue;
144
+ }
145
+ if (arg === "--fail-on-miss") {
146
+ options.failOnMiss = true;
147
+ continue;
148
+ }
149
+ if (arg === "--verbose" || arg === "-v") {
150
+ options.verbose = true;
151
+ continue;
152
+ }
153
+ if (arg === "--help" || arg === "-h") {
154
+ printUsage();
155
+ process.exit(0);
156
+ }
157
+ throw new Error(`Unknown argument: ${arg}`);
158
+ }
159
+ return options;
160
+ }
161
+ async function loadReplayManifest(options) {
162
+ if (options.workspacePath) {
163
+ const workspacePath = path.resolve(options.workspacePath);
164
+ if (options.task?.trim()) {
165
+ return {
166
+ source: workspacePath,
167
+ kind: "Ad-hoc workspace",
168
+ manifest: {
169
+ name: `Ad-hoc replay: ${options.workspaceName ?? path.basename(workspacePath)}`,
170
+ reportPath: options.reportPath,
171
+ workspaces: [
172
+ {
173
+ name: options.workspaceName ?? path.basename(workspacePath),
174
+ path: workspacePath,
175
+ cases: [
176
+ {
177
+ id: options.caseId ?? slugify(options.task),
178
+ task: options.task.trim(),
179
+ source: "cli"
180
+ }
181
+ ]
182
+ }
183
+ ]
184
+ }
185
+ };
186
+ }
187
+ return {
188
+ source: options.feedbackDir ? path.resolve(options.feedbackDir) : workspacePath,
189
+ kind: "Feedback workspace",
190
+ manifest: {
191
+ name: `Feedback replay: ${options.workspaceName ?? path.basename(workspacePath)}`,
192
+ reportPath: options.reportPath,
193
+ workspaces: [
194
+ {
195
+ name: options.workspaceName ?? path.basename(workspacePath),
196
+ path: workspacePath,
197
+ includeFeedback: true,
198
+ feedbackDir: options.feedbackDir
199
+ }
200
+ ]
201
+ }
202
+ };
203
+ }
204
+ const manifestPath = path.resolve(options.manifestPath ?? path.join(".flowseeker", "replay-workspaces.json"));
205
+ return {
206
+ source: manifestPath,
207
+ kind: "Manifest",
208
+ manifest: await readJson(manifestPath)
209
+ };
210
+ }
211
+ async function loadCases(workspacePath, workspace) {
212
+ const cases = [...(workspace.cases ?? [])];
213
+ const shouldLoadFeedback = workspace.includeFeedback === true || cases.length === 0;
214
+ if (shouldLoadFeedback) {
215
+ const feedbackDir = workspace.feedbackDir ? resolveMaybeRelative(workspacePath, workspace.feedbackDir) : undefined;
216
+ const feedbackRecords = await (0, feedback_1.readFeedbackRecords)(workspacePath, feedbackDir);
217
+ cases.push(...feedbackRecords.map(({ record }) => replayCaseFromFeedback(record)));
218
+ }
219
+ return dedupeCases(cases).sort((left, right) => (left.createdAt ?? "").localeCompare(right.createdAt ?? "") || left.id.localeCompare(right.id));
220
+ }
221
+ function replayCaseFromFeedback(record) {
222
+ return {
223
+ id: `feedback-${record.id}`,
224
+ task: record.run.task,
225
+ createdAt: record.createdAt,
226
+ source: record.source,
227
+ notes: record.note,
228
+ feedbackKind: record.kind,
229
+ feedbackNote: record.note,
230
+ expectedPaths: record.labels?.expectedPaths,
231
+ avoidPaths: record.labels?.avoidPaths,
232
+ passAtK: record.labels?.passAtK,
233
+ expectedMode: record.labels?.expectedMode,
234
+ originalTopFiles: record.run.topFiles?.map((f) => ({
235
+ relativePath: f.relativePath,
236
+ role: f.role,
237
+ score: f.score,
238
+ evidence: f.evidence
239
+ })),
240
+ outcome: record.outcome
241
+ };
242
+ }
243
+ function filterCases(cases, caseId) {
244
+ if (!caseId) {
245
+ return cases;
246
+ }
247
+ return cases.filter((caseDef) => caseDef.id === caseId);
248
+ }
249
+ function evaluateCase(workspaceName, workspacePath, caseDef, result, durationMs) {
250
+ const passAtK = caseDef.passAtK ?? 10;
251
+ const expectedMetrics = (0, evaluationMetrics_1.computeExpectedPathMetrics)(result.units, caseDef.expectedPaths ?? [], passAtK, caseDef.expectedMode ?? "any");
252
+ const avoidHitsTop10 = findAvoidHits(result.units.slice(0, 10), caseDef.avoidPaths ?? []);
253
+ const contextGapReported = caseDef.feedbackKind === "missing_file" || caseDef.feedbackKind === "agent_needed_more_context" || caseDef.outcome?.aiNeededMoreContext === true;
254
+ const positiveFeedback = caseDef.feedbackKind === "relevant" || caseDef.outcome?.planAccepted === true || caseDef.outcome?.fixVerified === true;
255
+ const negativeFeedback = caseDef.feedbackKind === "not_relevant" || contextGapReported;
256
+ return {
257
+ workspaceName,
258
+ workspacePath,
259
+ caseDef,
260
+ result,
261
+ durationMs,
262
+ expectedMetrics,
263
+ pass: expectedMetrics.pass,
264
+ avoidHitsTop10,
265
+ contextGapReported,
266
+ positiveFeedback,
267
+ negativeFeedback
268
+ };
269
+ }
270
+ function findAvoidHits(units, avoidPaths) {
271
+ if (avoidPaths.length === 0) {
272
+ return [];
273
+ }
274
+ return uniqueStrings(units
275
+ .filter((unit) => avoidPaths.some((avoidPath) => (0, evaluationMetrics_1.pathMatches)(unit.relativePath, avoidPath)))
276
+ .filter((unit) => !unit.contrastContext)
277
+ .map((unit) => unit.relativePath));
278
+ }
279
+ function renderReport(manifest, results, durationMs) {
280
+ const lines = [
281
+ "# FlowSeeker Real-World Replay Report",
282
+ "",
283
+ `Generated: ${new Date().toISOString()}`,
284
+ `Replay: ${manifest.name ?? "Unnamed replay"}`,
285
+ `Workspaces: ${new Set(results.map((result) => result.workspaceName)).size}`,
286
+ `Cases: ${results.length}`,
287
+ `Duration: ${(durationMs / 1000).toFixed(2)}s`,
288
+ "",
289
+ "## Summary",
290
+ "",
291
+ formatSummary(results),
292
+ formatTokenSavingsSummary(results),
293
+ "",
294
+ "## How To Read This",
295
+ "",
296
+ "- `Context gap reported` comes from human/agent feedback, not from FlowSeeker guessing.",
297
+ "- `Expected pass` is only available when a case has expected paths.",
298
+ "- Token savings are measured with the same local tokenizer/baseline used by FlowSeeker packets.",
299
+ "",
300
+ "## Workspace Summary",
301
+ "",
302
+ ...renderWorkspaceSummary(results),
303
+ "",
304
+ "## Cases",
305
+ ""
306
+ ];
307
+ for (const result of results) {
308
+ lines.push(...renderCase(result));
309
+ }
310
+ return `${lines.join("\n")}\n`;
311
+ }
312
+ function renderWorkspaceSummary(results) {
313
+ const byWorkspace = new Map();
314
+ for (const result of results) {
315
+ byWorkspace.set(result.workspaceName, [...(byWorkspace.get(result.workspaceName) ?? []), result]);
316
+ }
317
+ return Array.from(byWorkspace.entries()).map(([workspaceName, workspaceResults]) => `- ${workspaceName}: ${formatSummary(workspaceResults)}; ${formatTokenSavingsSummary(workspaceResults)}`);
318
+ }
319
+ function renderCase(result) {
320
+ const status = result.pass === "unlabeled" ? "UNLABELED" : result.pass ? "PASS" : "FAIL";
321
+ const topFiles = (0, fileGroups_1.aggregateEvidenceFiles)(result.result.units).slice(0, 15);
322
+ const stats = result.result.stats;
323
+ return [
324
+ `### ${status} - ${result.workspaceName}/${result.caseDef.id}`,
325
+ "",
326
+ `Workspace: ${result.workspacePath}`,
327
+ `Task: ${result.caseDef.task}`,
328
+ ...(result.caseDef.createdAt ? [`Original feedback/task time: ${result.caseDef.createdAt}`] : []),
329
+ ...(result.caseDef.source ? [`Source: ${result.caseDef.source}`] : []),
330
+ ...(result.caseDef.notes ? [`Notes: ${result.caseDef.notes}`] : []),
331
+ ...(result.caseDef.feedbackKind ? [`Feedback: ${result.caseDef.feedbackKind}${result.caseDef.feedbackNote ? ` - ${result.caseDef.feedbackNote}` : ""}`] : []),
332
+ `Context gap reported: ${yesNo(result.contextGapReported)}`,
333
+ `Positive feedback: ${yesNo(result.positiveFeedback)}`,
334
+ `Intent: ${result.result.profile.intent}`,
335
+ `Keywords: ${result.result.profile.keywords.join(", ") || "none"}`,
336
+ `Expected paths: ${(result.caseDef.expectedPaths ?? []).join(", ") || "none"}`,
337
+ `Expected mode: ${result.caseDef.expectedMode ?? "any"}`,
338
+ `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}`,
339
+ `Missing expected at 10: ${result.expectedMetrics.missingAt10.join(", ") || "none"}`,
340
+ `Avoid hits in top 10: ${result.avoidHitsTop10.join(", ") || "none"}`,
341
+ `Token savings: ${formatCaseTokenSavings(result)}`,
342
+ `Context coverage: ${formatContextCoverage(result.result)}`,
343
+ `Duration: ${(result.durationMs / 1000).toFixed(2)}s`,
344
+ `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})` : ""}`,
345
+ "",
346
+ "Top files:",
347
+ "",
348
+ ...topFiles.map((group, index) => `${index + 1}. ${group.relativePath} [${group.role}/${group.slot}] score=${group.score.toFixed(1)} evidence=${group.unitCount} subsystem=${group.subsystem ?? "none"}`),
349
+ ...(result.caseDef.originalTopFiles && result.caseDef.originalTopFiles.length > 0
350
+ ? [
351
+ "",
352
+ "Original top files (from feedback snapshot):",
353
+ "",
354
+ ...result.caseDef.originalTopFiles.map((f, index) => `${index + 1}. ${f.relativePath} [${f.role}] score=${f.score.toFixed(1)} evidence=${f.evidence}`)
355
+ ]
356
+ : []),
357
+ ""
358
+ ];
359
+ }
360
+ function formatSummary(results) {
361
+ const labeled = results.filter((result) => result.pass !== "unlabeled");
362
+ const passed = labeled.filter((result) => result.pass === true);
363
+ const feedbackCases = results.filter((result) => result.caseDef.feedbackKind || result.caseDef.outcome);
364
+ const positive = feedbackCases.filter((result) => result.positiveFeedback).length;
365
+ const negative = feedbackCases.filter((result) => result.negativeFeedback).length;
366
+ const contextGaps = feedbackCases.filter((result) => result.contextGapReported).length;
367
+ const avoidCases = results.filter((result) => (result.caseDef.avoidPaths ?? []).length > 0).length;
368
+ const avoidHitCases = results.filter((result) => result.avoidHitsTop10.length > 0).length;
369
+ const avgRequiredCoverage = average(results.map((result) => result.result.contextCoverage?.requiredCoveragePercent ?? 0));
370
+ const avgDuration = average(results.map((result) => result.durationMs));
371
+ return `cases=${results.length}, labeled=${labeled.length}, expectedPass=${passed.length}/${labeled.length}, feedbackCases=${feedbackCases.length}, positiveFeedback=${positive}/${feedbackCases.length}, negativeFeedback=${negative}/${feedbackCases.length}, contextGapReported=${contextGaps}/${feedbackCases.length}, avoidHitCases=${avoidHitCases}/${avoidCases}, requiredCoverageAvg=${avgRequiredCoverage.toFixed(1)}%, avg=${(avgDuration / 1000).toFixed(2)}s`;
372
+ }
373
+ function formatTokenSavingsSummary(results) {
374
+ const metrics = results.map((result) => result.result.tokenSavings).filter((item) => item !== undefined && item.status !== "unavailable");
375
+ if (metrics.length === 0) {
376
+ return "tokenSavings=unavailable";
377
+ }
378
+ const avgReduction = average(metrics.map((item) => item.reductionPercent));
379
+ const avgPacketTokens = average(metrics.map((item) => item.solvePacketTokensEstimate));
380
+ const avgWorkspaceTokens = average(metrics.map((item) => item.workspaceTokensEstimate));
381
+ const partial = metrics.filter((item) => item.status === "partial").length;
382
+ const proofPartial = metrics.filter((item) => item.proofStatus !== "complete").length;
383
+ return `tokenSavings avg=${(0, tokenSavings_1.formatReductionPercent)(avgReduction)}, packetAvg=${(0, tokenSavings_1.formatTokenCount)(avgPacketTokens)}, workspaceAvg=${(0, tokenSavings_1.formatTokenCount)(avgWorkspaceTokens)}, partial=${partial}/${metrics.length}, proofNotComplete=${proofPartial}/${metrics.length}`;
384
+ }
385
+ function formatCaseConsole(result) {
386
+ const status = result.pass === "unlabeled" ? "UNLABELED" : result.pass ? "PASS" : "FAIL";
387
+ const gap = result.contextGapReported ? "context gap reported" : "no reported gap";
388
+ return `${status}; ${gap}; ${formatCaseTokenSavings(result)}; ${formatContextCoverage(result.result)}; ${(result.durationMs / 1000).toFixed(2)}s`;
389
+ }
390
+ function formatCaseTokenSavings(result) {
391
+ const metrics = result.result.tokenSavings;
392
+ if (!metrics || metrics.status === "unavailable") {
393
+ return "tokens unavailable";
394
+ }
395
+ const warning = metrics.proofWarnings.length > 0 ? `; warnings=${metrics.proofWarnings.join(" | ")}` : "";
396
+ return `tokens ${(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}${warning}`;
397
+ }
398
+ function formatContextCoverage(result) {
399
+ const coverage = result.contextCoverage;
400
+ if (!coverage) {
401
+ return "coverage unavailable";
402
+ }
403
+ const missing = coverage.missingRequiredSlots.length > 0 ? ` missing=${coverage.missingRequiredSlots.join("|")}` : "";
404
+ return `coverage ${coverage.foundRequiredSlots.length}/${coverage.requiredSlots.length} (${coverage.requiredCoveragePercent.toFixed(0)}%)${missing}`;
405
+ }
406
+ function validateManifest(manifest, manifestPath) {
407
+ if (!Array.isArray(manifest.workspaces) || manifest.workspaces.length === 0) {
408
+ throw new Error(`Invalid replay manifest ${manifestPath}: workspaces must be a non-empty array.`);
409
+ }
410
+ manifest.workspaces.forEach((workspace, index) => {
411
+ if (!workspace.path) {
412
+ throw new Error(`Invalid replay manifest ${manifestPath}: workspaces[${index}].path is required.`);
413
+ }
414
+ });
415
+ }
416
+ async function readJson(filePath) {
417
+ const text = await fs.readFile(filePath, "utf8");
418
+ return JSON.parse(text);
419
+ }
420
+ function dedupeCases(cases) {
421
+ const byKey = new Map();
422
+ for (const caseDef of cases) {
423
+ const key = caseDef.id || slugify(caseDef.task);
424
+ byKey.set(key, { ...caseDef, id: key });
425
+ }
426
+ return Array.from(byKey.values());
427
+ }
428
+ function resolveMaybeRelative(workspacePath, value) {
429
+ return path.isAbsolute(value) ? value : path.resolve(workspacePath, value);
430
+ }
431
+ function requireValue(args, index, flag) {
432
+ const value = args[index + 1];
433
+ if (!value || value.startsWith("-")) {
434
+ throw new Error(`${flag} requires a value.`);
435
+ }
436
+ return value.replace(/\^/g, "");
437
+ }
438
+ function slugify(value) {
439
+ const slug = (0, text_1.normalizeText)(value)
440
+ .replace(/[^a-z0-9]+/g, "-")
441
+ .replace(/^-+|-+$/g, "")
442
+ .slice(0, 72);
443
+ return slug || "replay-task";
444
+ }
445
+ function printUsage() {
446
+ console.log([
447
+ "Usage:",
448
+ " node dist/cli/runReplay.js --manifest .flowseeker/replay-workspaces.json",
449
+ " node dist/cli/runReplay.js --workspace D:/repo",
450
+ " node dist/cli/runReplay.js --workspace D:/repo --task \"Fix timestamp based on browser timezone\"",
451
+ "",
452
+ "Options:",
453
+ " --manifest, -m Path to a real-world replay manifest.",
454
+ " --workspace, -w Run one workspace. Without --task, loads .flowseeker/feedback.",
455
+ " --task, -t Natural-language task for ad-hoc replay mode.",
456
+ " --feedback-dir Override feedback directory for workspace replay.",
457
+ " --case-id Filter to one replay case id.",
458
+ " --report, -r Override report output path.",
459
+ " --fail-on-gap Exit with code 1 if feedback reports missing context.",
460
+ " --fail-on-miss Exit with code 1 if labeled expected paths miss pass@K.",
461
+ " --verbose, -v Print scan progress.",
462
+ ""
463
+ ].join("\n"));
464
+ }
465
+ function defaultReportPath() {
466
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
467
+ return path.join(".flowseeker", "reports", `real-world-replay-${timestamp}.md`);
468
+ }
469
+ function yesNo(value) {
470
+ return value ? "yes" : "no";
471
+ }
472
+ function uniqueStrings(values) {
473
+ return Array.from(new Set(values));
474
+ }
475
+ function average(values) {
476
+ if (values.length === 0) {
477
+ return 0;
478
+ }
479
+ return values.reduce((sum, value) => sum + value, 0) / values.length;
480
+ }
481
+ //# sourceMappingURL=runReplay.js.map
@@ -0,0 +1,149 @@
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.checkHostCompatibility = checkHostCompatibility;
37
+ const vscode = __importStar(require("vscode"));
38
+ const approvalPolicy_1 = require("../agent/approvalPolicy");
39
+ const capabilities_1 = require("../runtime/capabilities");
40
+ const hostDetect_1 = require("../runtime/hostDetect");
41
+ const hostTier_1 = require("../runtime/hostTier");
42
+ const mcpConfig_1 = require("../mcp/mcpConfig");
43
+ async function checkHostCompatibility(context) {
44
+ const host = (0, hostDetect_1.detectHost)();
45
+ const capabilities = (0, capabilities_1.getHostCapabilities)(context);
46
+ const probe = await (0, hostDetect_1.probeLanguageModels)(capabilities);
47
+ const tier = (0, hostTier_1.getHostTier)();
48
+ const mcpServers = await (0, mcpConfig_1.loadMcpServerConfigs)();
49
+ const policy = (0, approvalPolicy_1.getApprovalPolicy)();
50
+ const existingVerification = (0, hostTier_1.getVerificationForHost)(context, host.id, host.version);
51
+ const lines = [
52
+ "# FlowSeeker Host Compatibility",
53
+ "",
54
+ "## Host Identity",
55
+ "",
56
+ ...(0, hostDetect_1.summarizeProbe)(host, capabilities, probe).map((line) => `- ${line}`),
57
+ "",
58
+ "## Tier",
59
+ "",
60
+ `- **Tier:** ${(0, hostTier_1.tierLabel)(tier.tier)}`,
61
+ `- **Description:** ${(0, hostTier_1.tierDescription)(tier.tier)}`,
62
+ `- **Reason:** ${tier.reason}`,
63
+ "",
64
+ ...(existingVerification
65
+ ? [
66
+ `- **User verified:** ${existingVerification.nativeChatWorks ? "Native Chat works on this host" : "Native Chat does NOT work on this host"}`,
67
+ `- **Verified at:** ${existingVerification.verifiedAt}`,
68
+ ...(existingVerification.notes ? [`- **Notes:** ${existingVerification.notes}`] : []),
69
+ ""
70
+ ]
71
+ : tier.tier === "native-unverified"
72
+ ? [
73
+ "",
74
+ "> **Can you help verify?** Open your host's chat panel and type `@flowseeker /guide test`. Does the FlowSeeker participant appear and respond?",
75
+ ""
76
+ ]
77
+ : [""]),
78
+ "## Capabilities",
79
+ "",
80
+ ...(0, capabilities_1.summarizeHostCapabilities)(capabilities).map((line) => `- ${line}`),
81
+ "",
82
+ "## MCP Configuration",
83
+ "",
84
+ mcpServers.length > 0
85
+ ? `FlowSeeker found ${mcpServers.length} configured MCP server(s):`
86
+ : "FlowSeeker did not find any configured MCP servers.",
87
+ "",
88
+ ...mcpServers.map((server) => `- ${server.enabled === false ? "[disabled] " : ""}${server.name} (${server.type})`),
89
+ "",
90
+ "## Agent Approval Policy",
91
+ "",
92
+ `- Read workspace: ${enabled(policy.readWorkspace)}`,
93
+ `- Edit workspace: ${enabled(policy.editWorkspace)}`,
94
+ `- Safe commands: ${enabled(policy.safeCommands)}`,
95
+ `- All commands: ${enabled(policy.allCommands)}`,
96
+ `- MCP tools: ${enabled(policy.mcpTools)}`,
97
+ `- Rules: ${policy.rules.length}`,
98
+ "",
99
+ "## Recommended Fallbacks",
100
+ "",
101
+ ...tierFallbacks(tier.tier)
102
+ ];
103
+ const document = await vscode.workspace.openTextDocument({
104
+ content: lines.join("\n"),
105
+ language: "markdown"
106
+ });
107
+ await vscode.window.showTextDocument(document, { preview: false });
108
+ // Human-in-the-loop verification for unverified hosts
109
+ if (tier.tier === "native-unverified" && !existingVerification) {
110
+ const answer = await vscode.window.showInformationMessage(`FlowSeeker detected "${host.appName}" — a host that may support Native Chat but hasn't been verified. Does @flowseeker /guide work in your chat panel?`, { modal: false }, "Yes, it works", "No, it doesn't", "Skip");
111
+ if (answer === "Yes, it works" || answer === "No, it doesn't") {
112
+ (0, hostTier_1.saveHostVerification)(context, {
113
+ hostId: host.id,
114
+ hostVersion: host.version,
115
+ nativeChatWorks: answer === "Yes, it works",
116
+ verifiedAt: new Date().toISOString()
117
+ });
118
+ }
119
+ }
120
+ }
121
+ function tierFallbacks(tier) {
122
+ switch (tier) {
123
+ case "native-full":
124
+ return [
125
+ "- Native Chat is your primary interface. Sidebar is available as a secondary option.",
126
+ "- If Native Chat is ever unavailable, the sidebar chat and Copy Agent Prompt will still work."
127
+ ];
128
+ case "native-unverified":
129
+ return [
130
+ "- **Primary (guaranteed):** Use the FlowSeeker sidebar chat for all commands.",
131
+ "- **Copy Agent Prompt:** Copy context and paste into Cursor Composer, Antigravity Agent, or any AI tool.",
132
+ "- **Native Chat:** May work — try `@flowseeker /guide` in your host's chat panel.",
133
+ "- If Language Model API returns 0 models, configure a direct provider key in the sidebar."
134
+ ];
135
+ case "sidebar-primary":
136
+ return [
137
+ "- **Primary:** Use the FlowSeeker sidebar chat.",
138
+ "- **Copy Agent Prompt:** Copy the Solve Packet and paste into any AI tool.",
139
+ "- **Direct Provider:** Configure an API key (OpenAI, Anthropic, Gemini, etc.) for AI-assisted guidance.",
140
+ "- Native Chat is not available on this host."
141
+ ];
142
+ default:
143
+ return [];
144
+ }
145
+ }
146
+ function enabled(value) {
147
+ return value ? "auto-approved" : "requires approval";
148
+ }
149
+ //# sourceMappingURL=checkHostCompatibility.js.map
@@ -0,0 +1,52 @@
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.copyAgentPrompt = copyAgentPrompt;
37
+ const vscode = __importStar(require("vscode"));
38
+ const agentPrompt_1 = require("../pipeline/agentPrompt");
39
+ const logger_1 = require("../utils/logger");
40
+ async function copyAgentPrompt(provider) {
41
+ const result = provider.getResult();
42
+ if (!result) {
43
+ vscode.window.showWarningMessage("Run FlowSeeker: Find Relevant Context first.");
44
+ return;
45
+ }
46
+ const selectedUnits = provider.getSelectedUnits();
47
+ const prompt = (0, agentPrompt_1.createAgentSolvePrompt)(result, selectedUnits);
48
+ await vscode.env.clipboard.writeText(prompt);
49
+ (0, logger_1.logInfo)(`Copied agent solve prompt with ${selectedUnits.length} selected evidence units.`);
50
+ vscode.window.showInformationMessage("Copied FlowSeeker agent solve prompt.");
51
+ }
52
+ //# sourceMappingURL=copyAgentPrompt.js.map