gravity-core 1.0.22 → 1.0.24
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/mcp-server.js +1 -1
- package/dist/native-host.js +35 -127
- package/dist/native-host.js.map +1 -1
- package/extension/manifest.json +1 -1
- package/package.json +2 -1
package/dist/mcp-server.js
CHANGED
package/dist/native-host.js
CHANGED
|
@@ -10,94 +10,19 @@
|
|
|
10
10
|
* MCP Server ← WebSocket → Native Host ← Native Messaging → Extension ← CDP → Browser
|
|
11
11
|
*/
|
|
12
12
|
import { WebSocketServer, WebSocket } from 'ws';
|
|
13
|
+
import { createRequire } from 'module';
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
// @ts-ignore - no types available
|
|
16
|
+
const nativeMessage = require('chrome-native-messaging');
|
|
13
17
|
const WS_PORT = 9224;
|
|
14
18
|
let wsServer = null;
|
|
15
19
|
let wsClient = null;
|
|
16
|
-
/**
|
|
17
|
-
* Read native messaging message from stdin
|
|
18
|
-
*/
|
|
19
|
-
function readNativeMessage() {
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
const headerBuffer = Buffer.alloc(4);
|
|
22
|
-
let headerBytesRead = 0;
|
|
23
|
-
const readHeader = () => {
|
|
24
|
-
const chunk = process.stdin.read(4 - headerBytesRead);
|
|
25
|
-
if (chunk === null) {
|
|
26
|
-
// No data available yet, wait for readable event
|
|
27
|
-
process.stdin.once('readable', readHeader);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
if (chunk.length === 0) {
|
|
31
|
-
// EOF
|
|
32
|
-
reject(new Error('EOF: stdin closed'));
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
chunk.copy(headerBuffer, headerBytesRead);
|
|
36
|
-
headerBytesRead += chunk.length;
|
|
37
|
-
if (headerBytesRead === 4) {
|
|
38
|
-
const messageLength = headerBuffer.readUInt32LE(0);
|
|
39
|
-
if (messageLength === 0 || messageLength > 1024 * 1024) {
|
|
40
|
-
reject(new Error(`Invalid message length: ${messageLength}`));
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
readMessage(messageLength);
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
process.stdin.once('readable', readHeader);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
const readMessage = (length) => {
|
|
50
|
-
const messageBuffer = Buffer.alloc(length);
|
|
51
|
-
let messageBytesRead = 0;
|
|
52
|
-
const readChunk = () => {
|
|
53
|
-
const chunk = process.stdin.read(length - messageBytesRead);
|
|
54
|
-
if (chunk === null) {
|
|
55
|
-
// No data available yet, wait for readable event
|
|
56
|
-
process.stdin.once('readable', readChunk);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
if (chunk.length === 0) {
|
|
60
|
-
// EOF
|
|
61
|
-
reject(new Error('EOF: stdin closed during message read'));
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
chunk.copy(messageBuffer, messageBytesRead);
|
|
65
|
-
messageBytesRead += chunk.length;
|
|
66
|
-
if (messageBytesRead === length) {
|
|
67
|
-
try {
|
|
68
|
-
const message = JSON.parse(messageBuffer.toString('utf-8'));
|
|
69
|
-
resolve(message);
|
|
70
|
-
}
|
|
71
|
-
catch (error) {
|
|
72
|
-
reject(new Error(`Failed to parse JSON: ${error}`));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
process.stdin.once('readable', readChunk);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
readChunk();
|
|
80
|
-
};
|
|
81
|
-
readHeader();
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Send native messaging message to stdout
|
|
86
|
-
*/
|
|
87
|
-
function sendNativeMessage(message) {
|
|
88
|
-
const messageStr = JSON.stringify(message);
|
|
89
|
-
const messageBuffer = Buffer.from(messageStr, 'utf-8');
|
|
90
|
-
const headerBuffer = Buffer.alloc(4);
|
|
91
|
-
headerBuffer.writeUInt32LE(messageBuffer.length, 0);
|
|
92
|
-
process.stdout.write(headerBuffer);
|
|
93
|
-
process.stdout.write(messageBuffer);
|
|
94
|
-
}
|
|
95
20
|
/**
|
|
96
21
|
* Start WebSocket server for MCP connections
|
|
97
22
|
*/
|
|
98
23
|
function startWebSocketServer() {
|
|
99
24
|
wsServer = new WebSocketServer({ port: WS_PORT });
|
|
100
|
-
console.error(
|
|
25
|
+
console.error('[Native Host] WebSocket server listening on port', WS_PORT);
|
|
101
26
|
wsServer.on('connection', (ws) => {
|
|
102
27
|
console.error('[Native Host] MCP server connected');
|
|
103
28
|
wsClient = ws;
|
|
@@ -105,8 +30,8 @@ function startWebSocketServer() {
|
|
|
105
30
|
try {
|
|
106
31
|
const message = JSON.parse(data.toString());
|
|
107
32
|
console.error('[Native Host] MCP → Extension:', message.type || message.method);
|
|
108
|
-
// Forward to extension via native messaging
|
|
109
|
-
|
|
33
|
+
// Forward to extension via native messaging (stdout)
|
|
34
|
+
output.write(message);
|
|
110
35
|
}
|
|
111
36
|
catch (error) {
|
|
112
37
|
console.error('[Native Host] Error processing WebSocket message:', error.message);
|
|
@@ -126,57 +51,43 @@ function startWebSocketServer() {
|
|
|
126
51
|
});
|
|
127
52
|
}
|
|
128
53
|
/**
|
|
129
|
-
*
|
|
54
|
+
* Setup Native Messaging streams
|
|
130
55
|
*/
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
console.error('[Native Host] Extension → MCP:', message.type);
|
|
139
|
-
// Forward to MCP server via WebSocket
|
|
140
|
-
if (wsClient && wsClient.readyState === WebSocket.OPEN) {
|
|
141
|
-
wsClient.send(JSON.stringify(message));
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
console.error('[Native Host] No MCP client connected, message dropped');
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
catch (error) {
|
|
148
|
-
if (error.message.includes('EOF') || error.message.includes('end')) {
|
|
149
|
-
console.error('[Native Host] Extension disconnected (stdin closed)');
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
console.error('[Native Host] Error reading from extension:', error.message);
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
56
|
+
const input = new nativeMessage.Input();
|
|
57
|
+
const output = new nativeMessage.Output();
|
|
58
|
+
const transform = new nativeMessage.Transform((msg, push, done) => {
|
|
59
|
+
console.error('[Native Host] Extension → MCP:', msg.type);
|
|
60
|
+
// Forward to MCP server via WebSocket
|
|
61
|
+
if (wsClient && wsClient.readyState === WebSocket.OPEN) {
|
|
62
|
+
wsClient.send(JSON.stringify(msg));
|
|
155
63
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (wsServer) {
|
|
159
|
-
wsServer.close();
|
|
64
|
+
else {
|
|
65
|
+
console.error('[Native Host] No MCP client connected, message dropped');
|
|
160
66
|
}
|
|
161
|
-
|
|
162
|
-
}
|
|
67
|
+
done();
|
|
68
|
+
});
|
|
163
69
|
/**
|
|
164
70
|
* Main entry point
|
|
165
71
|
*/
|
|
166
|
-
|
|
72
|
+
function main() {
|
|
167
73
|
console.error('[Native Host] Starting Gravity Native Host...');
|
|
168
|
-
// Set stdin to binary mode for Native Messaging
|
|
169
|
-
process.stdin.setEncoding('binary');
|
|
170
|
-
process.stdin.pause();
|
|
171
74
|
// Start WebSocket server
|
|
172
75
|
startWebSocketServer();
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
76
|
+
// Setup Native Messaging pipeline
|
|
77
|
+
process.stdin
|
|
78
|
+
.pipe(input)
|
|
79
|
+
.pipe(transform)
|
|
80
|
+
.pipe(output)
|
|
81
|
+
.pipe(process.stdout);
|
|
179
82
|
console.error('[Native Host] Ready and waiting for messages...');
|
|
83
|
+
// Handle stdin close
|
|
84
|
+
process.stdin.on('end', () => {
|
|
85
|
+
console.error('[Native Host] Extension disconnected (stdin closed)');
|
|
86
|
+
if (wsServer) {
|
|
87
|
+
wsServer.close();
|
|
88
|
+
}
|
|
89
|
+
process.exit(0);
|
|
90
|
+
});
|
|
180
91
|
}
|
|
181
92
|
// Handle graceful shutdown
|
|
182
93
|
process.on('SIGINT', () => {
|
|
@@ -193,8 +104,5 @@ process.on('SIGTERM', () => {
|
|
|
193
104
|
}
|
|
194
105
|
process.exit(0);
|
|
195
106
|
});
|
|
196
|
-
main()
|
|
197
|
-
console.error('[Native Host] Fatal error:', error);
|
|
198
|
-
process.exit(1);
|
|
199
|
-
});
|
|
107
|
+
main();
|
|
200
108
|
//# sourceMappingURL=native-host.js.map
|
package/dist/native-host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-host.js","sourceRoot":"","sources":["../src/native-host.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"native-host.js","sourceRoot":"","sources":["../src/native-host.ts"],"names":[],"mappings":"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"}
|
package/extension/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gravity-core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24",
|
|
4
4
|
"description": "Gravity - AI-powered CSS layout diagnostics for any IDE. Connect your browser to get real-time layout issue detection.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"node": ">=16.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
+
"chrome-native-messaging": "^0.2.0",
|
|
49
50
|
"ws": "^8.18.0"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|