@orangepro/orangepro-mcp 0.2.26 → 0.2.27
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/dist/local/operations.js +23 -15
- package/dist/local/telemetry.js +28 -20
- package/package.json +1 -1
package/dist/local/operations.js
CHANGED
|
@@ -1494,6 +1494,7 @@ function writeStartStaticSnapshot(root, baseRef, warnings) {
|
|
|
1494
1494
|
return behaviorCoveragePath ? { behaviorCoveragePath } : {};
|
|
1495
1495
|
}
|
|
1496
1496
|
export async function opStart(root, opts = {}, deps = defaultDeps()) {
|
|
1497
|
+
const startTime = Date.now();
|
|
1497
1498
|
const providerOpts = startProviderOverride(root, opts);
|
|
1498
1499
|
const scanRoot = opts.source ? resolve(opts.source) : resolve(root);
|
|
1499
1500
|
const providerEnv = loadProviderEnv([root, scanRoot], deps.env);
|
|
@@ -1511,21 +1512,6 @@ export async function opStart(root, opts = {}, deps = defaultDeps()) {
|
|
|
1511
1512
|
suppressProgress: true
|
|
1512
1513
|
}, deps);
|
|
1513
1514
|
const warnings = [...analyze.warnings];
|
|
1514
|
-
let dominantLang = "unknown";
|
|
1515
|
-
try {
|
|
1516
|
-
const g = loadGraph(root);
|
|
1517
|
-
const lc = {};
|
|
1518
|
-
for (const n of g.nodes) {
|
|
1519
|
-
const lang = n.kind === "File" && typeof n.properties.language === "string" ? n.properties.language : null;
|
|
1520
|
-
if (lang)
|
|
1521
|
-
lc[lang] = (lc[lang] ?? 0) + 1;
|
|
1522
|
-
}
|
|
1523
|
-
const top = Object.entries(lc).sort((a, b) => b[1] - a[1]);
|
|
1524
|
-
if (top.length > 0)
|
|
1525
|
-
dominantLang = top[0][0];
|
|
1526
|
-
}
|
|
1527
|
-
catch { /* telemetry is best-effort */ }
|
|
1528
|
-
pingTelemetry({ fileCount: scope.files, language: dominantLang });
|
|
1529
1515
|
reportProgress("start: deterministic graph is ready", { current: 4, total: 8 });
|
|
1530
1516
|
const staticSnapshot = writeStartStaticSnapshot(root, opts.baseRef, warnings);
|
|
1531
1517
|
const providerConfigured = deps.aiProvider !== undefined || resolveProviderConfig(providerEnv, providerOpts) !== null;
|
|
@@ -1687,6 +1673,28 @@ export async function opStart(root, opts = {}, deps = defaultDeps()) {
|
|
|
1687
1673
|
const rtm = opRtm(root, { format: "md", baseRef: opts.baseRef, limit: START_RTM_LIMIT });
|
|
1688
1674
|
const finalGraph = loadGraph(workspacePaths(root).graphPath);
|
|
1689
1675
|
const aiLinked = summarizeAiLinks(finalGraph);
|
|
1676
|
+
// --- Telemetry (v2): fire after report is generated, graph is final ---
|
|
1677
|
+
try {
|
|
1678
|
+
const lc = {};
|
|
1679
|
+
for (const n of finalGraph.nodes) {
|
|
1680
|
+
if (n.kind === "File" && typeof n.properties.language === "string") {
|
|
1681
|
+
lc[n.properties.language] = (lc[n.properties.language] ?? 0) + 1;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
const topLang = Object.entries(lc).sort((a, b) => b[1] - a[1]);
|
|
1685
|
+
const dominantLang = topLang.length > 0 ? topLang[0][0] : "unknown";
|
|
1686
|
+
const behaviorCount = behaviorNodes(finalGraph).length;
|
|
1687
|
+
pingTelemetry({
|
|
1688
|
+
event: "scan_complete",
|
|
1689
|
+
fileCount: scope.files,
|
|
1690
|
+
language: dominantLang,
|
|
1691
|
+
behaviors: behaviorCount,
|
|
1692
|
+
hasByok: !!(providerEnv.ANTHROPIC_API_KEY || providerEnv.OPENAI_API_KEY || providerEnv.OLLAMA_BASE_URL),
|
|
1693
|
+
reportGenerated: !!coverageHtml,
|
|
1694
|
+
durationMs: Date.now() - startTime,
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
catch { /* telemetry must never fail the run */ }
|
|
1690
1698
|
const finalAnalyze = {
|
|
1691
1699
|
...analyze,
|
|
1692
1700
|
analysis: finalGraph.analysis ?? analyze.analysis,
|
package/dist/local/telemetry.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Anonymous usage telemetry for OrangePro MCP.
|
|
2
|
+
* Anonymous usage telemetry for OrangePro MCP (v2).
|
|
3
3
|
*
|
|
4
|
-
* Sends one lightweight ping per
|
|
5
|
-
* file count bucket,
|
|
6
|
-
*
|
|
4
|
+
* Sends one lightweight ping per scan with: version, detected language,
|
|
5
|
+
* file count bucket, behavior count bucket, whether BYOK is configured,
|
|
6
|
+
* whether the report was generated, scan duration, OS, and node version.
|
|
7
|
+
*
|
|
8
|
+
* No code, no file names, no repo name, no identity, no IP stored.
|
|
7
9
|
*
|
|
8
10
|
* Disable: set DO_NOT_TRACK=1 or ORANGEPRO_NO_TELEMETRY=1
|
|
9
11
|
*/
|
|
10
12
|
import https from "https";
|
|
11
13
|
import { readFileSync } from "fs";
|
|
12
|
-
import { resolve } from "path";
|
|
14
|
+
import { dirname, resolve } from "path";
|
|
15
|
+
import { fileURLToPath } from "url";
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
13
18
|
const ENDPOINT_HOST = "telemetry.orangepro.ai";
|
|
14
19
|
const ENDPOINT_PATH = "/v1/ping";
|
|
15
20
|
const TIMEOUT_MS = 3000;
|
|
@@ -22,20 +27,20 @@ function getVersion() {
|
|
|
22
27
|
return "unknown";
|
|
23
28
|
}
|
|
24
29
|
}
|
|
30
|
+
function bucket(count, thresholds) {
|
|
31
|
+
for (let i = 0; i < thresholds.length; i++) {
|
|
32
|
+
if (count < thresholds[i]) {
|
|
33
|
+
const low = i === 0 ? 1 : thresholds[i - 1];
|
|
34
|
+
return `${low}-${thresholds[i] - 1}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return `${thresholds[thresholds.length - 1]}+`;
|
|
38
|
+
}
|
|
25
39
|
function fileBucket(count) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (count < 500)
|
|
31
|
-
return "200-499";
|
|
32
|
-
if (count < 1000)
|
|
33
|
-
return "500-999";
|
|
34
|
-
if (count < 5000)
|
|
35
|
-
return "1000-4999";
|
|
36
|
-
if (count < 10000)
|
|
37
|
-
return "5000-9999";
|
|
38
|
-
return "10000+";
|
|
40
|
+
return bucket(count, [50, 200, 500, 1000, 5000, 10000]);
|
|
41
|
+
}
|
|
42
|
+
function behaviorBucket(count) {
|
|
43
|
+
return bucket(count, [100, 500, 1000, 5000, 10000]);
|
|
39
44
|
}
|
|
40
45
|
export function pingTelemetry(payload) {
|
|
41
46
|
// Respect DO_NOT_TRACK standard and custom env var
|
|
@@ -44,13 +49,16 @@ export function pingTelemetry(payload) {
|
|
|
44
49
|
return;
|
|
45
50
|
}
|
|
46
51
|
const data = JSON.stringify({
|
|
47
|
-
event: "
|
|
52
|
+
event: payload.event || "scan_complete",
|
|
48
53
|
v: getVersion(),
|
|
49
54
|
lang: payload.language,
|
|
50
55
|
files: fileBucket(payload.fileCount),
|
|
56
|
+
behaviors: payload.behaviors != null ? behaviorBucket(payload.behaviors) : undefined,
|
|
57
|
+
has_byok: payload.hasByok ? 1 : 0,
|
|
58
|
+
report: payload.reportGenerated !== false ? 1 : 0,
|
|
59
|
+
duration_ms: payload.durationMs ?? undefined,
|
|
51
60
|
os: process.platform,
|
|
52
61
|
node: process.version,
|
|
53
|
-
ts: new Date().toISOString(),
|
|
54
62
|
});
|
|
55
63
|
try {
|
|
56
64
|
const req = https.request({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orangepro/orangepro-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.27",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "OrangePro (`opro`) — a local-first, BYOK CLI + MCP server that builds an evidence graph from a local checkout, ingests runtime coverage, and generates grounded tests. Metadata-only exports; no source upload; generated tests stay local.",
|
|
6
6
|
"license": "MIT",
|