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,109 @@
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.registerFlowSeekerMcpProvider = registerFlowSeekerMcpProvider;
37
+ const vscode = __importStar(require("vscode"));
38
+ const capabilities_1 = require("../runtime/capabilities");
39
+ const mcpConfig_1 = require("./mcpConfig");
40
+ const logger_1 = require("../utils/logger");
41
+ function registerFlowSeekerMcpProvider(context) {
42
+ const capabilities = (0, capabilities_1.getHostCapabilities)(context);
43
+ if (!capabilities.hasMcp || typeof vscode.lm?.registerMcpServerDefinitionProvider !== "function") {
44
+ (0, logger_1.logInfo)("MCP provider API is unavailable in this host. FlowSeeker MCP registration skipped.");
45
+ return undefined;
46
+ }
47
+ const disposable = vscode.lm.registerMcpServerDefinitionProvider("flowseeker", {
48
+ async provideMcpServerDefinitions() {
49
+ // Always expose FlowSeeker's own bundled MCP server first so the host can
50
+ // call it with zero manual config. User-defined servers are added on top.
51
+ const bundled = bundledFlowSeekerServer(context);
52
+ const configs = await (0, mcpConfig_1.loadMcpServerConfigs)();
53
+ const userServers = configs
54
+ .filter((server) => server.enabled !== false)
55
+ .filter((server) => server.name.toLowerCase() !== "flowseeker")
56
+ .flatMap(toMcpDefinition);
57
+ return bundled ? [bundled, ...userServers] : userServers;
58
+ },
59
+ resolveMcpServerDefinition(server) {
60
+ return server;
61
+ }
62
+ });
63
+ (0, logger_1.logInfo)("FlowSeeker MCP server definition provider registered (bundled server auto-exposed).");
64
+ return disposable;
65
+ }
66
+ function bundledFlowSeekerServer(context) {
67
+ try {
68
+ const serverPath = vscode.Uri.joinPath(context.extensionUri, "dist", "cli", "mcpServer.js").fsPath;
69
+ const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
70
+ const args = [serverPath];
71
+ if (workspaceFolder) {
72
+ args.push("--workspace", workspaceFolder);
73
+ }
74
+ const definition = new vscode.McpStdioServerDefinition("flowseeker", process.execPath, args, { ELECTRON_RUN_AS_NODE: "1" });
75
+ if (workspaceFolder) {
76
+ definition.cwd = vscode.Uri.file(workspaceFolder);
77
+ }
78
+ return definition;
79
+ }
80
+ catch (error) {
81
+ (0, logger_1.logError)("Unable to create bundled FlowSeeker MCP server definition.", error);
82
+ return undefined;
83
+ }
84
+ }
85
+ function toMcpDefinition(server) {
86
+ try {
87
+ if (server.type === "http") {
88
+ if (!server.url) {
89
+ return [];
90
+ }
91
+ return [
92
+ new vscode.McpHttpServerDefinition(server.name, vscode.Uri.parse(server.url), server.headers, server.version)
93
+ ];
94
+ }
95
+ if (!server.command) {
96
+ return [];
97
+ }
98
+ const definition = new vscode.McpStdioServerDefinition(server.name, server.command, server.args ?? [], server.env ?? {}, server.version);
99
+ if (server.cwd) {
100
+ definition.cwd = vscode.Uri.file(server.cwd);
101
+ }
102
+ return [definition];
103
+ }
104
+ catch (error) {
105
+ (0, logger_1.logError)(`Unable to create MCP definition for ${server.name}.`, error);
106
+ return [];
107
+ }
108
+ }
109
+ //# sourceMappingURL=mcpProvider.js.map
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ /**
3
+ * FlowSeeker MCP Tool Definitions and Handlers.
4
+ *
5
+ * Exposes FlowSeeker retrieval pipeline as MCP tools for use in:
6
+ * - Cursor, Antigravity, Windsurf, Claude Desktop
7
+ * - Any MCP-compliant AI client
8
+ *
9
+ * Tools run the headless pipeline (no VS Code dependency) and return structured results.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MCP_PROMPT_DEFINITIONS = exports.TOOL_DEFINITIONS = void 0;
13
+ exports.handleToolCall = handleToolCall;
14
+ const loadConfigFromPath_1 = require("../config/loadConfigFromPath");
15
+ const defaultConfig_1 = require("../config/defaultConfig");
16
+ const runHeadless_1 = require("../pipeline/runHeadless");
17
+ const solvePacket_1 = require("../pipeline/solvePacket");
18
+ const agentPromptHeadless_1 = require("../pipeline/agentPromptHeadless");
19
+ const fileGroups_1 = require("../pipeline/fileGroups");
20
+ const tokenSavings_1 = require("../pipeline/tokenSavings");
21
+ exports.TOOL_DEFINITIONS = [
22
+ {
23
+ name: "flowseeker_retrieve",
24
+ description: "Find relevant code context and return a full Solve Packet. Includes ranked files, context coverage, and token savings before code edits.",
25
+ inputSchema: {
26
+ type: "object",
27
+ properties: {
28
+ task: {
29
+ type: "string",
30
+ description: "Natural-language task, bug, or feature to find code context for."
31
+ },
32
+ workspace: {
33
+ type: "string",
34
+ description: "Workspace root path. Use an absolute path if the IDE does not resolve cwd correctly."
35
+ },
36
+ maxFiles: {
37
+ type: "number",
38
+ description: "Maximum files to scan. Default: 5000."
39
+ }
40
+ },
41
+ required: ["task"]
42
+ }
43
+ },
44
+ {
45
+ name: "flowseeker_guide",
46
+ description: "Create an agent guidance prompt from relevant code context. Includes edit candidates, file context, and suggested verification steps.",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ task: {
51
+ type: "string",
52
+ description: "Natural-language codebase task to prepare agent guidance for."
53
+ },
54
+ workspace: {
55
+ type: "string",
56
+ description: "Workspace root path. Use an absolute path if the IDE does not resolve cwd correctly."
57
+ }
58
+ },
59
+ required: ["task"]
60
+ }
61
+ },
62
+ {
63
+ name: "flowseeker_files",
64
+ description: "List top ranked files for a task. Lightweight result for quickly finding where to inspect or edit.",
65
+ inputSchema: {
66
+ type: "object",
67
+ properties: {
68
+ task: {
69
+ type: "string",
70
+ description: "Natural-language codebase task to find relevant files for."
71
+ },
72
+ workspace: {
73
+ type: "string",
74
+ description: "Workspace root path. Use an absolute path if the IDE does not resolve cwd correctly."
75
+ },
76
+ limit: {
77
+ type: "number",
78
+ description: "Maximum number of files to return. Default: 15."
79
+ }
80
+ },
81
+ required: ["task"]
82
+ }
83
+ }
84
+ ];
85
+ exports.MCP_PROMPT_DEFINITIONS = [
86
+ {
87
+ name: "retrieve",
88
+ description: "Find relevant code context and return a full Solve Packet.",
89
+ toolName: "flowseeker_retrieve",
90
+ toolPurpose: "return a full Solve Packet with ranked files, context coverage, and token savings",
91
+ arguments: [
92
+ { name: "task", description: "Task, bug, or feature to analyze.", required: true },
93
+ { name: "workspace", description: "Optional workspace root path." }
94
+ ]
95
+ },
96
+ {
97
+ name: "guide",
98
+ description: "Create an agent guidance prompt from relevant code context.",
99
+ toolName: "flowseeker_guide",
100
+ toolPurpose: "return an agent guidance prompt with relevant files, edit candidates, and verification steps",
101
+ arguments: [
102
+ { name: "task", description: "Task, bug, or feature to prepare guidance for.", required: true },
103
+ { name: "workspace", description: "Optional workspace root path." }
104
+ ]
105
+ },
106
+ {
107
+ name: "files",
108
+ description: "List top ranked files for a task.",
109
+ toolName: "flowseeker_files",
110
+ toolPurpose: "return a lightweight top-file list for quick inspection",
111
+ arguments: [
112
+ { name: "task", description: "Task, bug, or feature to find files for.", required: true },
113
+ { name: "workspace", description: "Optional workspace root path." },
114
+ { name: "limit", description: "Optional maximum number of files to return." }
115
+ ]
116
+ }
117
+ ];
118
+ async function handleToolCall(toolName, input, defaultWorkspace) {
119
+ const workspace = input.workspace ?? defaultWorkspace;
120
+ const task = input.task?.trim();
121
+ if (!task) {
122
+ return errorResult("A task description is required.");
123
+ }
124
+ try {
125
+ switch (toolName) {
126
+ case "flowseeker_retrieve":
127
+ return await handleRetrieve(task, workspace, input.maxFiles);
128
+ case "flowseeker_guide":
129
+ return await handleGuide(task, workspace);
130
+ case "flowseeker_files":
131
+ return await handleFiles(task, workspace, input.limit);
132
+ default:
133
+ return errorResult(`Unknown tool: ${toolName}`);
134
+ }
135
+ }
136
+ catch (error) {
137
+ const message = error instanceof Error ? error.message : String(error);
138
+ return errorResult(`FlowSeeker failed: ${message}`);
139
+ }
140
+ }
141
+ // ── Individual Handlers ───────────────────────────────────────────────
142
+ async function handleRetrieve(task, workspace, maxFiles) {
143
+ const result = await runPipeline(task, workspace, maxFiles);
144
+ const packet = result.solvePacket
145
+ ? (0, solvePacket_1.renderSolvePacketMarkdown)(result.solvePacket)
146
+ : result.contextPack;
147
+ const summary = formatResultSummary(result);
148
+ return textResult(`${summary}\n\n${packet}`);
149
+ }
150
+ async function handleGuide(task, workspace) {
151
+ const result = await runPipeline(task, workspace);
152
+ const prompt = (0, agentPromptHeadless_1.createAgentSolvePromptHeadless)(result);
153
+ const summary = formatResultSummary(result);
154
+ return textResult(`${summary}\n\n${prompt}`);
155
+ }
156
+ async function handleFiles(task, workspace, limit) {
157
+ const result = await runPipeline(task, workspace);
158
+ const groups = (0, fileGroups_1.aggregateEvidenceFiles)(result.units).slice(0, limit ?? 15);
159
+ const lines = [
160
+ `# FlowSeeker File Results`,
161
+ ``,
162
+ `Task: ${task}`,
163
+ `Intent: ${result.profile.intent}`,
164
+ `Keywords: ${result.profile.keywords.join(", ") || "none"}`,
165
+ `Scanned: ${result.stats.scannedFiles} files`,
166
+ `Evidence: ${result.units.length} units`,
167
+ ``,
168
+ `## Top Files`,
169
+ ``
170
+ ];
171
+ for (const [index, group] of groups.entries()) {
172
+ const ranges = group.ranges
173
+ .slice(0, 3)
174
+ .map((r) => `${r.startLine}-${r.endLine}`)
175
+ .join(", ");
176
+ lines.push(`${index + 1}. **${group.relativePath}**${ranges ? ` (lines: ${ranges})` : ""}`, ` Role: ${group.role} | Slot: ${group.slot ?? "unknown"} | Score: ${group.score.toFixed(1)} | Evidence: ${group.unitCount}`, ``);
177
+ }
178
+ return textResult(lines.join("\n"));
179
+ }
180
+ // ── Helpers ───────────────────────────────────────────────────────────
181
+ async function runPipeline(task, workspace, maxFiles) {
182
+ const baseConfig = await (0, loadConfigFromPath_1.loadConfigFromPath)(workspace);
183
+ const config = maxFiles && maxFiles > 0
184
+ ? (0, defaultConfig_1.mergeConfig)(baseConfig, { pipeline: { ...baseConfig.pipeline, maxFiles } })
185
+ : baseConfig;
186
+ return (0, runHeadless_1.runFlowSeekerHeadless)(workspace, task, config, {
187
+ onStage: (stage, detail) => {
188
+ // MCP servers communicate via stdio; progress goes to stderr
189
+ process.stderr.write(`[FlowSeeker] ${stage}${detail ? `: ${detail}` : ""}\n`);
190
+ }
191
+ });
192
+ }
193
+ function formatResultSummary(result) {
194
+ const parts = [
195
+ `FlowSeeker retrieved **${result.units.length}** evidence unit(s) from **${result.stats.scannedFiles}** scanned file(s).`,
196
+ `Intent: \`${result.profile.intent}\``,
197
+ `Keywords: ${result.profile.keywords.map((k) => `\`${k}\``).join(", ") || "none"}`
198
+ ];
199
+ const ts = result.tokenSavings;
200
+ if (ts && ts.status !== "unavailable") {
201
+ parts.push(`Token savings: Solve Packet **${(0, tokenSavings_1.formatTokenCount)(ts.solvePacketTokensEstimate)}** / workspace **${(0, tokenSavings_1.formatTokenCount)(ts.workspaceTokensEstimate)}** tokens (**${(0, tokenSavings_1.formatReductionPercent)(ts.reductionPercent)}** reduction).`);
202
+ }
203
+ const cc = result.contextCoverage;
204
+ if (cc) {
205
+ parts.push(`Context coverage: **${cc.foundRequiredSlots.length}/${cc.requiredSlots.length}** required slot(s) found${cc.missingRequiredSlots.length ? `; missing: ${cc.missingRequiredSlots.join(", ")}` : ""}.`);
206
+ }
207
+ return parts.join("\n");
208
+ }
209
+ function textResult(text) {
210
+ return { content: [{ type: "text", text }] };
211
+ }
212
+ function errorResult(message) {
213
+ return { content: [{ type: "text", text: message }], isError: true };
214
+ }
215
+ //# sourceMappingURL=mcpTools.js.map
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAgentSolvePrompt = createAgentSolvePrompt;
4
+ const fileGroups_1 = require("./fileGroups");
5
+ function createAgentSolvePrompt(result, selectedUnits) {
6
+ const units = (0, fileGroups_1.selectDiverseEvidenceUnits)(selectedUnits.length > 0 ? selectedUnits : result.units, 2);
7
+ const editCandidates = units.filter((unit) => unit.role === "edit_candidate");
8
+ const readContext = units.filter((unit) => unit.role === "read_context" || unit.role === "impact" || unit.role === "verify");
9
+ const tests = units.filter((unit) => unit.role === "test");
10
+ const fileGroups = (0, fileGroups_1.aggregateEvidenceFiles)(selectedUnits.length > 0 ? selectedUnits : result.units);
11
+ const primaryEditFiles = fileGroups.filter((group) => group.role === "edit_candidate").slice(0, 8);
12
+ const readOnlyFiles = fileGroups.filter((group) => group.role !== "edit_candidate").slice(0, 12);
13
+ const allowedFiles = primaryEditFiles.map((group) => group.relativePath);
14
+ return [
15
+ "# FlowSeeker Agent Solve Prompt",
16
+ "",
17
+ "You are working inside a large codebase. Use the evidence below to solve the task with minimal additional context.",
18
+ "",
19
+ "## Task",
20
+ result.task,
21
+ "",
22
+ "## Retrieval Strategy",
23
+ `Intent: ${result.profile.intent}`,
24
+ `Strategies: ${result.profile.strategies.join(", ")}`,
25
+ `Keywords: ${result.profile.keywords.join(", ")}`,
26
+ "",
27
+ "## Guardrails",
28
+ "- Prefer editing only files listed in Allowed Edit Files.",
29
+ "- If the correct fix clearly requires another file, explain why before expanding scope.",
30
+ "- Use Read/Impact evidence to understand behavior, not as default edit targets.",
31
+ "- Update or add tests when a test evidence file is relevant.",
32
+ "- After edits, run the narrowest relevant checks first.",
33
+ "",
34
+ "## Allowed Edit Files",
35
+ allowedFiles.length > 0 ? allowedFiles.map((file) => `- ${file}`).join("\n") : "- None identified. Ask for more retrieval before editing.",
36
+ "",
37
+ "## File Scope",
38
+ renderFileScope(primaryEditFiles, readOnlyFiles),
39
+ "",
40
+ "## Edit Candidates",
41
+ renderUnits(editCandidates),
42
+ "",
43
+ "## Read / Impact Context",
44
+ renderUnits(readContext),
45
+ "",
46
+ "## Tests / Verification",
47
+ renderUnits(tests),
48
+ "",
49
+ "## Expected Agent Workflow",
50
+ "1. Read the edit candidates and relevant context snippets.",
51
+ "2. Identify the current behavior and target behavior from retrieval passes.",
52
+ "3. Apply the smallest coherent patch within Allowed Edit Files.",
53
+ "4. Update tests if the behavior changes.",
54
+ "5. Run focused checks and summarize changed files plus remaining risk.",
55
+ ""
56
+ ].join("\n");
57
+ }
58
+ function renderUnits(units) {
59
+ if (units.length === 0) {
60
+ return "- None";
61
+ }
62
+ return units
63
+ .map((unit) => {
64
+ const range = unit.range ? `:${unit.range.startLine}-${unit.range.endLine}` : "";
65
+ const passes = unit.retrievalPasses.length > 0 ? unit.retrievalPasses.join(", ") : "seed";
66
+ const reasons = unit.reasons.join("; ") || "ranked evidence";
67
+ const imports = unit.imports.length > 0 ? unit.imports.slice(0, 5).join(", ") : "none";
68
+ return [`- ${unit.relativePath}${range}`, ` Role: ${unit.role}; Kind: ${unit.kind}; Score: ${unit.score.toFixed(1)}; Passes: ${passes}`, ` Imports: ${imports}`, ` Reasons: ${reasons}`].join("\n");
69
+ })
70
+ .join("\n");
71
+ }
72
+ function renderFileScope(primaryEditFiles, readOnlyFiles) {
73
+ const lines = ["Primary edit files:"];
74
+ lines.push(...(primaryEditFiles.length > 0 ? primaryEditFiles.map((group) => `- ${group.relativePath} [${group.role}] score=${group.score.toFixed(1)} evidence=${group.unitCount}`) : ["- None"]));
75
+ lines.push("", "Read-only/context files:");
76
+ lines.push(...(readOnlyFiles.length > 0 ? readOnlyFiles.map((group) => `- ${group.relativePath} [${group.role}] score=${group.score.toFixed(1)} evidence=${group.unitCount}`) : ["- None"]));
77
+ return lines.join("\n");
78
+ }
79
+ //# sourceMappingURL=agentPrompt.js.map
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ /**
3
+ * Headless agent solve prompt — no VS Code dependency.
4
+ * Used by MCP server and CLI tools that run outside the extension host.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createAgentSolvePromptHeadless = createAgentSolvePromptHeadless;
8
+ const fileGroups_1 = require("./fileGroups");
9
+ const solvePacket_1 = require("./solvePacket");
10
+ const tokenSavings_1 = require("./tokenSavings");
11
+ function createAgentSolvePromptHeadless(result) {
12
+ const units = (0, fileGroups_1.selectDiverseEvidenceUnits)(result.units, 2);
13
+ const editCandidates = units.filter((unit) => unit.role === "edit_candidate");
14
+ const readContext = units.filter((unit) => unit.role === "read_context" || unit.role === "impact" || unit.role === "verify");
15
+ const tests = units.filter((unit) => unit.role === "test");
16
+ const fileGroups = (0, fileGroups_1.aggregateEvidenceFiles)(result.units);
17
+ const primaryEditFiles = fileGroups.filter((group) => group.role === "edit_candidate").slice(0, 8);
18
+ const readOnlyFiles = fileGroups.filter((group) => group.role !== "edit_candidate").slice(0, 12);
19
+ const allowedFiles = primaryEditFiles.map((group) => group.relativePath);
20
+ const packetSection = result.solvePacket
21
+ ? (0, solvePacket_1.renderSolvePacketMarkdown)(result.solvePacket)
22
+ : renderFallbackContextPack(result);
23
+ return [
24
+ "# FlowSeeker Agent Solve Prompt",
25
+ "",
26
+ "You are working inside a large codebase. FlowSeeker has retrieved a bounded context pack to reduce token usage.",
27
+ "Use the evidence below to solve the task with minimal additional context.",
28
+ "",
29
+ renderTokenSavingsHeadless(result),
30
+ "",
31
+ "## Task",
32
+ result.task,
33
+ "",
34
+ "## Retrieval Strategy",
35
+ `Intent: ${result.profile.intent}`,
36
+ `Strategies: ${result.profile.strategies.join(", ")}`,
37
+ `Keywords: ${result.profile.keywords.join(", ")}`,
38
+ "",
39
+ "## Guardrails",
40
+ "- Prefer editing only files listed in Allowed Edit Files.",
41
+ "- If the correct fix clearly requires another file, explain why before expanding scope.",
42
+ "- Use Read/Impact evidence to understand behavior, not as default edit targets.",
43
+ "- Update or add tests when a test evidence file is relevant.",
44
+ "- After edits, run the narrowest relevant checks first.",
45
+ "",
46
+ "## Allowed Edit Files",
47
+ allowedFiles.length > 0 ? allowedFiles.map((file) => `- ${file}`).join("\n") : "- None identified. Ask for more retrieval before editing.",
48
+ "",
49
+ "## File Scope",
50
+ renderFileScope(primaryEditFiles, readOnlyFiles),
51
+ "",
52
+ packetSection,
53
+ "",
54
+ "## Expected Agent Workflow",
55
+ "1. Read the edit candidates and relevant context snippets.",
56
+ "2. Identify the current behavior and target behavior from retrieval passes.",
57
+ "3. Apply the smallest coherent patch within Allowed Edit Files.",
58
+ "4. Update tests if the behavior changes.",
59
+ "5. Run focused checks and summarize changed files plus remaining risk.",
60
+ ""
61
+ ].join("\n");
62
+ }
63
+ function renderTokenSavingsHeadless(result) {
64
+ const metrics = result.tokenSavings;
65
+ if (!metrics || metrics.status === "unavailable") {
66
+ return "Token savings metrics are unavailable for this run.";
67
+ }
68
+ const basis = metrics.basis === "workspace_index" ? "workspace index" : "scanned candidate text";
69
+ return `Measured token savings: Solve Packet ${(0, tokenSavings_1.formatTokenCount)(metrics.solvePacketTokensEstimate)} tokens vs ${basis} ${(0, tokenSavings_1.formatTokenCount)(metrics.workspaceTokensEstimate)} tokens (${(0, tokenSavings_1.formatReductionPercent)(metrics.reductionPercent)} reduction).`;
70
+ }
71
+ function renderFallbackContextPack(result) {
72
+ return result.contextPack;
73
+ }
74
+ function renderFileScope(primaryEditFiles, readOnlyFiles) {
75
+ const lines = ["Primary edit files:"];
76
+ lines.push(...(primaryEditFiles.length > 0
77
+ ? primaryEditFiles.map((group) => `- ${group.relativePath} [${group.role}] score=${group.score.toFixed(1)} evidence=${group.unitCount}`)
78
+ : ["- None"]));
79
+ lines.push("", "Read-only/context files:");
80
+ lines.push(...(readOnlyFiles.length > 0
81
+ ? readOnlyFiles.map((group) => `- ${group.relativePath} [${group.role}] score=${group.score.toFixed(1)} evidence=${group.unitCount}`)
82
+ : ["- None"]));
83
+ return lines.join("\n");
84
+ }
85
+ //# sourceMappingURL=agentPromptHeadless.js.map