vectorvesper 2.4.1 → 2.6.0
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 +113 -113
- package/dist/{chunk-5YSVDVLK.js → chunk-BI3LEGXE.js} +1 -1
- package/dist/{chunk-SFP5K3ZO.js → chunk-ZFHVMCR6.js} +1 -1
- package/dist/hooks.json +4 -4
- package/dist/index.js +19 -16
- package/dist/{mcp-FP5FICSI.js → mcp-BEM4TVKM.js} +12 -4
- package/dist/{server-AYBXJAAO.js → server-CIFO3HSN.js} +114 -25
- package/package.json +81 -81
package/README.md
CHANGED
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
BANNER: host a wide image (≈1280×640) at an ABSOLUTE url — relative paths do
|
|
3
|
-
NOT render on npmjs.com — then uncomment this block:
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<a href="https://vectorvesper.dev">
|
|
7
|
-
<img src="https://vectorvesper.dev/banner.png" alt="Vector Vesper" width="100%" />
|
|
8
|
-
</a>
|
|
9
|
-
</p>
|
|
10
|
-
-->
|
|
11
|
-
|
|
12
|
-
<h1 align="center">Vector Vesper</h1>
|
|
13
|
-
|
|
14
|
-
<p align="center">
|
|
15
|
-
Production-grade WebGL, 3D, and motion components for React. Copy directly into your codebase and own the code.
|
|
16
|
-
</p>
|
|
17
|
-
|
|
18
|
-
<p align="center">
|
|
19
|
-
<a href="https://www.npmjs.com/package/vectorvesper"><img src="https://img.shields.io/npm/v/vectorvesper?color=7EACB5&label=npm" alt="npm version" /></a>
|
|
20
|
-
<a href="https://github.com/vectorvesper/vv-components/blob/main/LICENSE"><img src="https://img.shields.io/github/license/vectorvesper/vv-components?color=7EACB5&label=license" alt="license" /></a>
|
|
21
|
-
<a href="https://vectorvesper.dev"><img src="https://img.shields.io/badge/docs-vectorvesper.dev-7EACB5" alt="docs" /></a>
|
|
22
|
-
</p>
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
> Vector Vesper is a CLI you run with `npx`, not a package you install. Start with `npx vectorvesper init` below.
|
|
27
|
-
|
|
28
|
-
**Vector Vesper** is a motion toolkit for React consisting of 3D animations, shaders, and advanced motion components.
|
|
29
|
-
|
|
30
|
-
The CLI writes the component code directly into your repository. You have full control over the math, the shaders, and the styles.
|
|
31
|
-
|
|
32
|
-
## Quick Start
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
# Initialize project configuration
|
|
36
|
-
npx vectorvesper init
|
|
37
|
-
|
|
38
|
-
# Add a visual component
|
|
39
|
-
npx vectorvesper add video-card
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
The CLI auto-detects your workspace, installs required animation dependencies (such as `three`, `@react-three/fiber`, or `gsap`), and writes the code to `@/components/vv/`.
|
|
43
|
-
|
|
44
|
-
```tsx
|
|
45
|
-
import { VideoCard } from "@/components/vv/video-card";
|
|
46
|
-
|
|
47
|
-
export default function Page() {
|
|
48
|
-
return (
|
|
49
|
-
<div className="h-screen w-full">
|
|
50
|
-
<VideoCard src="/clip.mp4" />
|
|
51
|
-
</div>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## MCP server — motion advice for your coding agent
|
|
57
|
-
|
|
58
|
-
The same CLI runs as an [MCP](https://modelcontextprotocol.io) server, so Claude Code, Cursor, Copilot and friends can ask about motion before they write it.
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
npx vectorvesper mcp install
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
That configures every supported editor it finds. Restart the editor and run `npx vectorvesper mcp status` to confirm. No account or token is needed — the runtime, its contracts and the linter are free.
|
|
65
|
-
|
|
66
|
-
**Why bother.** Bad motion code does not error. TypeScript passes, the build is green, and the page janks on a mid-range phone six weeks later with nothing connecting the two. An agent has no feedback signal for the one quality dimension that matters here, so this server gives it three:
|
|
67
|
-
|
|
68
|
-
- **`plan_motion`** — describe what you are building and get told whether it needs a primitive **at all**, which ones, in what order, and when that advice would be wrong. It says "use CSS, not this" for a hover state, a fade on mount, a spinner or a one-time scroll reveal, because those are compositor features that cost no main-thread time. Roughly a fifth of its answers recommend the platform over this library.
|
|
69
|
-
- **`get_hook` / `get_pattern` / `get_component`** — the contract, not the source. Does this need a client boundary, does it own the element's transform, what does it conflict with, which frame lane does it run in, and when should you not use it.
|
|
70
|
-
- **`check_motion`** — a static linter for the failure class that ships silently: a private `requestAnimationFrame` loop outside the shared budget, a discarded unsubscribe, `setState` in a frame callback, layout read in the write lane, one transform with two owners, a `<Canvas>` prop that quietly overrules the adapter that set it, a WebGL scene with nothing watching for a lost context, motion with no reduced-motion guard.
|
|
71
|
-
|
|
72
|
-
Prefer to wire it by hand? Add this to your client's MCP config:
|
|
73
|
-
|
|
74
|
-
```json
|
|
75
|
-
{
|
|
76
|
-
"mcpServers": {
|
|
77
|
-
"vectorvesper": {
|
|
78
|
-
"command": "npx",
|
|
79
|
-
"args": ["-y", "vectorvesper", "mcp"]
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Full setup notes and the per-client config paths: [vectorvesper.dev/docs/mcp](https://vectorvesper.dev/docs/mcp).
|
|
86
|
-
|
|
87
|
-
## CLI Command Reference
|
|
88
|
-
|
|
89
|
-
| Command | Description |
|
|
90
|
-
| --- | --- |
|
|
91
|
-
| `init` | Detect project setup and write `vv.config.json` |
|
|
92
|
-
| `add <slug>` | Add a component and auto-install its dependencies |
|
|
93
|
-
| `list` | List all available components in the registry |
|
|
94
|
-
| `update [slug]` | Update installed components to the latest version |
|
|
95
|
-
| `diff [slug]` | Check local files against registry updates |
|
|
96
|
-
| `remove <slug>` | Safely remove a component's files from the project |
|
|
97
|
-
| `mcp install [client]` | Configure the MCP server for your editor(s) |
|
|
98
|
-
| `mcp status` | Check which clients are wired up |
|
|
99
|
-
| `mcp` | Run the MCP server on stdio (what the editor invokes) |
|
|
100
|
-
| `info` | Output workspace diagnostics for troubleshooting |
|
|
101
|
-
|
|
102
|
-
Works out of the box with **npm, pnpm, yarn, and bun** by checking your lockfile.
|
|
103
|
-
|
|
104
|
-
## Links
|
|
105
|
-
|
|
106
|
-
* **Documentation & Guides:** [vectorvesper.dev/docs](https://vectorvesper.dev/docs)
|
|
107
|
-
* **Visual Component Catalog:** [vectorvesper.dev/components](https://vectorvesper.dev/components)
|
|
108
|
-
* **GitHub Repository:** [github.com/vectorvesper/vv-components](https://github.com/vectorvesper/vv-components)
|
|
109
|
-
* **Report Issues:** [github.com/vectorvesper/vv-components/issues](https://github.com/vectorvesper/vv-components/issues)
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
Licensed under the MIT License for open-source components. Premium/commercial components are subject to the Vector Vesper terms of service.
|
|
1
|
+
<!--
|
|
2
|
+
BANNER: host a wide image (≈1280×640) at an ABSOLUTE url — relative paths do
|
|
3
|
+
NOT render on npmjs.com — then uncomment this block:
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://vectorvesper.dev">
|
|
7
|
+
<img src="https://vectorvesper.dev/banner.png" alt="Vector Vesper" width="100%" />
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
<h1 align="center">Vector Vesper</h1>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
Production-grade WebGL, 3D, and motion components for React. Copy directly into your codebase and own the code.
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="https://www.npmjs.com/package/vectorvesper"><img src="https://img.shields.io/npm/v/vectorvesper?color=7EACB5&label=npm" alt="npm version" /></a>
|
|
20
|
+
<a href="https://github.com/vectorvesper/vv-components/blob/main/LICENSE"><img src="https://img.shields.io/github/license/vectorvesper/vv-components?color=7EACB5&label=license" alt="license" /></a>
|
|
21
|
+
<a href="https://vectorvesper.dev"><img src="https://img.shields.io/badge/docs-vectorvesper.dev-7EACB5" alt="docs" /></a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
> Vector Vesper is a CLI you run with `npx`, not a package you install. Start with `npx vectorvesper init` below.
|
|
27
|
+
|
|
28
|
+
**Vector Vesper** is a motion toolkit for React consisting of 3D animations, shaders, and advanced motion components.
|
|
29
|
+
|
|
30
|
+
The CLI writes the component code directly into your repository. You have full control over the math, the shaders, and the styles.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Initialize project configuration
|
|
36
|
+
npx vectorvesper init
|
|
37
|
+
|
|
38
|
+
# Add a visual component
|
|
39
|
+
npx vectorvesper add video-card
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The CLI auto-detects your workspace, installs required animation dependencies (such as `three`, `@react-three/fiber`, or `gsap`), and writes the code to `@/components/vv/`.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { VideoCard } from "@/components/vv/video-card";
|
|
46
|
+
|
|
47
|
+
export default function Page() {
|
|
48
|
+
return (
|
|
49
|
+
<div className="h-screen w-full">
|
|
50
|
+
<VideoCard src="/clip.mp4" />
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## MCP server — motion advice for your coding agent
|
|
57
|
+
|
|
58
|
+
The same CLI runs as an [MCP](https://modelcontextprotocol.io) server, so Claude Code, Cursor, Copilot and friends can ask about motion before they write it.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npx vectorvesper mcp install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
That configures every supported editor it finds. Restart the editor and run `npx vectorvesper mcp status` to confirm. No account or token is needed — the runtime, its contracts and the linter are free.
|
|
65
|
+
|
|
66
|
+
**Why bother.** Bad motion code does not error. TypeScript passes, the build is green, and the page janks on a mid-range phone six weeks later with nothing connecting the two. An agent has no feedback signal for the one quality dimension that matters here, so this server gives it three:
|
|
67
|
+
|
|
68
|
+
- **`plan_motion`** — describe what you are building and get told whether it needs a primitive **at all**, which ones, in what order, and when that advice would be wrong. It says "use CSS, not this" for a hover state, a fade on mount, a spinner or a one-time scroll reveal, because those are compositor features that cost no main-thread time. Roughly a fifth of its answers recommend the platform over this library.
|
|
69
|
+
- **`get_hook` / `get_pattern` / `get_component`** — the contract, not the source. Does this need a client boundary, does it own the element's transform, what does it conflict with, which frame lane does it run in, and when should you not use it.
|
|
70
|
+
- **`check_motion`** — a static linter for the failure class that ships silently: a private `requestAnimationFrame` loop outside the shared budget, a discarded unsubscribe, `setState` in a frame callback, layout read in the write lane, one transform with two owners, a `<Canvas>` prop that quietly overrules the adapter that set it, a WebGL scene with nothing watching for a lost context, motion with no reduced-motion guard.
|
|
71
|
+
|
|
72
|
+
Prefer to wire it by hand? Add this to your client's MCP config:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"mcpServers": {
|
|
77
|
+
"vectorvesper": {
|
|
78
|
+
"command": "npx",
|
|
79
|
+
"args": ["-y", "vectorvesper", "mcp"]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Full setup notes and the per-client config paths: [vectorvesper.dev/docs/mcp](https://vectorvesper.dev/docs/mcp).
|
|
86
|
+
|
|
87
|
+
## CLI Command Reference
|
|
88
|
+
|
|
89
|
+
| Command | Description |
|
|
90
|
+
| --- | --- |
|
|
91
|
+
| `init` | Detect project setup and write `vv.config.json` |
|
|
92
|
+
| `add <slug>` | Add a component and auto-install its dependencies |
|
|
93
|
+
| `list` | List all available components in the registry |
|
|
94
|
+
| `update [slug]` | Update installed components to the latest version |
|
|
95
|
+
| `diff [slug]` | Check local files against registry updates |
|
|
96
|
+
| `remove <slug>` | Safely remove a component's files from the project |
|
|
97
|
+
| `mcp install [client]` | Configure the MCP server for your editor(s) |
|
|
98
|
+
| `mcp status` | Check which clients are wired up |
|
|
99
|
+
| `mcp` | Run the MCP server on stdio (what the editor invokes) |
|
|
100
|
+
| `info` | Output workspace diagnostics for troubleshooting |
|
|
101
|
+
|
|
102
|
+
Works out of the box with **npm, pnpm, yarn, and bun** by checking your lockfile.
|
|
103
|
+
|
|
104
|
+
## Links
|
|
105
|
+
|
|
106
|
+
* **Documentation & Guides:** [vectorvesper.dev/docs](https://vectorvesper.dev/docs)
|
|
107
|
+
* **Visual Component Catalog:** [vectorvesper.dev/components](https://vectorvesper.dev/components)
|
|
108
|
+
* **GitHub Repository:** [github.com/vectorvesper/vv-components](https://github.com/vectorvesper/vv-components)
|
|
109
|
+
* **Report Issues:** [github.com/vectorvesper/vv-components/issues](https://github.com/vectorvesper/vv-components/issues)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
Licensed under the MIT License for open-source components. Premium/commercial components are subject to the Vector Vesper terms of service.
|
|
@@ -130,7 +130,7 @@ var VVConfigSchema = z.object({
|
|
|
130
130
|
})
|
|
131
131
|
});
|
|
132
132
|
var VVGlobalConfigSchema = z.object({
|
|
133
|
-
// Auth —
|
|
133
|
+
// Auth — access token for paid components
|
|
134
134
|
auth: z.object({
|
|
135
135
|
token: z.string().optional(),
|
|
136
136
|
email: z.string().optional(),
|
package/dist/hooks.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.0.0",
|
|
3
|
-
"engineVersion": "4.0.
|
|
4
|
-
"generatedAt": "2026-
|
|
3
|
+
"engineVersion": "4.0.1",
|
|
4
|
+
"generatedAt": "2026-09-02T08:50:45.096Z",
|
|
5
5
|
"contractLevel": "full",
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
@@ -2804,8 +2804,8 @@
|
|
|
2804
2804
|
"practices/react-motion-rules.md",
|
|
2805
2805
|
"practices/adaptive-performance.md"
|
|
2806
2806
|
],
|
|
2807
|
-
"docsUrl": "https://vectorvesper.dev/runtime/
|
|
2808
|
-
"labUrl": "https://vectorvesper.dev/runtime/
|
|
2807
|
+
"docsUrl": "https://vectorvesper.dev/runtime/tick",
|
|
2808
|
+
"labUrl": "https://vectorvesper.dev/runtime/tick",
|
|
2809
2809
|
"disclosure": {
|
|
2810
2810
|
"exposeImplementation": false,
|
|
2811
2811
|
"reason": "Reproducing this hook's implementation makes the consumer run a private requestAnimationFrame loop instead of joining the shared FrameConductor. That silently removes the coordination, scheduling and frame-budget governance the runtime exists to provide, and nothing errors when it happens. Copying is a correctness bug, not just a licensing question.",
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
detectProject,
|
|
4
4
|
fetchComponent,
|
|
5
5
|
fetchRegistryIndex
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BI3LEGXE.js";
|
|
7
7
|
import {
|
|
8
8
|
getAuthToken,
|
|
9
9
|
getGlobalConfigPath,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
setVerbose,
|
|
16
16
|
validateSlug,
|
|
17
17
|
writeConfig
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ZFHVMCR6.js";
|
|
19
19
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
import { Command } from "commander";
|
|
@@ -295,7 +295,7 @@ async function listCommand() {
|
|
|
295
295
|
console.log(`
|
|
296
296
|
${pc2.green(String(freeCount))} free components${proCount > 0 ? ` \xB7 ${pc2.magenta(String(proCount))} pro components` : ""}`);
|
|
297
297
|
if (proCount > 0 && !hasAuth) {
|
|
298
|
-
console.log(` \u{1F511} ${pc2.dim("Unlock pro components:")} ${pc2.cyan("npx vectorvesper login <
|
|
298
|
+
console.log(` \u{1F511} ${pc2.dim("Unlock pro components:")} ${pc2.cyan("npx vectorvesper login <token>")} ${pc2.dim("\xB7")} ${pc2.cyan("https://vectorvesper.dev/pricing")}`);
|
|
299
299
|
}
|
|
300
300
|
console.log(`
|
|
301
301
|
\u{1F449} Run ${pc2.bold(pc2.cyan("npx vectorvesper add <slug>"))} to add a component to your project.
|
|
@@ -303,7 +303,8 @@ async function listCommand() {
|
|
|
303
303
|
} catch (error) {
|
|
304
304
|
const message = error instanceof Error ? error.message : String(error);
|
|
305
305
|
spinner.fail(pc2.red(`Failed to fetch components list: ${message}`));
|
|
306
|
-
process.
|
|
306
|
+
process.exitCode = 1;
|
|
307
|
+
return;
|
|
307
308
|
}
|
|
308
309
|
}
|
|
309
310
|
|
|
@@ -758,7 +759,7 @@ async function addCommand(slug, options = {}) {
|
|
|
758
759
|
} catch (error) {
|
|
759
760
|
const message = error instanceof Error ? error.message : String(error);
|
|
760
761
|
spinner.fail(pc5.red(`Failed to resolve component "${slug}": ${message}`));
|
|
761
|
-
process.
|
|
762
|
+
process.exitCode = 1;
|
|
762
763
|
return;
|
|
763
764
|
}
|
|
764
765
|
let transpileWarnings = [];
|
|
@@ -780,7 +781,7 @@ async function addCommand(slug, options = {}) {
|
|
|
780
781
|
} catch (error) {
|
|
781
782
|
const message = error instanceof Error ? error.message : String(error);
|
|
782
783
|
spinner.fail(pc5.red(message));
|
|
783
|
-
process.
|
|
784
|
+
process.exitCode = 1;
|
|
784
785
|
return;
|
|
785
786
|
}
|
|
786
787
|
const filesToWrite = [];
|
|
@@ -856,7 +857,7 @@ async function addCommand(slug, options = {}) {
|
|
|
856
857
|
} catch (error) {
|
|
857
858
|
const message = error instanceof Error ? error.message : String(error);
|
|
858
859
|
spinner.fail(pc5.red(`Failed to write files: ${message}`));
|
|
859
|
-
process.
|
|
860
|
+
process.exitCode = 1;
|
|
860
861
|
return;
|
|
861
862
|
}
|
|
862
863
|
try {
|
|
@@ -1018,7 +1019,7 @@ async function updateCommand(slug, options = {}) {
|
|
|
1018
1019
|
if (updatedComponents.length > 0) {
|
|
1019
1020
|
await handleDependencies(updatedComponents, projectRoot, projectInfo, options);
|
|
1020
1021
|
}
|
|
1021
|
-
if (failed.length > 0) process.
|
|
1022
|
+
if (failed.length > 0) process.exitCode = 1;
|
|
1022
1023
|
}
|
|
1023
1024
|
|
|
1024
1025
|
// src/commands/remove.ts
|
|
@@ -1122,7 +1123,7 @@ Remove ${slug}
|
|
|
1122
1123
|
import fs7 from "fs";
|
|
1123
1124
|
import path7 from "path";
|
|
1124
1125
|
import pc8 from "picocolors";
|
|
1125
|
-
var CLI_VERSION = true ? "2.
|
|
1126
|
+
var CLI_VERSION = true ? "2.6.0" : "0.0.0-dev";
|
|
1126
1127
|
async function infoCommand() {
|
|
1127
1128
|
console.log(pc8.bold(pc8.cyan("\nVector Vesper Diagnostics\n")));
|
|
1128
1129
|
const projectInfo = detectProject();
|
|
@@ -1255,7 +1256,8 @@ Component Diff: ${slug}`)));
|
|
|
1255
1256
|
} catch (error) {
|
|
1256
1257
|
const message = error instanceof Error ? error.message : String(error);
|
|
1257
1258
|
spinner.fail(pc9.red(`Failed to fetch remote component details: ${message}`));
|
|
1258
|
-
process.
|
|
1259
|
+
process.exitCode = 1;
|
|
1260
|
+
return;
|
|
1259
1261
|
}
|
|
1260
1262
|
} else {
|
|
1261
1263
|
const spinner = ora4({
|
|
@@ -1320,7 +1322,8 @@ ${pc9.green("\u2714")} All components are up to date!
|
|
|
1320
1322
|
} catch (error) {
|
|
1321
1323
|
const message = error instanceof Error ? error.message : String(error);
|
|
1322
1324
|
spinner.fail(pc9.red(`Failed to check updates: ${message}`));
|
|
1323
|
-
process.
|
|
1325
|
+
process.exitCode = 1;
|
|
1326
|
+
return;
|
|
1324
1327
|
}
|
|
1325
1328
|
}
|
|
1326
1329
|
}
|
|
@@ -1420,7 +1423,7 @@ async function whoamiCommand() {
|
|
|
1420
1423
|
}
|
|
1421
1424
|
|
|
1422
1425
|
// src/index.ts
|
|
1423
|
-
var version = true ? "2.
|
|
1426
|
+
var version = true ? "2.6.0" : "0.0.0-dev";
|
|
1424
1427
|
var program = new Command();
|
|
1425
1428
|
program.name("vv").description("Vector Vesper CLI \u2014 add visual components to your React project").version(version).option("--verbose", "Show detailed debug output").hook("preAction", (thisCommand) => {
|
|
1426
1429
|
const opts = thisCommand.opts();
|
|
@@ -1449,20 +1452,20 @@ program.command("info").description("Show project diagnostics and list installed
|
|
|
1449
1452
|
program.command("diff [slug]").description("Check for updates against the component registry").action(async (slug) => {
|
|
1450
1453
|
await diffCommand(slug);
|
|
1451
1454
|
});
|
|
1452
|
-
program.command("login <
|
|
1455
|
+
program.command("login <token>").description("Authenticate with an access token for pro components").action(async (key) => {
|
|
1453
1456
|
await loginCommand(key);
|
|
1454
1457
|
});
|
|
1455
|
-
program.command("logout"
|
|
1458
|
+
program.command("logout").description("Clear the stored access token").action(async () => {
|
|
1456
1459
|
await logoutCommand();
|
|
1457
1460
|
});
|
|
1458
|
-
program.command("whoami"
|
|
1461
|
+
program.command("whoami").description("Show current authentication status").action(async () => {
|
|
1459
1462
|
await whoamiCommand();
|
|
1460
1463
|
});
|
|
1461
1464
|
program.command("mcp [action] [client]").description(
|
|
1462
1465
|
"Run as an MCP server (stdio) for AI coding agents. `vv mcp install` wires it into your editor; `vv mcp status` checks the setup."
|
|
1463
1466
|
).option("--stdio", "Force server mode even from an interactive terminal").option("-g, --global", "Write user-level config instead of project-level (install)").action(
|
|
1464
1467
|
async (action, client, options) => {
|
|
1465
|
-
const { mcpCommand } = await import("./mcp-
|
|
1468
|
+
const { mcpCommand } = await import("./mcp-BEM4TVKM.js");
|
|
1466
1469
|
await mcpCommand(action, { ...options, client });
|
|
1467
1470
|
}
|
|
1468
1471
|
);
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-CPZKZO3A.js";
|
|
4
4
|
import {
|
|
5
5
|
getAuthToken
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ZFHVMCR6.js";
|
|
7
7
|
|
|
8
8
|
// src/commands/mcp.ts
|
|
9
9
|
import pc from "picocolors";
|
|
@@ -12,7 +12,7 @@ import pc from "picocolors";
|
|
|
12
12
|
import fs from "fs";
|
|
13
13
|
import os from "os";
|
|
14
14
|
import path from "path";
|
|
15
|
-
var CLIENT_IDS = ["claude", "cursor", "antigravity", "opencode"];
|
|
15
|
+
var CLIENT_IDS = ["claude", "cursor", "windsurf", "antigravity", "opencode"];
|
|
16
16
|
var SERVER_NAME = "vectorvesper";
|
|
17
17
|
var ARGS = ["-y", "vectorvesper@latest", "mcp", "--stdio"];
|
|
18
18
|
function home(...parts) {
|
|
@@ -32,6 +32,14 @@ var CLIENTS = {
|
|
|
32
32
|
globalPath: home(".cursor", "mcp.json"),
|
|
33
33
|
dialect: "mcpServers"
|
|
34
34
|
},
|
|
35
|
+
windsurf: {
|
|
36
|
+
label: "Windsurf",
|
|
37
|
+
// Windsurf reads one user-level file; there is no workspace scope, so a
|
|
38
|
+
// --global flag would have nothing to switch to.
|
|
39
|
+
projectPath: null,
|
|
40
|
+
globalPath: home(".codeium", "windsurf", "mcp_config.json"),
|
|
41
|
+
dialect: "mcpServers"
|
|
42
|
+
},
|
|
35
43
|
antigravity: {
|
|
36
44
|
label: "Antigravity",
|
|
37
45
|
// Workspace scope lives under .agents/; the global file is shared by the
|
|
@@ -138,7 +146,7 @@ function detectClients(cwd = process.cwd()) {
|
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
// src/commands/mcp.ts
|
|
141
|
-
var VERSION = true ? "2.
|
|
149
|
+
var VERSION = true ? "2.6.0" : "0.0.0-dev";
|
|
142
150
|
var CONFIG_SNIPPET = `{
|
|
143
151
|
"mcpServers": {
|
|
144
152
|
"vectorvesper": {
|
|
@@ -285,7 +293,7 @@ ${pc.red("\u2717")} Unknown argument "${action}" for \`vv mcp\`.
|
|
|
285
293
|
return;
|
|
286
294
|
}
|
|
287
295
|
protectStdout();
|
|
288
|
-
const { startMcpServer } = await import("./server-
|
|
296
|
+
const { startMcpServer } = await import("./server-CIFO3HSN.js");
|
|
289
297
|
try {
|
|
290
298
|
await startMcpServer();
|
|
291
299
|
} catch (error) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectProject,
|
|
3
3
|
fetchRegistryIndex
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BI3LEGXE.js";
|
|
5
5
|
import {
|
|
6
6
|
findHook,
|
|
7
7
|
findPattern,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./chunk-CPZKZO3A.js";
|
|
10
10
|
import {
|
|
11
11
|
getAuthToken
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ZFHVMCR6.js";
|
|
13
13
|
|
|
14
14
|
// src/mcp/server.ts
|
|
15
15
|
import { z } from "zod";
|
|
@@ -38,6 +38,7 @@ var VV_ACCESSORS = /* @__PURE__ */ new Set([
|
|
|
38
38
|
"getFramePressure",
|
|
39
39
|
"getRendererHealth"
|
|
40
40
|
]);
|
|
41
|
+
var CONTEXT_EVENTS = /* @__PURE__ */ new Set(["webglcontextlost", "webglcontextrestored"]);
|
|
41
42
|
var TEARDOWN_RETURNING = /* @__PURE__ */ new Set(["subscribe", "retain"]);
|
|
42
43
|
var LAYOUT_READ_PROPS = /* @__PURE__ */ new Set([
|
|
43
44
|
"offsetWidth",
|
|
@@ -84,10 +85,26 @@ function collectReactSetters(ast, traverse) {
|
|
|
84
85
|
});
|
|
85
86
|
return names;
|
|
86
87
|
}
|
|
87
|
-
function accessorName(
|
|
88
|
+
function accessorName(calleePath) {
|
|
89
|
+
const callee = calleePath?.node ?? calleePath;
|
|
88
90
|
const obj = callee?.object;
|
|
89
|
-
if (obj
|
|
90
|
-
|
|
91
|
+
if (!obj) return void 0;
|
|
92
|
+
if (obj.type === "CallExpression" || obj.type === "OptionalCallExpression") {
|
|
93
|
+
return obj.callee?.type === "Identifier" ? obj.callee.name : void 0;
|
|
94
|
+
}
|
|
95
|
+
if (obj.type === "Identifier" && typeof calleePath?.get === "function") {
|
|
96
|
+
const binding = calleePath.scope?.getBinding(obj.name);
|
|
97
|
+
const init = binding?.path?.node?.init;
|
|
98
|
+
if (init && (init.type === "CallExpression" || init.type === "OptionalCallExpression")) {
|
|
99
|
+
return init.callee?.type === "Identifier" ? init.callee.name : void 0;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return void 0;
|
|
103
|
+
}
|
|
104
|
+
function unsubscribeBinding(callPath) {
|
|
105
|
+
const declarator = callPath?.parentPath;
|
|
106
|
+
if (declarator?.node?.type !== "VariableDeclarator") return void 0;
|
|
107
|
+
return declarator.node.id?.type === "Identifier" ? declarator.node.id.name : void 0;
|
|
91
108
|
}
|
|
92
109
|
function asProgram(cbNode) {
|
|
93
110
|
if (!cbNode) return null;
|
|
@@ -129,6 +146,7 @@ function collect(ast, traverse) {
|
|
|
129
146
|
laneViolations: [],
|
|
130
147
|
orphanSubscriptions: [],
|
|
131
148
|
canvases: [],
|
|
149
|
+
rawGlContexts: [],
|
|
132
150
|
handlesContextLoss: false,
|
|
133
151
|
gatingObserver: []
|
|
134
152
|
};
|
|
@@ -150,21 +168,72 @@ function collect(ast, traverse) {
|
|
|
150
168
|
if (init && (init.type === "ArrowFunctionExpression" || init.type === "FunctionExpression")) return init;
|
|
151
169
|
return null;
|
|
152
170
|
};
|
|
153
|
-
const scanHotCallback = (cbNode, ctx, fromRaf) => {
|
|
171
|
+
const scanHotCallback = (cbNode, ctx, fromRaf, unsubName) => {
|
|
154
172
|
const file = asProgram(cbNode);
|
|
155
173
|
if (!file) return;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
174
|
+
const isTerminal = (setterPath) => {
|
|
175
|
+
if (!unsubName) return false;
|
|
176
|
+
let node = setterPath;
|
|
177
|
+
while (node) {
|
|
178
|
+
if (node.node?.type === "BlockStatement") {
|
|
179
|
+
const parent = node.parentPath?.node?.type;
|
|
180
|
+
if (parent === "ArrowFunctionExpression" || parent === "FunctionExpression" || parent === "FunctionDeclaration") {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
let found = false;
|
|
184
|
+
node.traverse({
|
|
185
|
+
CallExpression(inner) {
|
|
186
|
+
if (inner.node.callee?.type === "Identifier" && inner.node.callee.name === unsubName) {
|
|
187
|
+
found = true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
if (found) return true;
|
|
160
192
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
193
|
+
node = node.parentPath;
|
|
194
|
+
}
|
|
195
|
+
return false;
|
|
196
|
+
};
|
|
197
|
+
const isLatched = (setterPath) => {
|
|
198
|
+
let node = setterPath;
|
|
199
|
+
while (node) {
|
|
200
|
+
const parent = node.parentPath;
|
|
201
|
+
if (parent?.node?.type === "IfStatement" && parent.node.test) {
|
|
202
|
+
const guards = /* @__PURE__ */ new Set();
|
|
203
|
+
const collect2 = (n) => {
|
|
204
|
+
if (!n || typeof n.type !== "string") return;
|
|
205
|
+
if (n.type === "Identifier") guards.add(n.name);
|
|
206
|
+
for (const key of Object.keys(n)) {
|
|
207
|
+
const v = n[key];
|
|
208
|
+
if (Array.isArray(v)) v.forEach(collect2);
|
|
209
|
+
else if (v && typeof v.type === "string") collect2(v);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
collect2(parent.node.test);
|
|
213
|
+
let latched = false;
|
|
214
|
+
const check = (inner) => {
|
|
215
|
+
const target = inner.node.left ?? inner.node.argument;
|
|
216
|
+
if (target?.type === "Identifier" && guards.has(target.name)) latched = true;
|
|
217
|
+
};
|
|
218
|
+
if (typeof node.traverse === "function") {
|
|
219
|
+
node.traverse({ AssignmentExpression: check, UpdateExpression: check });
|
|
220
|
+
}
|
|
221
|
+
if (latched) return true;
|
|
165
222
|
}
|
|
223
|
+
node = parent;
|
|
166
224
|
}
|
|
167
|
-
|
|
225
|
+
return false;
|
|
226
|
+
};
|
|
227
|
+
const onCall = (p) => {
|
|
228
|
+
if (!isStateSetterCall(p.node.callee, reactSetters)) return;
|
|
229
|
+
f.setStateInHot.push({
|
|
230
|
+
line: cbNode.loc?.start.line ?? 0,
|
|
231
|
+
ctx,
|
|
232
|
+
fromRaf,
|
|
233
|
+
gated: isTerminal(p) || isLatched(p)
|
|
234
|
+
});
|
|
235
|
+
};
|
|
236
|
+
traverse(file, { CallExpression: onCall, OptionalCallExpression: onCall });
|
|
168
237
|
};
|
|
169
238
|
const containsStateSetter = (cbNode) => {
|
|
170
239
|
const file = asProgram(cbNode);
|
|
@@ -225,7 +294,13 @@ function collect(ast, traverse) {
|
|
|
225
294
|
f.frameCallbacks.push({ line, lane, via });
|
|
226
295
|
const cb = resolveFunction(argPaths[1]);
|
|
227
296
|
if (!cb) return;
|
|
228
|
-
|
|
297
|
+
const unsubName = unsubscribeBinding(p);
|
|
298
|
+
scanHotCallback(
|
|
299
|
+
cb,
|
|
300
|
+
lane ? `a \`${via}("${lane}")\` frame callback` : `a \`${via}\` frame callback`,
|
|
301
|
+
false,
|
|
302
|
+
unsubName
|
|
303
|
+
);
|
|
229
304
|
if (lane === "input" || lane === "update" || lane === "render") scanLaneDiscipline(cb, lane, via);
|
|
230
305
|
};
|
|
231
306
|
const handleCall = (p) => {
|
|
@@ -252,7 +327,9 @@ function collect(ast, traverse) {
|
|
|
252
327
|
f.hasClearInterval = true;
|
|
253
328
|
break;
|
|
254
329
|
case "addEventListener": {
|
|
255
|
-
|
|
330
|
+
const evNode = node.arguments?.[0];
|
|
331
|
+
const evName = evNode?.type === "StringLiteral" ? evNode.value : null;
|
|
332
|
+
if (!evName || !CONTEXT_EVENTS.has(evName)) f.addEventListener.push(line);
|
|
256
333
|
const ev = node.arguments?.[0];
|
|
257
334
|
if (ev?.type === "StringLiteral" && HOT_EVENTS.has(ev.value)) {
|
|
258
335
|
scanHotCallback(resolveFunction(argPaths[1]), `a "${ev.value}" listener`, false);
|
|
@@ -271,6 +348,13 @@ function collect(ast, traverse) {
|
|
|
271
348
|
case "matchMedia":
|
|
272
349
|
f.hasReducedMotionGuard = true;
|
|
273
350
|
break;
|
|
351
|
+
case "getContext": {
|
|
352
|
+
const kind = node.arguments?.[0];
|
|
353
|
+
if (kind?.type === "StringLiteral" && /^(webgl2?|experimental-webgl)$/.test(kind.value)) {
|
|
354
|
+
f.rawGlContexts.push(line);
|
|
355
|
+
}
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
274
358
|
case "kill":
|
|
275
359
|
case "revert":
|
|
276
360
|
f.hasGsapCleanup = true;
|
|
@@ -280,7 +364,7 @@ function collect(ast, traverse) {
|
|
|
280
364
|
break;
|
|
281
365
|
case "subscribe":
|
|
282
366
|
case "retain": {
|
|
283
|
-
const accessor = accessorName(node.callee);
|
|
367
|
+
const accessor = accessorName(typeof p.get === "function" ? p.get("callee") : node.callee);
|
|
284
368
|
if (!accessor || !VV_ACCESSORS.has(accessor)) break;
|
|
285
369
|
if (name === "subscribe" && accessor === "getConductor") {
|
|
286
370
|
recordFrameCallback(p, argPaths, "getConductor().subscribe");
|
|
@@ -327,7 +411,9 @@ function collect(ast, traverse) {
|
|
|
327
411
|
const v = p.node.value;
|
|
328
412
|
if (v.includes("prefers-reduced-motion")) f.hasReducedMotionGuard = true;
|
|
329
413
|
if (v === "webglcontextlost" || v === "webglcontextrestored") f.handlesContextLoss = true;
|
|
330
|
-
if (/\binfinite\b/.test(v))
|
|
414
|
+
if (/\binfinite\b/.test(v) && /\b\d+(?:\.\d+)?m?s\b/.test(v)) {
|
|
415
|
+
f.looping.push({ line: p.node.loc?.start.line ?? 0, kind: "CSS `infinite` animation" });
|
|
416
|
+
}
|
|
331
417
|
if (/\btransition\b|\banimation\b/.test(v) && /\btransform\b|\ball\b/.test(v)) {
|
|
332
418
|
f.transformAuthorities.push({ line: p.node.loc?.start.line ?? 0, source: "a CSS transition/animation" });
|
|
333
419
|
}
|
|
@@ -499,7 +585,7 @@ function checkMissingCleanup(f, file) {
|
|
|
499
585
|
return out;
|
|
500
586
|
}
|
|
501
587
|
function checkSetStatePerFrame(f, file) {
|
|
502
|
-
const hot = f.setStateInHot.filter((s) => !s.fromRaf || isRafLoop(f));
|
|
588
|
+
const hot = f.setStateInHot.filter((s) => (!s.fromRaf || isRafLoop(f)) && !s.gated);
|
|
503
589
|
if (hot.length === 0) return [];
|
|
504
590
|
const zeroReRender = f.vvHooks.find((v) => v.hook.runtime.reRendersPerFrame === 0);
|
|
505
591
|
const first = hot[0];
|
|
@@ -583,7 +669,9 @@ function checkRenderQualityProps(f, file) {
|
|
|
583
669
|
return out;
|
|
584
670
|
}
|
|
585
671
|
function checkContextLoss(f, file) {
|
|
586
|
-
|
|
672
|
+
const r3fCanvas = f.usesR3F && f.canvases.length > 0;
|
|
673
|
+
const rawContext = f.rawGlContexts.length > 0;
|
|
674
|
+
if (!r3fCanvas && !rawContext) return [];
|
|
587
675
|
const handled = f.handlesContextLoss || f.vvImports.has("useRenderQuality") || f.vvImports.has("getRendererHealth");
|
|
588
676
|
if (handled) return [];
|
|
589
677
|
return [
|
|
@@ -591,15 +679,16 @@ function checkContextLoss(f, file) {
|
|
|
591
679
|
rule: "webgl-context-loss",
|
|
592
680
|
severity: "warning",
|
|
593
681
|
file,
|
|
594
|
-
line: f.canvases[0].line,
|
|
682
|
+
line: r3fCanvas ? f.canvases[0].line : f.rawGlContexts[0],
|
|
595
683
|
message: "Nothing in this file notices a lost graphics context. When the browser takes one away the canvas goes black permanently and nothing is logged, so it reads as a rendering bug rather than a recoverable event.",
|
|
596
|
-
fix: "Spread `useRenderQuality`'s props onto the canvas and key it on a scene gate's `generation` \u2014 the `onCreated` it returns attaches the listener and reports the loss, and the moving key rebuilds the tree against a fresh context. Failing that, attach a `webglcontextlost` listener that calls `preventDefault()` (without it some drivers refuse a replacement context outright) and report to `getRendererHealth()`.",
|
|
684
|
+
fix: (r3fCanvas ? "Spread `useRenderQuality`'s props onto the canvas and key it on a scene gate's `generation` \u2014 the `onCreated` it returns attaches the listener and reports the loss, and the moving key rebuilds the tree against a fresh context. Failing that, attach a " : "You created this context by hand, so the adapter does not apply. Attach a ") + "`webglcontextlost` listener that calls `preventDefault()` (without it some drivers refuse a replacement context outright) and report to `getRendererHealth()`.",
|
|
597
685
|
nudge: 'Call `get_pattern("lazy-3d-section")` for the whole wiring.'
|
|
598
686
|
}
|
|
599
687
|
];
|
|
600
688
|
}
|
|
601
689
|
function checkHandRolledGate(f, file) {
|
|
602
|
-
|
|
690
|
+
const ownsGpu = f.usesR3F && f.canvases.length > 0 || f.rawGlContexts.length > 0;
|
|
691
|
+
if (!ownsGpu) return [];
|
|
603
692
|
if (f.gatingObserver.length === 0 || f.vvImports.has("useSceneGate")) return [];
|
|
604
693
|
return [
|
|
605
694
|
{
|
|
@@ -886,7 +975,7 @@ function formatPlan({ building, using }) {
|
|
|
886
975
|
}
|
|
887
976
|
|
|
888
977
|
// src/mcp/server.ts
|
|
889
|
-
var VERSION = true ? "2.
|
|
978
|
+
var VERSION = true ? "2.6.0" : "0.0.0-dev";
|
|
890
979
|
function text(body) {
|
|
891
980
|
return { content: [{ type: "text", text: body }] };
|
|
892
981
|
}
|
package/package.json
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "vectorvesper",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Motion runtime and WebGL/R3F component CLI for React, with an MCP server that tells your coding agent which primitive to use, how to wire it, and when not to.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"main": "./dist/index.js",
|
|
8
|
-
"bin": {
|
|
9
|
-
"vectorvesper": "dist/index.js",
|
|
10
|
-
"vv": "dist/index.js"
|
|
11
|
-
},
|
|
12
|
-
"files": [
|
|
13
|
-
"dist",
|
|
14
|
-
"package.json"
|
|
15
|
-
],
|
|
16
|
-
"engines": {
|
|
17
|
-
"node": ">=18"
|
|
18
|
-
},
|
|
19
|
-
"repository": {
|
|
20
|
-
"type": "git",
|
|
21
|
-
"url": "git+https://github.com/vectorvesper/vv-components.git"
|
|
22
|
-
},
|
|
23
|
-
"bugs": {
|
|
24
|
-
"url": "https://github.com/vectorvesper/vv-components/issues"
|
|
25
|
-
},
|
|
26
|
-
"homepage": "https://vectorvesper.dev",
|
|
27
|
-
"keywords": [
|
|
28
|
-
"mcp",
|
|
29
|
-
"model-context-protocol",
|
|
30
|
-
"mcp-server",
|
|
31
|
-
"ai",
|
|
32
|
-
"agent",
|
|
33
|
-
"claude",
|
|
34
|
-
"cursor",
|
|
35
|
-
"copilot",
|
|
36
|
-
"react",
|
|
37
|
-
"webgl",
|
|
38
|
-
"three",
|
|
39
|
-
"threejs",
|
|
40
|
-
"react-three-fiber",
|
|
41
|
-
"components",
|
|
42
|
-
"cli",
|
|
43
|
-
"ui",
|
|
44
|
-
"animation",
|
|
45
|
-
"motion",
|
|
46
|
-
"gsap",
|
|
47
|
-
"shader",
|
|
48
|
-
"interactive",
|
|
49
|
-
"performance",
|
|
50
|
-
"requestanimationframe"
|
|
51
|
-
],
|
|
52
|
-
"scripts": {
|
|
53
|
-
"build": "tsup",
|
|
54
|
-
"dev": "tsup --watch",
|
|
55
|
-
"typecheck": "tsc --noEmit",
|
|
56
|
-
"test": "vitest run",
|
|
57
|
-
"test:watch": "vitest",
|
|
58
|
-
"test:mcp": "node scripts/mcp-e2e/harness.mjs --local",
|
|
59
|
-
"test:mcp:published": "node scripts/mcp-e2e/harness.mjs",
|
|
60
|
-
"postbuild": "node scripts/bundle-manifest.mjs",
|
|
61
|
-
"prepublishOnly": "npm run build"
|
|
62
|
-
},
|
|
63
|
-
"dependencies": {
|
|
64
|
-
"@babel/core": "^7.24.0",
|
|
65
|
-
"@babel/preset-typescript": "^7.24.0",
|
|
66
|
-
"@clack/prompts": "^0.7.0",
|
|
67
|
-
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
68
|
-
"commander": "^12.0.0",
|
|
69
|
-
"ora": "^8.0.1",
|
|
70
|
-
"picocolors": "^1.0.0",
|
|
71
|
-
"zod": "^3.22.4"
|
|
72
|
-
},
|
|
73
|
-
"devDependencies": {
|
|
74
|
-
"@types/babel__core": "^7.20.5",
|
|
75
|
-
"@types/node": "^25.9.2",
|
|
76
|
-
"tsup": "^8.0.2",
|
|
77
|
-
"typescript": "^6.0.3",
|
|
78
|
-
"vitest": "^2.1.8"
|
|
79
|
-
},
|
|
80
|
-
"mcpName": "dev.vectorvesper/motion"
|
|
81
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "vectorvesper",
|
|
3
|
+
"version": "2.6.0",
|
|
4
|
+
"description": "Motion runtime and WebGL/R3F component CLI for React, with an MCP server that tells your coding agent which primitive to use, how to wire it, and when not to.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"bin": {
|
|
9
|
+
"vectorvesper": "dist/index.js",
|
|
10
|
+
"vv": "dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"package.json"
|
|
15
|
+
],
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/vectorvesper/vv-components.git"
|
|
22
|
+
},
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/vectorvesper/vv-components/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://vectorvesper.dev",
|
|
27
|
+
"keywords": [
|
|
28
|
+
"mcp",
|
|
29
|
+
"model-context-protocol",
|
|
30
|
+
"mcp-server",
|
|
31
|
+
"ai",
|
|
32
|
+
"agent",
|
|
33
|
+
"claude",
|
|
34
|
+
"cursor",
|
|
35
|
+
"copilot",
|
|
36
|
+
"react",
|
|
37
|
+
"webgl",
|
|
38
|
+
"three",
|
|
39
|
+
"threejs",
|
|
40
|
+
"react-three-fiber",
|
|
41
|
+
"components",
|
|
42
|
+
"cli",
|
|
43
|
+
"ui",
|
|
44
|
+
"animation",
|
|
45
|
+
"motion",
|
|
46
|
+
"gsap",
|
|
47
|
+
"shader",
|
|
48
|
+
"interactive",
|
|
49
|
+
"performance",
|
|
50
|
+
"requestanimationframe"
|
|
51
|
+
],
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsup",
|
|
54
|
+
"dev": "tsup --watch",
|
|
55
|
+
"typecheck": "tsc --noEmit",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"test:watch": "vitest",
|
|
58
|
+
"test:mcp": "node scripts/mcp-e2e/harness.mjs --local",
|
|
59
|
+
"test:mcp:published": "node scripts/mcp-e2e/harness.mjs",
|
|
60
|
+
"postbuild": "node scripts/bundle-manifest.mjs",
|
|
61
|
+
"prepublishOnly": "npm run build"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@babel/core": "^7.24.0",
|
|
65
|
+
"@babel/preset-typescript": "^7.24.0",
|
|
66
|
+
"@clack/prompts": "^0.7.0",
|
|
67
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
68
|
+
"commander": "^12.0.0",
|
|
69
|
+
"ora": "^8.0.1",
|
|
70
|
+
"picocolors": "^1.0.0",
|
|
71
|
+
"zod": "^3.22.4"
|
|
72
|
+
},
|
|
73
|
+
"devDependencies": {
|
|
74
|
+
"@types/babel__core": "^7.20.5",
|
|
75
|
+
"@types/node": "^25.9.2",
|
|
76
|
+
"tsup": "^8.0.2",
|
|
77
|
+
"typescript": "^6.0.3",
|
|
78
|
+
"vitest": "^2.1.8"
|
|
79
|
+
},
|
|
80
|
+
"mcpName": "dev.vectorvesper/motion"
|
|
81
|
+
}
|