sceneview-mcp 4.0.11 → 4.0.13
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/README.md +15 -2
- package/dist/analyze-project.js +9 -2
- package/dist/android-docs.js +206 -0
- package/dist/artifact.js +1 -1
- package/dist/debug-issue.js +35 -10
- package/dist/examples.js +136 -0
- package/dist/extra-guides.js +4 -3
- package/dist/generate-scene.js +1 -9
- package/dist/generated/llms-txt.js +1 -1
- package/dist/generated/version.js +7 -4
- package/dist/guides.js +9 -8
- package/dist/index.js +32 -3
- package/dist/issues.js +54 -3
- package/dist/migration.js +5 -4
- package/dist/platform-setup.js +26 -11
- package/dist/samples.js +65 -64
- package/dist/telemetry.js +178 -2
- package/dist/tiers.js +2 -0
- package/dist/tools/definitions.js +38 -0
- package/dist/tools/handler.js +54 -14
- package/dist/validator.js +9 -0
- package/package.json +15 -4
- package/dist/auth.js +0 -84
- package/dist/billing.js +0 -137
- package/dist/convert-platform.js +0 -302
- package/dist/explain-api.js +0 -246
- package/dist/generate-animation.js +0 -576
- package/dist/generate-environment.js +0 -483
- package/dist/generate-gesture.js +0 -532
- package/dist/generate-physics.js +0 -570
- package/dist/optimize-scene.js +0 -173
- package/llms.txt +0 -3326
package/dist/samples.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { LATEST_SCENEVIEW_RELEASE } from "./generated/version.js";
|
|
1
2
|
export const SAMPLES = {
|
|
2
3
|
"model-viewer": {
|
|
3
4
|
id: "model-viewer",
|
|
4
5
|
title: "3D Model Viewer",
|
|
5
6
|
description: "Full-screen 3D scene with a GLB model, HDR environment, orbit camera, and animation controls",
|
|
6
7
|
tags: ["3d", "model", "environment", "camera", "animation"],
|
|
7
|
-
dependency: "io.github.sceneview:sceneview:
|
|
8
|
-
prompt: "Create an Android Compose screen that loads a GLB model and displays it with HDR lighting, orbit camera, and animation playback. Use SceneView `io.github.sceneview:sceneview
|
|
8
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
9
|
+
prompt: "Create an Android Compose screen that loads a GLB model and displays it with HDR lighting, orbit camera, and animation playback. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
9
10
|
code: `@Composable
|
|
10
11
|
fun ModelViewerScreen() {
|
|
11
12
|
val engine = rememberEngine()
|
|
@@ -38,8 +39,8 @@ fun ModelViewerScreen() {
|
|
|
38
39
|
title: "AR Tap-to-Place Model Viewer",
|
|
39
40
|
description: "AR scene with plane detection. Tap a surface to place a 3D model with pinch-to-scale and drag-to-rotate gestures.",
|
|
40
41
|
tags: ["ar", "model", "anchor", "plane-detection", "placement", "gestures"],
|
|
41
|
-
dependency: "io.github.sceneview:arsceneview:
|
|
42
|
-
prompt: "Create an AR screen that detects surfaces and lets the user tap to place a GLB model. Support pinch-to-scale and drag-to-rotate. Use SceneView `io.github.sceneview:arsceneview
|
|
42
|
+
dependency: "io.github.sceneview:arsceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
43
|
+
prompt: "Create an AR screen that detects surfaces and lets the user tap to place a GLB model. Support pinch-to-scale and drag-to-rotate. Use SceneView `io.github.sceneview:arsceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
43
44
|
code: `@Composable
|
|
44
45
|
fun ARModelViewerScreen() {
|
|
45
46
|
val engine = rememberEngine()
|
|
@@ -83,8 +84,8 @@ fun ARModelViewerScreen() {
|
|
|
83
84
|
title: "AR Augmented Image",
|
|
84
85
|
description: "Detects reference images in the camera feed and overlays 3D models or video above them.",
|
|
85
86
|
tags: ["ar", "model", "image-tracking"],
|
|
86
|
-
dependency: "io.github.sceneview:arsceneview:
|
|
87
|
-
prompt: "Create an AR screen that detects a printed reference image and places a 3D model above it. Use SceneView `io.github.sceneview:arsceneview
|
|
87
|
+
dependency: "io.github.sceneview:arsceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
88
|
+
prompt: "Create an AR screen that detects a printed reference image and places a 3D model above it. Use SceneView `io.github.sceneview:arsceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
88
89
|
code: `@Composable
|
|
89
90
|
fun AugmentedImageScreen() {
|
|
90
91
|
val engine = rememberEngine()
|
|
@@ -125,8 +126,8 @@ fun AugmentedImageScreen() {
|
|
|
125
126
|
title: "AR Cloud Anchor",
|
|
126
127
|
description: "Host and resolve persistent cross-device anchors using ARCore Cloud Anchors.",
|
|
127
128
|
tags: ["ar", "anchor", "cloud-anchor"],
|
|
128
|
-
dependency: "io.github.sceneview:arsceneview:
|
|
129
|
-
prompt: "Create an AR screen that can host a cloud anchor (saving its ID) and resolve it later on another device. Use SceneView `io.github.sceneview:arsceneview
|
|
129
|
+
dependency: "io.github.sceneview:arsceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
130
|
+
prompt: "Create an AR screen that can host a cloud anchor (saving its ID) and resolve it later on another device. Use SceneView `io.github.sceneview:arsceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
130
131
|
code: `// ⚠️ Cloud Anchors require an ARCore Cloud API key in AndroidManifest.xml:
|
|
131
132
|
// <meta-data android:name="com.google.android.ar.API_KEY"
|
|
132
133
|
// android:value="\${arcoreApiKey}" />
|
|
@@ -164,8 +165,8 @@ fun CloudAnchorScreen() {
|
|
|
164
165
|
title: "AR Point Cloud",
|
|
165
166
|
description: "Visualizes ARCore feature points as 3D spheres with confidence-based filtering.",
|
|
166
167
|
tags: ["ar", "point-cloud"],
|
|
167
|
-
dependency: "io.github.sceneview:arsceneview:
|
|
168
|
-
prompt: "Create an AR screen that visualizes ARCore feature points as small 3D spheres, filtered by confidence. Use SceneView `io.github.sceneview:arsceneview
|
|
168
|
+
dependency: "io.github.sceneview:arsceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
169
|
+
prompt: "Create an AR screen that visualizes ARCore feature points as small 3D spheres, filtered by confidence. Use SceneView `io.github.sceneview:arsceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
169
170
|
code: `@Composable
|
|
170
171
|
fun PointCloudScreen() {
|
|
171
172
|
val engine = rememberEngine()
|
|
@@ -196,8 +197,8 @@ fun PointCloudScreen() {
|
|
|
196
197
|
title: "AR Face Mesh",
|
|
197
198
|
description: "AR face tracking with AugmentedFaceNode — applies a textured mesh overlay to detected faces using the front camera.",
|
|
198
199
|
tags: ["ar", "face-tracking", "model"],
|
|
199
|
-
dependency: "io.github.sceneview:arsceneview:
|
|
200
|
-
prompt: "Create an AR screen that uses the front camera to detect faces and overlay a 3D mesh on them. Use SceneView `io.github.sceneview:arsceneview
|
|
200
|
+
dependency: "io.github.sceneview:arsceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
201
|
+
prompt: "Create an AR screen that uses the front camera to detect faces and overlay a 3D mesh on them. Use SceneView `io.github.sceneview:arsceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
201
202
|
code: `@Composable
|
|
202
203
|
fun ARFaceMeshScreen() {
|
|
203
204
|
val engine = rememberEngine()
|
|
@@ -240,8 +241,8 @@ fun ARFaceMeshScreen() {
|
|
|
240
241
|
title: "glTF Camera",
|
|
241
242
|
description: "Extracts and uses camera definitions embedded in a glTF file for cinematic viewpoints.",
|
|
242
243
|
tags: ["3d", "model", "camera"],
|
|
243
|
-
dependency: "io.github.sceneview:sceneview:
|
|
244
|
-
prompt: "Create a 3D scene that loads a GLB file containing embedded camera definitions, then uses those cameras for cinematic viewpoints. Use SceneView `io.github.sceneview:sceneview
|
|
244
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
245
|
+
prompt: "Create a 3D scene that loads a GLB file containing embedded camera definitions, then uses those cameras for cinematic viewpoints. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
245
246
|
code: `@Composable
|
|
246
247
|
fun GltfCameraScreen() {
|
|
247
248
|
val engine = rememberEngine()
|
|
@@ -270,8 +271,8 @@ fun GltfCameraScreen() {
|
|
|
270
271
|
title: "Camera Manipulator",
|
|
271
272
|
description: "Orbit, pan, and zoom camera with customizable sensitivity and bounds.",
|
|
272
273
|
tags: ["3d", "camera", "gestures"],
|
|
273
|
-
dependency: "io.github.sceneview:sceneview:
|
|
274
|
-
prompt: "Create a 3D scene with a fully configurable orbit camera — drag to rotate, two-finger pan, pinch to zoom. Use SceneView `io.github.sceneview:sceneview
|
|
274
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
275
|
+
prompt: "Create a 3D scene with a fully configurable orbit camera — drag to rotate, two-finger pan, pinch to zoom. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
275
276
|
code: `@Composable
|
|
276
277
|
fun CameraManipulatorScreen() {
|
|
277
278
|
val engine = rememberEngine()
|
|
@@ -301,8 +302,8 @@ fun CameraManipulatorScreen() {
|
|
|
301
302
|
title: "Camera Animation",
|
|
302
303
|
description: "Animated camera flythrough around a 3D model — smooth orbit using LaunchedEffect and trigonometric interpolation.",
|
|
303
304
|
tags: ["3d", "camera", "animation", "model"],
|
|
304
|
-
dependency: "io.github.sceneview:sceneview:
|
|
305
|
-
prompt: "Create a 3D scene with a camera that automatically orbits around a model in a smooth circle. Include a play/pause button. Use SceneView `io.github.sceneview:sceneview
|
|
305
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
306
|
+
prompt: "Create a 3D scene with a camera that automatically orbits around a model in a smooth circle. Include a play/pause button. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
306
307
|
code: `@Composable
|
|
307
308
|
fun CameraAnimationScreen() {
|
|
308
309
|
val engine = rememberEngine()
|
|
@@ -362,8 +363,8 @@ fun CameraAnimationScreen() {
|
|
|
362
363
|
title: "Autopilot Demo",
|
|
363
364
|
description: "Autonomous driving HUD with animated car, road geometry, and real-time telemetry overlay.",
|
|
364
365
|
tags: ["3d", "model", "animation", "geometry"],
|
|
365
|
-
dependency: "io.github.sceneview:sceneview:
|
|
366
|
-
prompt: "Create an autopilot-style visualization with a 3D car on a road and a HUD overlay showing speed, distance, and status. Use SceneView `io.github.sceneview:sceneview
|
|
366
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
367
|
+
prompt: "Create an autopilot-style visualization with a 3D car on a road and a HUD overlay showing speed, distance, and status. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
367
368
|
code: `@Composable
|
|
368
369
|
fun AutopilotScreen() {
|
|
369
370
|
val engine = rememberEngine()
|
|
@@ -431,8 +432,8 @@ fun AutopilotScreen() {
|
|
|
431
432
|
title: "Physics Simulation",
|
|
432
433
|
description: "Animated physics simulation with spheres falling under gravity and bouncing off a floor, using onFrame for per-frame updates.",
|
|
433
434
|
tags: ["3d", "physics", "geometry", "animation"],
|
|
434
|
-
dependency: "io.github.sceneview:sceneview:
|
|
435
|
-
prompt: "Create a 3D scene with spheres that fall under gravity and bounce on a floor using per-frame animation. Use SceneView `io.github.sceneview:sceneview
|
|
435
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
436
|
+
prompt: "Create a 3D scene with spheres that fall under gravity and bounce on a floor using per-frame animation. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
436
437
|
code: `@Composable
|
|
437
438
|
fun PhysicsDemoScreen() {
|
|
438
439
|
val engine = rememberEngine()
|
|
@@ -524,8 +525,8 @@ fun PhysicsDemoScreen() {
|
|
|
524
525
|
title: "Dynamic Sky & Lighting",
|
|
525
526
|
description: "Time-of-day sun cycle with animated LightNode direction, intensity, and color to simulate sunrise through sunset.",
|
|
526
527
|
tags: ["3d", "sky", "environment", "animation", "lighting"],
|
|
527
|
-
dependency: "io.github.sceneview:sceneview:
|
|
528
|
-
prompt: "Create a 3D scene with a time-of-day sun that moves from sunrise through noon to sunset, with animated light color and intensity. Use SceneView `io.github.sceneview:sceneview
|
|
528
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
529
|
+
prompt: "Create a 3D scene with a time-of-day sun that moves from sunrise through noon to sunset, with animated light color and intensity. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
529
530
|
code: `@Composable
|
|
530
531
|
fun DynamicSkyScreen() {
|
|
531
532
|
val engine = rememberEngine()
|
|
@@ -608,8 +609,8 @@ fun DynamicSkyScreen() {
|
|
|
608
609
|
title: "Line & Path",
|
|
609
610
|
description: "Animated 3D line art with sine waves and Lissajous curves using PathNode and LineNode, with parameter sliders.",
|
|
610
611
|
tags: ["3d", "lines", "geometry", "animation"],
|
|
611
|
-
dependency: "io.github.sceneview:sceneview:
|
|
612
|
-
prompt: "Create a 3D scene that draws animated parametric curves (sine wave, Lissajous) using PathNode with amplitude and frequency sliders. Use SceneView `io.github.sceneview:sceneview
|
|
612
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
613
|
+
prompt: "Create a 3D scene that draws animated parametric curves (sine wave, Lissajous) using PathNode with amplitude and frequency sliders. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
613
614
|
code: `@Composable
|
|
614
615
|
fun LinePathScreen() {
|
|
615
616
|
val engine = rememberEngine()
|
|
@@ -685,8 +686,8 @@ fun LinePathScreen() {
|
|
|
685
686
|
title: "Text Labels",
|
|
686
687
|
description: "Camera-facing 3D text labels using TextNode — floating labels above geometry spheres representing planets.",
|
|
687
688
|
tags: ["3d", "text", "geometry"],
|
|
688
|
-
dependency: "io.github.sceneview:sceneview:
|
|
689
|
-
prompt: "Create a 3D scene with floating text labels above colored spheres representing planets. Use TextNode for the labels. Use SceneView `io.github.sceneview:sceneview
|
|
689
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
690
|
+
prompt: "Create a 3D scene with floating text labels above colored spheres representing planets. Use TextNode for the labels. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
690
691
|
code: `@Composable
|
|
691
692
|
fun TextLabelsScreen() {
|
|
692
693
|
val engine = rememberEngine()
|
|
@@ -743,8 +744,8 @@ fun TextLabelsScreen() {
|
|
|
743
744
|
title: "Reflection Probe",
|
|
744
745
|
description: "Zone-based IBL overrides with material picker (Chrome, Gold, Copper, Rough) and probe toggle.",
|
|
745
746
|
tags: ["3d", "reflection", "environment", "model"],
|
|
746
|
-
dependency: "io.github.sceneview:sceneview:
|
|
747
|
-
prompt: "Create a 3D scene with a metallic sphere and a ReflectionProbeNode that overrides the IBL. Add a material picker to switch between Chrome, Gold, Copper, and Rough. Use SceneView `io.github.sceneview:sceneview
|
|
747
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
748
|
+
prompt: "Create a 3D scene with a metallic sphere and a ReflectionProbeNode that overrides the IBL. Add a material picker to switch between Chrome, Gold, Copper, and Rough. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
748
749
|
code: `@Composable
|
|
749
750
|
fun ReflectionProbeScreen() {
|
|
750
751
|
val engine = rememberEngine()
|
|
@@ -779,8 +780,8 @@ fun ReflectionProbeScreen() {
|
|
|
779
780
|
title: "Post-Processing",
|
|
780
781
|
description: "Real-time post-processing effects: bloom, vignette, tone mapping, FXAA, and SSAO controls.",
|
|
781
782
|
tags: ["3d", "post-processing", "environment"],
|
|
782
|
-
dependency: "io.github.sceneview:sceneview:
|
|
783
|
-
prompt: "Create a 3D scene with interactive post-processing controls for bloom, vignette, tone mapping, FXAA, and SSAO. Use SceneView `io.github.sceneview:sceneview
|
|
783
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
784
|
+
prompt: "Create a 3D scene with interactive post-processing controls for bloom, vignette, tone mapping, FXAA, and SSAO. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
784
785
|
code: `@Composable
|
|
785
786
|
fun PostProcessingScreen() {
|
|
786
787
|
val engine = rememberEngine()
|
|
@@ -807,8 +808,8 @@ fun PostProcessingScreen() {
|
|
|
807
808
|
title: "Video Texture",
|
|
808
809
|
description: "Video playback on a 3D plane using VideoNode with MediaPlayer — supports looping, chroma-key, and auto-sizing.",
|
|
809
810
|
tags: ["3d", "video", "model"],
|
|
810
|
-
dependency: "io.github.sceneview:sceneview:
|
|
811
|
-
prompt: "Create a 3D scene with a video playing on a floating 3D plane. Include play/pause controls and chroma-key support. Use SceneView `io.github.sceneview:sceneview
|
|
811
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
812
|
+
prompt: "Create a 3D scene with a video playing on a floating 3D plane. Include play/pause controls and chroma-key support. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
812
813
|
code: `@Composable
|
|
813
814
|
fun VideoTextureScreen() {
|
|
814
815
|
val context = LocalContext.current
|
|
@@ -857,8 +858,8 @@ fun VideoTextureScreen() {
|
|
|
857
858
|
title: "Multi-Model Scene",
|
|
858
859
|
description: "Scene with multiple 3D models loaded independently, positioned and scaled to create a complete environment.",
|
|
859
860
|
tags: ["3d", "model", "multi-model", "environment"],
|
|
860
|
-
dependency: "io.github.sceneview:sceneview:
|
|
861
|
-
prompt: "Create a 3D scene that loads multiple GLB models (a car, a building, and trees) and positions them to form a street scene. Use SceneView `io.github.sceneview:sceneview
|
|
861
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
862
|
+
prompt: "Create a 3D scene that loads multiple GLB models (a car, a building, and trees) and positions them to form a street scene. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
862
863
|
code: `@Composable
|
|
863
864
|
fun MultiModelScreen() {
|
|
864
865
|
val engine = rememberEngine()
|
|
@@ -923,8 +924,8 @@ fun MultiModelScreen() {
|
|
|
923
924
|
title: "Gesture Interaction",
|
|
924
925
|
description: "Full gesture handling — tap to select, double-tap to scale, long-press for info, pinch-to-scale, drag-to-move on editable nodes.",
|
|
925
926
|
tags: ["3d", "gestures", "model"],
|
|
926
|
-
dependency: "io.github.sceneview:sceneview:
|
|
927
|
-
prompt: "Create a 3D scene with a model that responds to tap (select), double-tap (scale up), long-press (show info), and supports pinch-to-scale and drag-to-move. Use SceneView `io.github.sceneview:sceneview
|
|
927
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
928
|
+
prompt: "Create a 3D scene with a model that responds to tap (select), double-tap (scale up), long-press (show info), and supports pinch-to-scale and drag-to-move. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
928
929
|
code: `@Composable
|
|
929
930
|
fun GestureInteractionScreen() {
|
|
930
931
|
val engine = rememberEngine()
|
|
@@ -987,8 +988,8 @@ fun GestureInteractionScreen() {
|
|
|
987
988
|
title: "Environment & Lighting",
|
|
988
989
|
description: "Complete lighting setup — HDR environment (IBL + skybox), main directional light, point light, and spot light with LightNode.",
|
|
989
990
|
tags: ["3d", "environment", "lighting", "model"],
|
|
990
|
-
dependency: "io.github.sceneview:sceneview:
|
|
991
|
-
prompt: "Create a 3D scene with full HDR environment lighting (IBL + skybox), a directional sun light, a red point light, and a blue spot light. Use SceneView `io.github.sceneview:sceneview
|
|
991
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
992
|
+
prompt: "Create a 3D scene with full HDR environment lighting (IBL + skybox), a directional sun light, a red point light, and a blue spot light. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
992
993
|
code: `@Composable
|
|
993
994
|
fun EnvironmentLightingScreen() {
|
|
994
995
|
val engine = rememberEngine()
|
|
@@ -1056,8 +1057,8 @@ fun EnvironmentLightingScreen() {
|
|
|
1056
1057
|
title: "Procedural Geometry",
|
|
1057
1058
|
description: "Procedural shapes — CubeNode, SphereNode, CylinderNode, PlaneNode — with PBR materials (metallic, roughness, color).",
|
|
1058
1059
|
tags: ["3d", "geometry", "model"],
|
|
1059
|
-
dependency: "io.github.sceneview:sceneview:
|
|
1060
|
-
prompt: "Create a 3D scene showing procedural geometry shapes (cube, sphere, cylinder, plane) with different PBR materials. No model files needed. Use SceneView `io.github.sceneview:sceneview
|
|
1060
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
1061
|
+
prompt: "Create a 3D scene showing procedural geometry shapes (cube, sphere, cylinder, plane) with different PBR materials. No model files needed. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
1061
1062
|
code: `@Composable
|
|
1062
1063
|
fun ProceduralGeometryScreen() {
|
|
1063
1064
|
val engine = rememberEngine()
|
|
@@ -1136,8 +1137,8 @@ fun ProceduralGeometryScreen() {
|
|
|
1136
1137
|
title: "Compose UI in 3D",
|
|
1137
1138
|
description: "Embed interactive Jetpack Compose UI (Cards, Buttons, Text) inside 3D space using ViewNode.",
|
|
1138
1139
|
tags: ["3d", "compose-ui", "text"],
|
|
1139
|
-
dependency: "io.github.sceneview:sceneview:
|
|
1140
|
-
prompt: "Create a 3D scene with interactive Compose UI elements (Card with text and a button) floating in 3D space using ViewNode. Use SceneView `io.github.sceneview:sceneview
|
|
1140
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
1141
|
+
prompt: "Create a 3D scene with interactive Compose UI elements (Card with text and a button) floating in 3D space using ViewNode. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
1141
1142
|
code: `@Composable
|
|
1142
1143
|
fun ComposeUI3DScreen() {
|
|
1143
1144
|
val engine = rememberEngine()
|
|
@@ -1186,8 +1187,8 @@ fun ComposeUI3DScreen() {
|
|
|
1186
1187
|
title: "Node Hierarchy",
|
|
1187
1188
|
description: "Parent-child node relationships — a spinning solar system with planet groups orbiting a central sun.",
|
|
1188
1189
|
tags: ["3d", "hierarchy", "geometry", "animation"],
|
|
1189
|
-
dependency: "io.github.sceneview:sceneview:
|
|
1190
|
-
prompt: "Create a 3D solar system where planets orbit a sun using parent-child node hierarchies. Each planet group rotates independently. Use SceneView `io.github.sceneview:sceneview
|
|
1190
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
1191
|
+
prompt: "Create a 3D solar system where planets orbit a sun using parent-child node hierarchies. Each planet group rotates independently. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
1191
1192
|
code: `@Composable
|
|
1192
1193
|
fun NodeHierarchyScreen() {
|
|
1193
1194
|
val engine = rememberEngine()
|
|
@@ -1267,7 +1268,7 @@ fun NodeHierarchyScreen() {
|
|
|
1267
1268
|
title: "iOS 3D Model Viewer",
|
|
1268
1269
|
description: "SwiftUI 3D scene with a USDZ model, IBL environment, orbit camera, and animation playback.",
|
|
1269
1270
|
tags: ["3d", "model", "environment", "camera", "animation", "ios", "swift"],
|
|
1270
|
-
dependency:
|
|
1271
|
+
dependency: `https://github.com/sceneview/sceneview — from: "${LATEST_SCENEVIEW_RELEASE}"`,
|
|
1271
1272
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1272
1273
|
prompt: "Create a SwiftUI screen that loads a USDZ model and displays it with IBL lighting, orbit camera, and animation playback. Use SceneViewSwift.",
|
|
1273
1274
|
language: "swift",
|
|
@@ -1306,7 +1307,7 @@ struct ModelViewerScreen: View {
|
|
|
1306
1307
|
title: "iOS AR Tap-to-Place Model Viewer",
|
|
1307
1308
|
description: "AR scene with plane detection. Tap a surface to place a 3D model using ARKit + RealityKit.",
|
|
1308
1309
|
tags: ["ar", "model", "anchor", "plane-detection", "placement", "ios", "swift"],
|
|
1309
|
-
dependency:
|
|
1310
|
+
dependency: `https://github.com/sceneview/sceneview — from: "${LATEST_SCENEVIEW_RELEASE}"`,
|
|
1310
1311
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1311
1312
|
prompt: "Create an iOS AR screen that detects surfaces and lets the user tap to place a USDZ model. Use SceneViewSwift.",
|
|
1312
1313
|
language: "swift",
|
|
@@ -1346,7 +1347,7 @@ struct ARModelViewerScreen: View {
|
|
|
1346
1347
|
title: "iOS AR Augmented Image",
|
|
1347
1348
|
description: "Detects reference images in the camera feed and overlays 3D content above them using ARKit.",
|
|
1348
1349
|
tags: ["ar", "model", "image-tracking", "ios", "swift"],
|
|
1349
|
-
dependency:
|
|
1350
|
+
dependency: `https://github.com/sceneview/sceneview — from: "${LATEST_SCENEVIEW_RELEASE}"`,
|
|
1350
1351
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1351
1352
|
prompt: "Create an iOS AR screen that detects a printed reference image and places a 3D model above it. Use SceneViewSwift.",
|
|
1352
1353
|
language: "swift",
|
|
@@ -1384,7 +1385,7 @@ struct AugmentedImageScreen: View {
|
|
|
1384
1385
|
title: "iOS Procedural Geometry",
|
|
1385
1386
|
description: "Procedural geometry shapes — cube, sphere, cylinder, cone, and plane — with PBR materials.",
|
|
1386
1387
|
tags: ["3d", "geometry", "ios", "swift"],
|
|
1387
|
-
dependency:
|
|
1388
|
+
dependency: `https://github.com/sceneview/sceneview — from: "${LATEST_SCENEVIEW_RELEASE}"`,
|
|
1388
1389
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1389
1390
|
prompt: "Create a SwiftUI scene showing procedural geometry shapes (cube, sphere, cylinder, cone, plane) with different materials. Use SceneViewSwift.",
|
|
1390
1391
|
language: "swift",
|
|
@@ -1438,7 +1439,7 @@ struct GeometryShapesScreen: View {
|
|
|
1438
1439
|
title: "iOS Lighting",
|
|
1439
1440
|
description: "Directional, point, and spot lights with configurable intensity, color, and shadows.",
|
|
1440
1441
|
tags: ["3d", "lighting", "environment", "ios", "swift"],
|
|
1441
|
-
dependency:
|
|
1442
|
+
dependency: `https://github.com/sceneview/sceneview — from: "${LATEST_SCENEVIEW_RELEASE}"`,
|
|
1442
1443
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1443
1444
|
prompt: "Create a SwiftUI 3D scene with directional, point, and spot lights illuminating geometry. Use SceneViewSwift.",
|
|
1444
1445
|
language: "swift",
|
|
@@ -1502,7 +1503,7 @@ struct LightingScreen: View {
|
|
|
1502
1503
|
title: "iOS Physics Demo",
|
|
1503
1504
|
description: "Interactive physics simulation with bouncing spheres, gravity, and configurable restitution.",
|
|
1504
1505
|
tags: ["3d", "physics", "geometry", "ios", "swift"],
|
|
1505
|
-
dependency:
|
|
1506
|
+
dependency: `https://github.com/sceneview/sceneview — from: "${LATEST_SCENEVIEW_RELEASE}"`,
|
|
1506
1507
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1507
1508
|
prompt: "Create a SwiftUI 3D scene where tapping spawns coloured spheres that fall under gravity and bounce off a floor. Use SceneViewSwift.",
|
|
1508
1509
|
language: "swift",
|
|
@@ -1566,7 +1567,7 @@ struct PhysicsDemoScreen: View {
|
|
|
1566
1567
|
title: "iOS 3D Text Labels",
|
|
1567
1568
|
description: "Camera-facing 3D text labels using TextNode and BillboardNode for always-facing-camera behavior.",
|
|
1568
1569
|
tags: ["3d", "text", "geometry", "ios", "swift"],
|
|
1569
|
-
dependency:
|
|
1570
|
+
dependency: `https://github.com/sceneview/sceneview — from: "${LATEST_SCENEVIEW_RELEASE}"`,
|
|
1570
1571
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1571
1572
|
prompt: "Create a SwiftUI 3D scene with floating text labels that always face the camera, showing planet names. Use SceneViewSwift.",
|
|
1572
1573
|
language: "swift",
|
|
@@ -1614,7 +1615,7 @@ struct TextLabelsScreen: View {
|
|
|
1614
1615
|
title: "iOS Video on 3D Surface",
|
|
1615
1616
|
description: "Video playback on a 3D plane using VideoNode with play/pause controls.",
|
|
1616
1617
|
tags: ["3d", "video", "ios", "swift"],
|
|
1617
|
-
dependency:
|
|
1618
|
+
dependency: `https://github.com/sceneview/sceneview — from: "${LATEST_SCENEVIEW_RELEASE}"`,
|
|
1618
1619
|
spmDependency: "https://github.com/sceneview/sceneview",
|
|
1619
1620
|
prompt: "Create a SwiftUI 3D scene with a video playing on a floating 3D plane. Include play/pause controls. Use SceneViewSwift.",
|
|
1620
1621
|
language: "swift",
|
|
@@ -1685,8 +1686,8 @@ struct VideoPlayerScreen: View {
|
|
|
1685
1686
|
title: "Image Node",
|
|
1686
1687
|
description: "Display images on 3D planes using ImageNode — from assets, resources, or Bitmaps.",
|
|
1687
1688
|
tags: ["3d", "image", "geometry"],
|
|
1688
|
-
dependency: "io.github.sceneview:sceneview:
|
|
1689
|
-
prompt: "Create a 3D scene with images displayed on floating planes using ImageNode. Show examples from file, resource, and Bitmap. Use SceneView `io.github.sceneview:sceneview
|
|
1689
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
1690
|
+
prompt: "Create a 3D scene with images displayed on floating planes using ImageNode. Show examples from file, resource, and Bitmap. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
1690
1691
|
code: `@Composable
|
|
1691
1692
|
fun ImageNodeScreen() {
|
|
1692
1693
|
val engine = rememberEngine()
|
|
@@ -1744,8 +1745,8 @@ fun ImageNodeScreen() {
|
|
|
1744
1745
|
title: "Billboard Sprite",
|
|
1745
1746
|
description: "Always-facing-camera sprites using BillboardNode — useful for markers, icons, and info overlays in 3D space.",
|
|
1746
1747
|
tags: ["3d", "billboard", "image"],
|
|
1747
|
-
dependency: "io.github.sceneview:sceneview:
|
|
1748
|
-
prompt: "Create a 3D scene with billboard sprites that always face the camera, useful for markers and info overlays. Use SceneView `io.github.sceneview:sceneview
|
|
1748
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
1749
|
+
prompt: "Create a 3D scene with billboard sprites that always face the camera, useful for markers and info overlays. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
1749
1750
|
code: `@Composable
|
|
1750
1751
|
fun BillboardSpriteScreen() {
|
|
1751
1752
|
val engine = rememberEngine()
|
|
@@ -1809,8 +1810,8 @@ fun BillboardSpriteScreen() {
|
|
|
1809
1810
|
title: "Animation State Machine",
|
|
1810
1811
|
description: "Reactive animation driven by Compose state — switch between Idle, Walk, and Run animations on a character model.",
|
|
1811
1812
|
tags: ["3d", "model", "animation"],
|
|
1812
|
-
dependency: "io.github.sceneview:sceneview:
|
|
1813
|
-
prompt: "Create a 3D scene with a character model that switches between Idle, Walk, and Run animations based on button clicks. Use animationName for state-driven animation. Use SceneView `io.github.sceneview:sceneview
|
|
1813
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
1814
|
+
prompt: "Create a 3D scene with a character model that switches between Idle, Walk, and Run animations based on button clicks. Use animationName for state-driven animation. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
1814
1815
|
code: `@Composable
|
|
1815
1816
|
fun AnimationStateScreen() {
|
|
1816
1817
|
val engine = rememberEngine()
|
|
@@ -1873,8 +1874,8 @@ fun AnimationStateScreen() {
|
|
|
1873
1874
|
title: "Spring Animation",
|
|
1874
1875
|
description: "Smooth spring-based node animations using Compose animateFloatAsState with spring spec for natural motion.",
|
|
1875
1876
|
tags: ["3d", "animation", "spring", "geometry"],
|
|
1876
|
-
dependency: "io.github.sceneview:sceneview:
|
|
1877
|
-
prompt: "Create a 3D scene with geometry nodes that animate position using spring physics via Compose's animateFloatAsState. Tap to toggle positions with springy motion. Use SceneView `io.github.sceneview:sceneview
|
|
1877
|
+
dependency: "io.github.sceneview:sceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
1878
|
+
prompt: "Create a 3D scene with geometry nodes that animate position using spring physics via Compose's animateFloatAsState. Tap to toggle positions with springy motion. Use SceneView `io.github.sceneview:sceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
1878
1879
|
code: `@Composable
|
|
1879
1880
|
fun SpringAnimationScreen() {
|
|
1880
1881
|
val engine = rememberEngine()
|
|
@@ -1966,8 +1967,8 @@ fun SpringAnimationScreen() {
|
|
|
1966
1967
|
title: "AR Surface Cursor",
|
|
1967
1968
|
description: "AR scene with a center-screen reticle using HitResultNode that follows the detected surface.",
|
|
1968
1969
|
tags: ["ar", "cursor", "plane-detection", "placement"],
|
|
1969
|
-
dependency: "io.github.sceneview:arsceneview:
|
|
1970
|
-
prompt: "Create an AR screen with a surface cursor (reticle) in the center of the screen that follows detected surfaces, using HitResultNode. Tap to place a model at the cursor position. Use SceneView `io.github.sceneview:arsceneview
|
|
1970
|
+
dependency: "io.github.sceneview:arsceneview:" + LATEST_SCENEVIEW_RELEASE + "",
|
|
1971
|
+
prompt: "Create an AR screen with a surface cursor (reticle) in the center of the screen that follows detected surfaces, using HitResultNode. Tap to place a model at the cursor position. Use SceneView `io.github.sceneview:arsceneview:${LATEST_SCENEVIEW_RELEASE}`.",
|
|
1971
1972
|
code: `@Composable
|
|
1972
1973
|
fun ARSurfaceCursorScreen() {
|
|
1973
1974
|
val engine = rememberEngine()
|
package/dist/telemetry.js
CHANGED
|
@@ -8,16 +8,25 @@
|
|
|
8
8
|
// - client: MCP client name (e.g. "claude-desktop", "cursor")
|
|
9
9
|
// - clientVersion: MCP client version string reported during handshake
|
|
10
10
|
// - mcpVersion: this package's version
|
|
11
|
-
// - tier: "free" | "pro"
|
|
11
|
+
// - tier: "free" | "pro" — tier the TOOL resolved to, NOT the user's plan
|
|
12
12
|
// - tool?: tool name (only for "tool" events)
|
|
13
|
+
// - installId?: opaque random UUID per install — lets the worker count
|
|
14
|
+
// unique developers per client runtime without identifying who they are
|
|
15
|
+
// - botLikelihood?: float in [0.0, 1.0] computed at the sender side from
|
|
16
|
+
// environment signals (CI flags, no-TTY, container hints). Worker uses
|
|
17
|
+
// it to exclude bot traffic from monetization analytics by default.
|
|
13
18
|
//
|
|
14
19
|
// What NEVER gets sent:
|
|
15
20
|
// - IP address (the endpoint strips it server-side; we never send headers)
|
|
16
|
-
// - hostname, OS user, machine id
|
|
21
|
+
// - hostname, OS user, machine id, cwd, project path, package name
|
|
17
22
|
// - prompt content, tool arguments, tool results
|
|
18
23
|
// - API keys, billing info
|
|
19
24
|
//
|
|
20
25
|
// Opt out with `SCENEVIEW_TELEMETRY=0` or by running in CI (`CI=true`).
|
|
26
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
27
|
+
import { homedir } from "node:os";
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
import { randomUUID } from "node:crypto";
|
|
21
30
|
// Worker implementation: telemetry-worker/ (Hono + D1 + KV rate limiting).
|
|
22
31
|
// Deploy with: cd telemetry-worker && see DEPLOY.md
|
|
23
32
|
const TELEMETRY_ENDPOINT = "https://sceneview-telemetry.mcp-tools-lab.workers.dev/v1/events";
|
|
@@ -31,6 +40,9 @@ let clientContext;
|
|
|
31
40
|
// ─── Client-side batch buffer ─────────────────────────────────────────────────
|
|
32
41
|
let buffer = [];
|
|
33
42
|
let flushTimer;
|
|
43
|
+
// Cached fingerprint values — computed once per process.
|
|
44
|
+
let cachedInstallId;
|
|
45
|
+
let cachedBotLikelihood;
|
|
34
46
|
// Read lazily so tests that mutate env vars between runs see the latest value.
|
|
35
47
|
function isEnabled() {
|
|
36
48
|
if (process.env.SCENEVIEW_TELEMETRY === "0")
|
|
@@ -47,6 +59,156 @@ import { PACKAGE_VERSION } from "./generated/version.js";
|
|
|
47
59
|
function getMcpVersion() {
|
|
48
60
|
return process.env.SCENEVIEW_MCP_VERSION ?? PACKAGE_VERSION;
|
|
49
61
|
}
|
|
62
|
+
// ─── Install ID — anonymous per-install fingerprint ──────────────────────────
|
|
63
|
+
//
|
|
64
|
+
// Stored at `$XDG_CONFIG_HOME/sceneview-mcp/install.json` (default
|
|
65
|
+
// `~/.config/sceneview-mcp/install.json`). Created on first run if missing.
|
|
66
|
+
// Contents: `{ "installId": "<uuid v4>", "createdAt": "<ISO>" }`.
|
|
67
|
+
//
|
|
68
|
+
// Why a UUID and not a hash of hostname / cwd / etc.:
|
|
69
|
+
// - hostnames/cwd are personally identifying (employee laptop name,
|
|
70
|
+
// `/Users/<name>/...`) — even hashed, they're predictable enough that
|
|
71
|
+
// a determined attacker with worker-side DB access could brute-force
|
|
72
|
+
// them back. A UUID is provably non-identifying.
|
|
73
|
+
// - The point is to count unique developers per `client` runtime, not to
|
|
74
|
+
// fingerprint the host. A fresh install = a fresh identity, by design.
|
|
75
|
+
//
|
|
76
|
+
// Disabled when telemetry is disabled (no file is written).
|
|
77
|
+
function getInstallIdConfigPath() {
|
|
78
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
79
|
+
const base = xdg && xdg.length > 0 ? xdg : join(homedir(), ".config");
|
|
80
|
+
return join(base, "sceneview-mcp", "install.json");
|
|
81
|
+
}
|
|
82
|
+
function loadOrCreateInstallId() {
|
|
83
|
+
if (cachedInstallId !== undefined)
|
|
84
|
+
return cachedInstallId;
|
|
85
|
+
let path;
|
|
86
|
+
try {
|
|
87
|
+
path = getInstallIdConfigPath();
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
// Try to read an existing install record.
|
|
93
|
+
try {
|
|
94
|
+
const raw = readFileSync(path, "utf8");
|
|
95
|
+
const parsed = JSON.parse(raw);
|
|
96
|
+
if (typeof parsed.installId === "string" && parsed.installId.length > 0) {
|
|
97
|
+
cachedInstallId = parsed.installId;
|
|
98
|
+
return cachedInstallId;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// File missing or unreadable — fall through to create.
|
|
103
|
+
}
|
|
104
|
+
// Create a fresh install record. All failures are swallowed: a read-only
|
|
105
|
+
// home directory (CI sandboxes, container images) should not break telemetry
|
|
106
|
+
// or the MCP server itself.
|
|
107
|
+
try {
|
|
108
|
+
const installId = randomUUID();
|
|
109
|
+
const dir = join(path, "..");
|
|
110
|
+
mkdirSync(dir, { recursive: true });
|
|
111
|
+
writeFileSync(path, JSON.stringify({ installId, createdAt: new Date().toISOString() }, null, 2), { encoding: "utf8" });
|
|
112
|
+
cachedInstallId = installId;
|
|
113
|
+
return cachedInstallId;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Fallback: an ephemeral per-process UUID. Better than nothing —
|
|
117
|
+
// still distinguishes parallel scripted runs from a real install.
|
|
118
|
+
cachedInstallId = randomUUID();
|
|
119
|
+
return cachedInstallId;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// ─── Bot likelihood — sender-side heuristic ──────────────────────────────────
|
|
123
|
+
//
|
|
124
|
+
// Returns a score in [0.0, 1.0] where 1.0 = almost certainly automation.
|
|
125
|
+
// Signals (each independently bumps the score):
|
|
126
|
+
//
|
|
127
|
+
// - GITHUB_ACTIONS / GITLAB_CI / CIRCLECI / BUILDKITE / TF_BUILD / JENKINS_URL
|
|
128
|
+
// are set → +0.45 (strong)
|
|
129
|
+
// - CI is set to any truthy value → +0.30 (medium)
|
|
130
|
+
// - stdout is not a TTY → +0.15 (weak)
|
|
131
|
+
// - common container/sandbox hints
|
|
132
|
+
// (KUBERNETES_SERVICE_HOST, container=docker, AWS_LAMBDA_FUNCTION_NAME)
|
|
133
|
+
// → +0.20 (medium)
|
|
134
|
+
// - DEBIAN_FRONTEND=noninteractive (popular in scripts) → +0.10 (weak)
|
|
135
|
+
//
|
|
136
|
+
// The score is computed ONCE per process and reused on every event. It is
|
|
137
|
+
// clamped to [0.0, 1.0]. The worker uses it as an advisory exclusion filter
|
|
138
|
+
// (default threshold 0.7); raw events are still stored for forensics.
|
|
139
|
+
function computeBotLikelihood() {
|
|
140
|
+
if (cachedBotLikelihood !== undefined)
|
|
141
|
+
return cachedBotLikelihood;
|
|
142
|
+
let score = 0;
|
|
143
|
+
const env = process.env;
|
|
144
|
+
// Strong: a named CI provider env var.
|
|
145
|
+
const strongCiVars = [
|
|
146
|
+
"GITHUB_ACTIONS",
|
|
147
|
+
"GITLAB_CI",
|
|
148
|
+
"CIRCLECI",
|
|
149
|
+
"BUILDKITE",
|
|
150
|
+
"TF_BUILD",
|
|
151
|
+
"JENKINS_URL",
|
|
152
|
+
"BITBUCKET_BUILD_NUMBER",
|
|
153
|
+
"TEAMCITY_VERSION",
|
|
154
|
+
"TRAVIS",
|
|
155
|
+
"DRONE",
|
|
156
|
+
];
|
|
157
|
+
if (strongCiVars.some((k) => typeof env[k] === "string" && env[k].length > 0)) {
|
|
158
|
+
score += 0.45;
|
|
159
|
+
}
|
|
160
|
+
// Medium: generic CI=truthy. We don't double-count if a strong var fired,
|
|
161
|
+
// but for cheap envs ("CI=true" alone), this captures them.
|
|
162
|
+
const ci = env.CI;
|
|
163
|
+
if (typeof ci === "string" && (ci === "true" || ci === "1")) {
|
|
164
|
+
score += 0.3;
|
|
165
|
+
}
|
|
166
|
+
// Weak: no TTY → almost always automation or piped invocation. We test
|
|
167
|
+
// stdout because the MCP protocol uses stdin/stdout, but stderr is the
|
|
168
|
+
// more reliable indicator of "is a human watching".
|
|
169
|
+
try {
|
|
170
|
+
// process.stderr is most reliable; some MCP runners pipe stdout but leave
|
|
171
|
+
// stderr attached. Both being non-TTY is a stronger bot signal.
|
|
172
|
+
const stderrTty = typeof process.stderr === "object" &&
|
|
173
|
+
typeof process.stderr.isTTY === "boolean" &&
|
|
174
|
+
process.stderr.isTTY === true;
|
|
175
|
+
if (!stderrTty)
|
|
176
|
+
score += 0.15;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// Defensive — if stderr isn't introspectable, treat as non-TTY.
|
|
180
|
+
score += 0.15;
|
|
181
|
+
}
|
|
182
|
+
// Medium: containerized environments.
|
|
183
|
+
const containerVars = [
|
|
184
|
+
"KUBERNETES_SERVICE_HOST",
|
|
185
|
+
"AWS_LAMBDA_FUNCTION_NAME",
|
|
186
|
+
"VERCEL",
|
|
187
|
+
"NETLIFY",
|
|
188
|
+
"CODESPACE_NAME",
|
|
189
|
+
];
|
|
190
|
+
if (containerVars.some((k) => typeof env[k] === "string" && env[k].length > 0) ||
|
|
191
|
+
env.container === "docker") {
|
|
192
|
+
score += 0.2;
|
|
193
|
+
}
|
|
194
|
+
// Weak: scripted invocations frequently set this.
|
|
195
|
+
if (env.DEBIAN_FRONTEND === "noninteractive")
|
|
196
|
+
score += 0.1;
|
|
197
|
+
cachedBotLikelihood = Math.min(1, Math.max(0, score));
|
|
198
|
+
return cachedBotLikelihood;
|
|
199
|
+
}
|
|
200
|
+
// Build a base payload populated with the install fingerprint + bot score.
|
|
201
|
+
// `installId` is omitted when telemetry is disabled or the install file
|
|
202
|
+
// could not be created. `botLikelihood` is always present (default 0).
|
|
203
|
+
function buildBase() {
|
|
204
|
+
const out = {
|
|
205
|
+
botLikelihood: computeBotLikelihood(),
|
|
206
|
+
};
|
|
207
|
+
const installId = loadOrCreateInstallId();
|
|
208
|
+
if (installId)
|
|
209
|
+
out.installId = installId;
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
50
212
|
// Fire-and-forget POST of a single payload to the individual event endpoint.
|
|
51
213
|
// Used as fallback when batch delivery fails.
|
|
52
214
|
function sendSingle(payload) {
|
|
@@ -148,6 +310,8 @@ function send(payload) {
|
|
|
148
310
|
/** Exposed for tests — resets the cached client context and the batch buffer. */
|
|
149
311
|
export function __resetClientContext() {
|
|
150
312
|
clientContext = undefined;
|
|
313
|
+
cachedInstallId = undefined;
|
|
314
|
+
cachedBotLikelihood = undefined;
|
|
151
315
|
buffer = [];
|
|
152
316
|
if (flushTimer !== undefined) {
|
|
153
317
|
clearTimeout(flushTimer);
|
|
@@ -175,6 +339,7 @@ export function recordClientInit(clientInfo) {
|
|
|
175
339
|
clientVersion: clientContext.clientVersion,
|
|
176
340
|
mcpVersion: getMcpVersion(),
|
|
177
341
|
tier: "free",
|
|
342
|
+
...buildBase(),
|
|
178
343
|
});
|
|
179
344
|
}
|
|
180
345
|
/**
|
|
@@ -196,5 +361,16 @@ export function recordToolCall(toolName, tier) {
|
|
|
196
361
|
mcpVersion: getMcpVersion(),
|
|
197
362
|
tier,
|
|
198
363
|
tool: toolName,
|
|
364
|
+
...buildBase(),
|
|
199
365
|
});
|
|
200
366
|
}
|
|
367
|
+
// ─── Test-only exports ────────────────────────────────────────────────────────
|
|
368
|
+
/** Exposed for tests — bypass the cache and recompute the bot score. */
|
|
369
|
+
export function __computeBotLikelihoodForTest() {
|
|
370
|
+
cachedBotLikelihood = undefined;
|
|
371
|
+
return computeBotLikelihood();
|
|
372
|
+
}
|
|
373
|
+
/** Exposed for tests — read the install ID without going through send(). */
|
|
374
|
+
export function __getInstallIdForTest() {
|
|
375
|
+
return loadOrCreateInstallId();
|
|
376
|
+
}
|