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,216 @@
|
|
|
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.universalScan = universalScan;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const vscode = __importStar(require("vscode"));
|
|
39
|
+
const text_1 = require("../utils/text");
|
|
40
|
+
const fileScanner_1 = require("./fileScanner");
|
|
41
|
+
const nodeScan_1 = require("./nodeScan");
|
|
42
|
+
async function universalScan(profile, config, options = {}) {
|
|
43
|
+
const folders = vscode.workspace.workspaceFolders;
|
|
44
|
+
if (!folders || folders.length === 0) {
|
|
45
|
+
return emptyScanStats(config);
|
|
46
|
+
}
|
|
47
|
+
if (config.index.enableWorkspaceIndex && folders[0].uri.scheme === "file") {
|
|
48
|
+
try {
|
|
49
|
+
return await (0, nodeScan_1.nodeScanWorkspace)(folders[0].uri.fsPath, profile, config, {
|
|
50
|
+
onProgress: (message) => options.progress?.report({ message }),
|
|
51
|
+
shouldCancel: () => Boolean(options.token?.isCancellationRequested)
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
options.progress?.report({ message: "Workspace index failed; falling back to VSCode scan." });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const startedAt = Date.now();
|
|
59
|
+
const maxBytes = config.pipeline.maxTotalBytesMb * 1024 * 1024;
|
|
60
|
+
const maxRawEvidence = Math.max(config.pipeline.maxCandidates, config.pipeline.maxRawEvidence);
|
|
61
|
+
let stopReason;
|
|
62
|
+
const excludeGlob = (0, text_1.toExcludeGlob)(config.project.exclude);
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
const uris = [];
|
|
65
|
+
for (const include of config.project.include) {
|
|
66
|
+
if (options.token?.isCancellationRequested) {
|
|
67
|
+
stopReason = "cancelled";
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
const found = await vscode.workspace.findFiles((0, text_1.toWorkspaceGlob)(include), excludeGlob, 5000);
|
|
71
|
+
for (const uri of found) {
|
|
72
|
+
const key = uri.toString();
|
|
73
|
+
if (!seen.has(key)) {
|
|
74
|
+
seen.add(key);
|
|
75
|
+
uris.push(uri);
|
|
76
|
+
}
|
|
77
|
+
if (uris.length >= config.pipeline.maxFiles) {
|
|
78
|
+
stopReason = `maxFiles ${config.pipeline.maxFiles} reached during discovery`;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (stopReason) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (uris.length === 0 && !stopReason) {
|
|
87
|
+
const found = await vscode.workspace.findFiles("**/*", excludeGlob, 5000);
|
|
88
|
+
uris.push(...found);
|
|
89
|
+
}
|
|
90
|
+
const allUnits = [];
|
|
91
|
+
let scannedFiles = 0;
|
|
92
|
+
let skippedFiles = 0;
|
|
93
|
+
let scannedBytes = 0;
|
|
94
|
+
let scannedTokens = 0;
|
|
95
|
+
for (const uri of uris) {
|
|
96
|
+
const processedFiles = scannedFiles + skippedFiles;
|
|
97
|
+
if (options.token?.isCancellationRequested) {
|
|
98
|
+
stopReason = "cancelled";
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
if (Date.now() - startedAt > config.pipeline.maxScanMs) {
|
|
102
|
+
stopReason = `maxScanMs ${config.pipeline.maxScanMs} reached`;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
if (scannedBytes >= maxBytes) {
|
|
106
|
+
stopReason = `maxTotalBytesMb ${config.pipeline.maxTotalBytesMb} reached`;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
if (allUnits.length >= maxRawEvidence) {
|
|
110
|
+
stopReason = `maxRawEvidence ${maxRawEvidence} reached`;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
if (processedFiles % 15 === 0) {
|
|
114
|
+
options.progress?.report({ message: `Scanning ${processedFiles + 1}/${uris.length}: ${formatProgressPath(path.posix.relative(folders[0].uri.path, uri.path))}` });
|
|
115
|
+
}
|
|
116
|
+
const fileStartedAt = Date.now();
|
|
117
|
+
const result = await scanFile(uri, folders[0].uri, profile, config);
|
|
118
|
+
const fileDurationMs = Date.now() - fileStartedAt;
|
|
119
|
+
if (result.scanned) {
|
|
120
|
+
scannedFiles += 1;
|
|
121
|
+
scannedBytes += result.size;
|
|
122
|
+
scannedTokens += result.tokenCount;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
skippedFiles += 1;
|
|
126
|
+
}
|
|
127
|
+
allUnits.push(...result.units);
|
|
128
|
+
if (fileDurationMs > 1000) {
|
|
129
|
+
options.progress?.report({ message: `Slow scan ${fileDurationMs}ms: ${formatProgressPath(path.posix.relative(folders[0].uri.path, uri.path))} (${result.units.length} evidence)` });
|
|
130
|
+
}
|
|
131
|
+
if ((scannedFiles + skippedFiles) % 15 === 0) {
|
|
132
|
+
options.progress?.report({ message: `Scanned ${scannedFiles}/${uris.length} files, ${allUnits.length} evidence` });
|
|
133
|
+
}
|
|
134
|
+
if (allUnits.length >= maxRawEvidence) {
|
|
135
|
+
stopReason = `maxRawEvidence ${maxRawEvidence} reached`;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
if ((scannedFiles + skippedFiles) % 25 === 0) {
|
|
139
|
+
await yieldToHost();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
units: allUnits,
|
|
144
|
+
stats: {
|
|
145
|
+
scannedFiles,
|
|
146
|
+
skippedFiles,
|
|
147
|
+
discoveredFiles: uris.length,
|
|
148
|
+
scannedBytes,
|
|
149
|
+
scannedTokens,
|
|
150
|
+
rawEvidenceCount: allUnits.length,
|
|
151
|
+
rankedEvidenceCount: allUnits.length,
|
|
152
|
+
maxCandidates: config.pipeline.maxCandidates,
|
|
153
|
+
capped: allUnits.length > config.pipeline.maxCandidates,
|
|
154
|
+
stoppedEarly: Boolean(stopReason),
|
|
155
|
+
stopReason
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
async function scanFile(uri, rootUri, profile, config) {
|
|
160
|
+
const relativePath = path.posix.relative(rootUri.path, uri.path);
|
|
161
|
+
if (!(0, text_1.isLikelyTextPath)(relativePath)) {
|
|
162
|
+
return { units: [], scanned: false, size: 0, tokenCount: 0 };
|
|
163
|
+
}
|
|
164
|
+
const stat = await vscode.workspace.fs.stat(uri);
|
|
165
|
+
if (stat.size > config.project.maxFileSizeKb * 1024) {
|
|
166
|
+
return { units: [], scanned: false, size: stat.size, tokenCount: 0 };
|
|
167
|
+
}
|
|
168
|
+
let content;
|
|
169
|
+
try {
|
|
170
|
+
const bytes = await vscode.workspace.fs.readFile(uri);
|
|
171
|
+
content = new TextDecoder("utf-8", { fatal: false }).decode(bytes);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return { units: [], scanned: false, size: stat.size, tokenCount: 0 };
|
|
175
|
+
}
|
|
176
|
+
if (content.includes("\u0000")) {
|
|
177
|
+
return { units: [], scanned: false, size: stat.size, tokenCount: 0 };
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
units: (0, fileScanner_1.scanTextFile)({
|
|
181
|
+
file: uri.fsPath,
|
|
182
|
+
relativePath,
|
|
183
|
+
content,
|
|
184
|
+
size: stat.size,
|
|
185
|
+
profile,
|
|
186
|
+
config
|
|
187
|
+
}),
|
|
188
|
+
scanned: true,
|
|
189
|
+
size: stat.size,
|
|
190
|
+
tokenCount: (0, text_1.fastTokenEstimate)(`${relativePath}\n${content}`)
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function emptyScanStats(config) {
|
|
194
|
+
return {
|
|
195
|
+
units: [],
|
|
196
|
+
stats: {
|
|
197
|
+
scannedFiles: 0,
|
|
198
|
+
skippedFiles: 0,
|
|
199
|
+
discoveredFiles: 0,
|
|
200
|
+
scannedBytes: 0,
|
|
201
|
+
scannedTokens: 0,
|
|
202
|
+
rawEvidenceCount: 0,
|
|
203
|
+
rankedEvidenceCount: 0,
|
|
204
|
+
maxCandidates: config.pipeline.maxCandidates,
|
|
205
|
+
capped: false,
|
|
206
|
+
stoppedEarly: false
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function formatProgressPath(relativePath) {
|
|
211
|
+
return relativePath.length > 120 ? `...${relativePath.slice(-117)}` : relativePath;
|
|
212
|
+
}
|
|
213
|
+
function yieldToHost() {
|
|
214
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=universalScan.js.map
|
|
@@ -0,0 +1,233 @@
|
|
|
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.detectCommands = detectCommands;
|
|
37
|
+
exports.runVerification = runVerification;
|
|
38
|
+
exports.verifyAfterEdits = verifyAfterEdits;
|
|
39
|
+
exports.formatVerificationForChat = formatVerificationForChat;
|
|
40
|
+
exports.summarizeVerificationRun = summarizeVerificationRun;
|
|
41
|
+
const cp = __importStar(require("child_process"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const vscode = __importStar(require("vscode"));
|
|
44
|
+
const logger_1 = require("../utils/logger");
|
|
45
|
+
async function detectCommands(workspaceRoot, changedFiles) {
|
|
46
|
+
const commands = [];
|
|
47
|
+
try {
|
|
48
|
+
const pkgJsonPath = path.join(workspaceRoot, "package.json");
|
|
49
|
+
const pkgJson = JSON.parse(await vscode.workspace.fs.readFile(vscode.Uri.file(pkgJsonPath)).then((bytes) => new TextDecoder().decode(bytes)));
|
|
50
|
+
const scripts = pkgJson.scripts;
|
|
51
|
+
if (scripts) {
|
|
52
|
+
if (scripts.test) {
|
|
53
|
+
commands.push({ label: "npm test", command: "npm", args: ["run", "test", "--", "--passWithNoTests"], cwd: workspaceRoot, kind: "test", scope: "project" });
|
|
54
|
+
}
|
|
55
|
+
if (scripts.lint) {
|
|
56
|
+
commands.push({ label: "npm run lint", command: "npm", args: ["run", "lint"], cwd: workspaceRoot, kind: "lint", scope: "project" });
|
|
57
|
+
}
|
|
58
|
+
if (scripts.typecheck || scripts.tsc) {
|
|
59
|
+
commands.push({ label: "npm run typecheck", command: "npm", args: ["run", scripts.typecheck ? "typecheck" : "tsc"], cwd: workspaceRoot, kind: "typecheck", scope: "project" });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// No package.json or unreadable — skip npm commands.
|
|
65
|
+
}
|
|
66
|
+
const testFiles = changedFiles.filter((file) => /\.(test|spec)\.(ts|tsx|js|jsx|py|php|java|rb|go|rs)$/.test(file));
|
|
67
|
+
if (testFiles.length > 0) {
|
|
68
|
+
for (const testFile of testFiles.slice(0, 5)) {
|
|
69
|
+
commands.push({
|
|
70
|
+
label: `Run ${path.basename(testFile)}`,
|
|
71
|
+
command: "npx",
|
|
72
|
+
args: ["vitest", "run", testFile, "--passWithNoTests"],
|
|
73
|
+
cwd: workspaceRoot,
|
|
74
|
+
kind: "test",
|
|
75
|
+
scope: "file"
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return commands;
|
|
80
|
+
}
|
|
81
|
+
async function runVerification(workspaceRoot, changedFiles, commands) {
|
|
82
|
+
const detected = commands ?? await detectCommands(workspaceRoot, changedFiles);
|
|
83
|
+
if (detected.length === 0) {
|
|
84
|
+
return {
|
|
85
|
+
changedFiles,
|
|
86
|
+
results: [],
|
|
87
|
+
summary: "No test, lint, or typecheck commands were detected for this project."
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const results = [];
|
|
91
|
+
for (const cmd of detected.slice(0, 4)) {
|
|
92
|
+
const started = Date.now();
|
|
93
|
+
try {
|
|
94
|
+
const result = await runCommand(cmd);
|
|
95
|
+
results.push({ command: cmd, ...result, durationMs: Date.now() - started });
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
99
|
+
results.push({
|
|
100
|
+
command: cmd,
|
|
101
|
+
exitCode: null,
|
|
102
|
+
stdout: "",
|
|
103
|
+
stderr: message,
|
|
104
|
+
durationMs: Date.now() - started,
|
|
105
|
+
timedOut: false
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
changedFiles,
|
|
111
|
+
results,
|
|
112
|
+
summary: renderVerificationSummary(results)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function runCommand(cmd) {
|
|
116
|
+
return new Promise((resolve) => {
|
|
117
|
+
const child = cp.spawn(cmd.command, cmd.args, {
|
|
118
|
+
cwd: cmd.cwd,
|
|
119
|
+
timeout: 60000,
|
|
120
|
+
shell: true,
|
|
121
|
+
env: { ...process.env, FORCE_COLOR: "0", CI: "true" }
|
|
122
|
+
});
|
|
123
|
+
let stdout = "";
|
|
124
|
+
let stderr = "";
|
|
125
|
+
child.stdout.on("data", (chunk) => {
|
|
126
|
+
stdout += chunk.toString();
|
|
127
|
+
if (stdout.length > 8000) {
|
|
128
|
+
stdout = stdout.slice(0, 8000) + "\n... (output truncated)";
|
|
129
|
+
child.kill();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
child.stderr.on("data", (chunk) => {
|
|
133
|
+
stderr += chunk.toString();
|
|
134
|
+
if (stderr.length > 4000) {
|
|
135
|
+
stderr = stderr.slice(0, 4000) + "\n... (output truncated)";
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
child.on("close", (code, signal) => {
|
|
139
|
+
resolve({
|
|
140
|
+
exitCode: code,
|
|
141
|
+
stdout: stdout.trim(),
|
|
142
|
+
stderr: stderr.trim(),
|
|
143
|
+
timedOut: signal === "SIGTERM" || signal === "SIGKILL"
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
child.on("error", (err) => {
|
|
147
|
+
resolve({
|
|
148
|
+
exitCode: null,
|
|
149
|
+
stdout: stdout.trim(),
|
|
150
|
+
stderr: err.message,
|
|
151
|
+
timedOut: false
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function renderVerificationSummary(results) {
|
|
157
|
+
if (results.length === 0) {
|
|
158
|
+
return "No verification commands were run.";
|
|
159
|
+
}
|
|
160
|
+
const lines = ["## Verification Results", ""];
|
|
161
|
+
let passed = 0;
|
|
162
|
+
let failed = 0;
|
|
163
|
+
for (const result of results) {
|
|
164
|
+
const status = result.exitCode === 0 ? "PASS" : result.timedOut ? "TIMEOUT" : result.exitCode === null ? "ERROR" : "FAIL";
|
|
165
|
+
if (status === "PASS") {
|
|
166
|
+
passed += 1;
|
|
167
|
+
}
|
|
168
|
+
else if (status === "FAIL" || status === "ERROR") {
|
|
169
|
+
failed += 1;
|
|
170
|
+
}
|
|
171
|
+
lines.push(`### ${status}: ${result.command.label} (${result.durationMs}ms)`, "");
|
|
172
|
+
if (result.stdout) {
|
|
173
|
+
const truncated = result.stdout.length > 2000 ? result.stdout.slice(0, 2000) + "\n... (truncated)" : result.stdout;
|
|
174
|
+
lines.push("```", truncated, "```", "");
|
|
175
|
+
}
|
|
176
|
+
if (result.stderr) {
|
|
177
|
+
lines.push("**Stderr:**", "", "```", result.stderr.slice(0, 1000), "```", "");
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const summaryLine = `${passed} passed, ${failed} failed, ${results.length - passed - failed} other`;
|
|
181
|
+
lines.unshift(`**Summary:** ${summaryLine}`, "");
|
|
182
|
+
return lines.join("\n");
|
|
183
|
+
}
|
|
184
|
+
async function verifyAfterEdits(changedFiles) {
|
|
185
|
+
const folders = vscode.workspace.workspaceFolders;
|
|
186
|
+
if (!folders?.[0]) {
|
|
187
|
+
await vscode.window.showWarningMessage("Open a workspace folder before running verification.");
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
const workspaceRoot = folders[0].uri.fsPath;
|
|
191
|
+
(0, logger_1.logInfo)(`Verification started for ${changedFiles.length} changed file(s).`);
|
|
192
|
+
try {
|
|
193
|
+
const run = await runVerification(workspaceRoot, changedFiles);
|
|
194
|
+
const document = await vscode.workspace.openTextDocument({
|
|
195
|
+
content: run.summary,
|
|
196
|
+
language: "markdown"
|
|
197
|
+
});
|
|
198
|
+
await vscode.window.showTextDocument(document, { preview: true, viewColumn: vscode.ViewColumn.Beside });
|
|
199
|
+
const failed = run.results.filter((r) => r.exitCode !== 0 && r.exitCode !== null).length;
|
|
200
|
+
if (failed > 0) {
|
|
201
|
+
const action = await vscode.window.showErrorMessage(`${failed} verification check(s) failed. Review the results and fix issues before continuing.`, "Show Results", "Dismiss");
|
|
202
|
+
if (action === "Show Results") {
|
|
203
|
+
await vscode.window.showTextDocument(document, { preview: false, viewColumn: vscode.ViewColumn.Beside });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else if (run.results.length > 0) {
|
|
207
|
+
await vscode.window.showInformationMessage(`All ${run.results.length} verification check(s) passed.`);
|
|
208
|
+
}
|
|
209
|
+
return run;
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
(0, logger_1.logError)("Verification failed.", error);
|
|
213
|
+
await vscode.window.showErrorMessage("Verification failed to run. Check the FlowSeeker log for details.");
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function formatVerificationForChat(run) {
|
|
218
|
+
if (run.results.length === 0) {
|
|
219
|
+
return "No automated verification was run. Manually check the changed files.";
|
|
220
|
+
}
|
|
221
|
+
return renderVerificationSummary(run.results);
|
|
222
|
+
}
|
|
223
|
+
function summarizeVerificationRun(run) {
|
|
224
|
+
if (run.results.length === 0) {
|
|
225
|
+
return "Verification complete: no test, lint, build, or typecheck commands were detected for this project.";
|
|
226
|
+
}
|
|
227
|
+
const passed = run.results.filter((result) => result.exitCode === 0).length;
|
|
228
|
+
const failed = run.results.filter((result) => result.exitCode !== 0 && result.exitCode !== null).length;
|
|
229
|
+
const other = run.results.length - passed - failed;
|
|
230
|
+
const status = failed > 0 ? "failed" : passed > 0 && other === 0 ? "passed" : "finished";
|
|
231
|
+
return `Verification ${status}: ${passed} passed, ${failed} failed, ${other} other across ${run.results.length} check(s).`;
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=verifyAfterApply.js.map
|
|
@@ -0,0 +1,71 @@
|
|
|
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.getHostCapabilities = getHostCapabilities;
|
|
37
|
+
exports.summarizeHostCapabilities = summarizeHostCapabilities;
|
|
38
|
+
const vscode = __importStar(require("vscode"));
|
|
39
|
+
function getHostCapabilities(context) {
|
|
40
|
+
const candidate = vscode;
|
|
41
|
+
return {
|
|
42
|
+
appName: vscode.env.appName,
|
|
43
|
+
version: vscode.version,
|
|
44
|
+
uriScheme: vscode.env.uriScheme,
|
|
45
|
+
uiKind: vscode.env.uiKind === vscode.UIKind.Web ? "web" : "desktop",
|
|
46
|
+
extensionKind: context?.extension.extensionKind === vscode.ExtensionKind.Workspace ? "workspace" : context?.extension.extensionKind === vscode.ExtensionKind.UI ? "ui" : "unknown",
|
|
47
|
+
hasNativeChat: typeof candidate.chat?.createChatParticipant === "function",
|
|
48
|
+
hasLanguageModels: typeof candidate.lm?.selectChatModels === "function",
|
|
49
|
+
hasLanguageModelTools: typeof candidate.lm?.invokeTool === "function",
|
|
50
|
+
hasMcp: typeof candidate.lm?.registerMcpServerDefinitionProvider === "function",
|
|
51
|
+
hasLanguageModelProvider: typeof candidate.lm?.registerLanguageModelChatProvider === "function"
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function summarizeHostCapabilities(capabilities) {
|
|
55
|
+
return [
|
|
56
|
+
`Host: ${capabilities.appName} ${capabilities.version}`,
|
|
57
|
+
`URI scheme: ${capabilities.uriScheme}`,
|
|
58
|
+
`UI kind: ${capabilities.uiKind}`,
|
|
59
|
+
`Extension kind: ${capabilities.extensionKind}`,
|
|
60
|
+
`Sidebar webview: supported`,
|
|
61
|
+
`Native Chat participant: ${yesNo(capabilities.hasNativeChat)}`,
|
|
62
|
+
`VS Code Language Model API: ${yesNo(capabilities.hasLanguageModels)}`,
|
|
63
|
+
`Language Model tools: ${yesNo(capabilities.hasLanguageModelTools)}`,
|
|
64
|
+
`MCP server provider API: ${yesNo(capabilities.hasMcp)}`,
|
|
65
|
+
`Language Model provider API: ${yesNo(capabilities.hasLanguageModelProvider)}`
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
function yesNo(value) {
|
|
69
|
+
return value ? "supported" : "not available";
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1,98 @@
|
|
|
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.detectHost = detectHost;
|
|
37
|
+
exports.probeLanguageModels = probeLanguageModels;
|
|
38
|
+
exports.summarizeProbe = summarizeProbe;
|
|
39
|
+
const vscode = __importStar(require("vscode"));
|
|
40
|
+
function detectHost() {
|
|
41
|
+
const appName = vscode.env.appName;
|
|
42
|
+
const version = vscode.version;
|
|
43
|
+
const uriScheme = vscode.env.uriScheme;
|
|
44
|
+
const appNameLower = appName.toLowerCase();
|
|
45
|
+
if (/windsurf/i.test(appNameLower)) {
|
|
46
|
+
return { id: "windsurf", appName, version, uriScheme };
|
|
47
|
+
}
|
|
48
|
+
if (/cursor/i.test(appNameLower)) {
|
|
49
|
+
return { id: "cursor", appName, version, uriScheme };
|
|
50
|
+
}
|
|
51
|
+
if (/antigravity/i.test(appNameLower)) {
|
|
52
|
+
return { id: "antigravity", appName, version, uriScheme };
|
|
53
|
+
}
|
|
54
|
+
if (/vscodium/i.test(appNameLower)) {
|
|
55
|
+
return { id: "vscodium", appName, version, uriScheme };
|
|
56
|
+
}
|
|
57
|
+
if (/theia/i.test(appNameLower)) {
|
|
58
|
+
return { id: "theia", appName, version, uriScheme };
|
|
59
|
+
}
|
|
60
|
+
if (/insiders?/i.test(appNameLower)) {
|
|
61
|
+
return { id: "vscode-insiders", appName, version, uriScheme };
|
|
62
|
+
}
|
|
63
|
+
if (/visual studio code/i.test(appNameLower) || /code/i.test(appNameLower) || uriScheme === "vscode") {
|
|
64
|
+
return { id: "vscode", appName, version, uriScheme };
|
|
65
|
+
}
|
|
66
|
+
return { id: "unknown", appName, version, uriScheme };
|
|
67
|
+
}
|
|
68
|
+
async function probeLanguageModels(capabilities) {
|
|
69
|
+
const apiExists = capabilities.hasLanguageModels;
|
|
70
|
+
if (!apiExists) {
|
|
71
|
+
return { apiExists: false, apiWorking: false, modelCount: 0, modelVendors: [] };
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const models = await vscode.lm.selectChatModels({});
|
|
75
|
+
const modelList = Array.isArray(models) ? models : [];
|
|
76
|
+
return {
|
|
77
|
+
apiExists: true,
|
|
78
|
+
apiWorking: modelList.length > 0,
|
|
79
|
+
modelCount: modelList.length,
|
|
80
|
+
modelVendors: [...new Set(modelList.map((m) => m.vendor).filter(Boolean))]
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
85
|
+
return { apiExists: true, apiWorking: false, modelCount: 0, modelVendors: [], error: message };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function summarizeProbe(host, capabilities, probe) {
|
|
89
|
+
return [
|
|
90
|
+
`Host detected: ${host.id} (appName: "${host.appName}", version: ${host.version}, scheme: ${host.uriScheme})`,
|
|
91
|
+
`chatParticipant API: ${capabilities.hasNativeChat ? "exists" : "missing"}`,
|
|
92
|
+
`Language Model API: ${capabilities.hasLanguageModels ? "exists" : "missing"}`,
|
|
93
|
+
` → selectChatModels probe: ${probe.apiWorking ? `${probe.modelCount} model(s), vendors: ${probe.modelVendors.join(", ") || "none"}` : probe.apiExists ? `API exists but returned 0 models${probe.error ? ` (${probe.error})` : ""}` : "N/A"}`,
|
|
94
|
+
`MCP provider API: ${capabilities.hasMcp ? "exists" : "missing"}`,
|
|
95
|
+
`Language Model provider API: ${capabilities.hasLanguageModelProvider ? "exists" : "missing"}`
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=hostDetect.js.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getHostTier = getHostTier;
|
|
4
|
+
exports.clearTierCache = clearTierCache;
|
|
5
|
+
exports.tierLabel = tierLabel;
|
|
6
|
+
exports.tierDescription = tierDescription;
|
|
7
|
+
exports.loadHostVerifications = loadHostVerifications;
|
|
8
|
+
exports.saveHostVerification = saveHostVerification;
|
|
9
|
+
exports.getVerificationForHost = getVerificationForHost;
|
|
10
|
+
const hostDetect_1 = require("./hostDetect");
|
|
11
|
+
const capabilities_1 = require("./capabilities");
|
|
12
|
+
const KNOWN_NATIVE_HOSTS = new Set(["vscode", "vscode-insiders"]);
|
|
13
|
+
let cachedTier;
|
|
14
|
+
function getHostTier() {
|
|
15
|
+
if (cachedTier)
|
|
16
|
+
return cachedTier;
|
|
17
|
+
const host = (0, hostDetect_1.detectHost)();
|
|
18
|
+
const capabilities = (0, capabilities_1.getHostCapabilities)();
|
|
19
|
+
let tier;
|
|
20
|
+
let reason;
|
|
21
|
+
if (!capabilities.hasNativeChat) {
|
|
22
|
+
tier = "sidebar-primary";
|
|
23
|
+
reason = `Host "${host.appName}" does not expose the VS Code Chat API. Sidebar chat is the primary interface.`;
|
|
24
|
+
}
|
|
25
|
+
else if (KNOWN_NATIVE_HOSTS.has(host.id)) {
|
|
26
|
+
tier = "native-full";
|
|
27
|
+
reason = `Host "${host.appName}" is a verified VS Code family editor with full Native Chat support.`;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
tier = "native-unverified";
|
|
31
|
+
reason = `Host "${host.appName}" exposes the Chat API but has not been verified to render @flowseeker. Native chat participant is registered; sidebar is the guaranteed interface.`;
|
|
32
|
+
}
|
|
33
|
+
cachedTier = { tier, host, capabilities, reason };
|
|
34
|
+
return cachedTier;
|
|
35
|
+
}
|
|
36
|
+
function clearTierCache() {
|
|
37
|
+
cachedTier = undefined;
|
|
38
|
+
}
|
|
39
|
+
function tierLabel(tier) {
|
|
40
|
+
switch (tier) {
|
|
41
|
+
case "native-full": return "Native Chat";
|
|
42
|
+
case "native-unverified": return "Native Chat (unverified)";
|
|
43
|
+
case "sidebar-primary": return "Sidebar";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function tierDescription(tier) {
|
|
47
|
+
switch (tier) {
|
|
48
|
+
case "native-full":
|
|
49
|
+
return "@flowseeker /guide works in native chat. Sidebar is also available.";
|
|
50
|
+
case "native-unverified":
|
|
51
|
+
return "Native chat may work. Sidebar chat is the guaranteed interface.";
|
|
52
|
+
case "sidebar-primary":
|
|
53
|
+
return "Native chat is unavailable. Use the sidebar or Copy Agent Prompt.";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const VERIFICATION_KEY = "flowseeker.hostVerifications";
|
|
57
|
+
function loadHostVerifications(context) {
|
|
58
|
+
return context.globalState.get(VERIFICATION_KEY) ?? [];
|
|
59
|
+
}
|
|
60
|
+
function saveHostVerification(context, verification) {
|
|
61
|
+
const verifications = loadHostVerifications(context).filter((v) => !(v.hostId === verification.hostId && v.hostVersion === verification.hostVersion));
|
|
62
|
+
verifications.push(verification);
|
|
63
|
+
void context.globalState.update(VERIFICATION_KEY, verifications);
|
|
64
|
+
}
|
|
65
|
+
function getVerificationForHost(context, hostId, hostVersion) {
|
|
66
|
+
return loadHostVerifications(context).find((v) => v.hostId === hostId && v.hostVersion === hostVersion);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=hostTier.js.map
|