gravity-core 1.0.1

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.
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Browser connection management
3
+ * Handles WebSocket connection to native host
4
+ */
5
+ import { WebSocket } from 'ws';
6
+ export class BrowserConnection {
7
+ constructor(options = {}) {
8
+ this.socket = null;
9
+ this.isConnected = false;
10
+ this.reconnectTimer = null;
11
+ this.reconnectAttempts = 0;
12
+ this.maxReconnectAttempts = Infinity;
13
+ this.reconnectInterval = 2000;
14
+ this.messageIdCounter = 1;
15
+ this.pendingRequests = new Map();
16
+ this.port = options.port || 9224;
17
+ this.timeout = options.timeout || 10000;
18
+ this.autoReconnect = options.autoReconnect !== false;
19
+ }
20
+ /**
21
+ * Connect to browser via native host
22
+ */
23
+ async connect() {
24
+ return new Promise((resolve, reject) => {
25
+ this.attemptConnect(resolve, reject);
26
+ });
27
+ }
28
+ /**
29
+ * Attempt to connect to native host
30
+ */
31
+ attemptConnect(resolve, reject) {
32
+ if (this.socket && this.socket.readyState === WebSocket.OPEN) {
33
+ resolve();
34
+ return;
35
+ }
36
+ if (this.socket) {
37
+ this.socket.removeAllListeners();
38
+ this.socket.close();
39
+ this.socket = null;
40
+ }
41
+ const url = `ws://localhost:${this.port}`;
42
+ this.reconnectAttempts++;
43
+ if (this.reconnectAttempts === 1) {
44
+ console.log(`🔌 Connecting to Gravity at ${url}...`);
45
+ }
46
+ const ws = new WebSocket(url);
47
+ this.socket = ws;
48
+ const timeout = setTimeout(() => {
49
+ ws.close();
50
+ reject(new Error(`Connection timeout after ${this.timeout}ms`));
51
+ }, this.timeout);
52
+ ws.on('open', () => {
53
+ clearTimeout(timeout);
54
+ console.log('✅ Connected to Gravity');
55
+ this.isConnected = true;
56
+ this.reconnectAttempts = 0;
57
+ resolve();
58
+ });
59
+ ws.on('message', (data) => {
60
+ try {
61
+ const message = JSON.parse(data.toString());
62
+ this.handleMessage(message);
63
+ }
64
+ catch (error) {
65
+ console.error('Failed to parse message:', error);
66
+ }
67
+ });
68
+ ws.on('close', () => {
69
+ clearTimeout(timeout);
70
+ console.log('❌ Gravity connection closed');
71
+ this.isConnected = false;
72
+ this.socket = null;
73
+ // Reject all pending requests
74
+ for (const [id, pending] of this.pendingRequests) {
75
+ clearTimeout(pending.timeout);
76
+ pending.reject(new Error('Connection closed'));
77
+ this.pendingRequests.delete(id);
78
+ }
79
+ // Auto-reconnect if enabled
80
+ if (this.autoReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {
81
+ this.scheduleReconnect();
82
+ }
83
+ });
84
+ ws.on('error', (error) => {
85
+ clearTimeout(timeout);
86
+ if (error.code !== 'ECONNREFUSED') {
87
+ console.error('Connection error:', error.message);
88
+ }
89
+ reject(error);
90
+ });
91
+ }
92
+ /**
93
+ * Schedule a reconnection attempt
94
+ */
95
+ scheduleReconnect() {
96
+ if (this.reconnectTimer) {
97
+ clearTimeout(this.reconnectTimer);
98
+ }
99
+ this.reconnectTimer = setTimeout(() => {
100
+ this.reconnectTimer = null;
101
+ this.attemptConnect(() => { }, () => { });
102
+ }, this.reconnectInterval);
103
+ }
104
+ /**
105
+ * Disconnect from browser
106
+ */
107
+ async disconnect() {
108
+ if (this.reconnectTimer) {
109
+ clearTimeout(this.reconnectTimer);
110
+ this.reconnectTimer = null;
111
+ }
112
+ if (this.socket) {
113
+ this.socket.removeAllListeners();
114
+ this.socket.close();
115
+ this.socket = null;
116
+ }
117
+ this.isConnected = false;
118
+ // Reject all pending requests
119
+ for (const [id, pending] of this.pendingRequests) {
120
+ clearTimeout(pending.timeout);
121
+ pending.reject(new Error('Disconnected'));
122
+ this.pendingRequests.delete(id);
123
+ }
124
+ }
125
+ /**
126
+ * Check if connected
127
+ */
128
+ getStatus() {
129
+ return {
130
+ connected: this.isConnected,
131
+ message: this.isConnected ? 'Connected' : 'Disconnected',
132
+ timestamp: new Date().toISOString(),
133
+ };
134
+ }
135
+ /**
136
+ * Send CDP command
137
+ */
138
+ async sendCommand(method, params = {}) {
139
+ if (!this.isConnected) {
140
+ throw new Error('Not connected to Gravity');
141
+ }
142
+ const id = this.messageIdCounter++;
143
+ return new Promise((resolve, reject) => {
144
+ const timeout = setTimeout(() => {
145
+ this.pendingRequests.delete(id);
146
+ reject(new Error(`Command ${method} timed out after ${this.timeout}ms`));
147
+ }, this.timeout);
148
+ this.pendingRequests.set(id, { resolve, reject, timeout });
149
+ const message = {
150
+ type: 'cdp_request',
151
+ id,
152
+ method,
153
+ params,
154
+ };
155
+ try {
156
+ this.socket.send(JSON.stringify(message));
157
+ }
158
+ catch (error) {
159
+ clearTimeout(timeout);
160
+ this.pendingRequests.delete(id);
161
+ reject(error);
162
+ }
163
+ });
164
+ }
165
+ /**
166
+ * Handle incoming messages
167
+ */
168
+ handleMessage(message) {
169
+ if (message.type === 'cdp_response') {
170
+ const pending = this.pendingRequests.get(message.id);
171
+ if (pending) {
172
+ clearTimeout(pending.timeout);
173
+ this.pendingRequests.delete(message.id);
174
+ if (message.error) {
175
+ pending.reject(new Error(message.error.message || 'Command failed'));
176
+ }
177
+ else {
178
+ pending.resolve(message.result);
179
+ }
180
+ }
181
+ }
182
+ }
183
+ }
184
+ //# sourceMappingURL=browser-connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-connection.js","sourceRoot":"","sources":["../src/browser-connection.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gravity MCP Server
4
+ *
5
+ * This is the entry point for the npm package when used as an MCP server.
6
+ * It connects to the Chrome extension via WebSocket and provides MCP tools
7
+ * for layout diagnostics.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG"}
package/dist/cli.js ADDED
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gravity MCP Server
4
+ *
5
+ * This is the entry point for the npm package when used as an MCP server.
6
+ * It connects to the Chrome extension via WebSocket and provides MCP tools
7
+ * for layout diagnostics.
8
+ */
9
+ import { Gravity } from './index.js';
10
+ // Get port from environment or use default
11
+ const port = parseInt(process.env.GRAVITY_PORT || '9224', 10);
12
+ const timeout = parseInt(process.env.GRAVITY_TIMEOUT || '10000', 10);
13
+ // Initialize bridge
14
+ const bridge = new Gravity({ port, timeout });
15
+ // Tool definitions for MCP
16
+ const tools = [
17
+ {
18
+ name: 'diagnose_layout',
19
+ description: 'Diagnose CSS layout issues for a DOM element',
20
+ inputSchema: {
21
+ type: 'object',
22
+ properties: {
23
+ selector: {
24
+ type: 'string',
25
+ description: 'CSS selector for the element to diagnose (e.g., "#modal", ".button")',
26
+ },
27
+ },
28
+ required: ['selector'],
29
+ },
30
+ },
31
+ {
32
+ name: 'check_connection',
33
+ description: 'Check if browser is connected',
34
+ inputSchema: {
35
+ type: 'object',
36
+ properties: {},
37
+ },
38
+ },
39
+ {
40
+ name: 'highlight_element',
41
+ description: 'Highlight an element in the browser',
42
+ inputSchema: {
43
+ type: 'object',
44
+ properties: {
45
+ selector: {
46
+ type: 'string',
47
+ description: 'CSS selector for the element to highlight',
48
+ },
49
+ color: {
50
+ type: 'string',
51
+ description: 'Color for the highlight (default: red)',
52
+ },
53
+ duration: {
54
+ type: 'number',
55
+ description: 'Duration in milliseconds (default: 3000)',
56
+ },
57
+ },
58
+ required: ['selector'],
59
+ },
60
+ },
61
+ ];
62
+ /**
63
+ * Handle MCP tool calls
64
+ */
65
+ async function handleToolCall(toolName, params) {
66
+ switch (toolName) {
67
+ case 'diagnose_layout': {
68
+ if (!bridge.isConnected()) {
69
+ throw new Error('Not connected to browser. Make sure the Gravity extension is loaded and you clicked "Connect to Tab".');
70
+ }
71
+ const result = await bridge.diagnoseLayout(params.selector);
72
+ return result;
73
+ }
74
+ case 'check_connection': {
75
+ const status = bridge.getStatus();
76
+ return {
77
+ connected: status.connected,
78
+ message: status.message,
79
+ timestamp: status.timestamp,
80
+ };
81
+ }
82
+ case 'highlight_element': {
83
+ if (!bridge.isConnected()) {
84
+ throw new Error('Not connected to browser');
85
+ }
86
+ // This would require additional implementation in the bridge
87
+ // For now, return a message
88
+ return {
89
+ success: true,
90
+ message: `Highlight request sent for ${params.selector}`,
91
+ };
92
+ }
93
+ default:
94
+ throw new Error(`Unknown tool: ${toolName}`);
95
+ }
96
+ }
97
+ /**
98
+ * Process MCP request
99
+ */
100
+ async function processRequest(request) {
101
+ try {
102
+ if (request.method === 'initialize') {
103
+ return {
104
+ jsonrpc: '2.0',
105
+ id: request.id,
106
+ result: {
107
+ protocolVersion: '2024-11-05',
108
+ capabilities: {
109
+ tools: {},
110
+ },
111
+ serverInfo: {
112
+ name: 'gravity',
113
+ version: '1.0.1',
114
+ },
115
+ },
116
+ };
117
+ }
118
+ if (request.method === 'tools/list') {
119
+ return {
120
+ jsonrpc: '2.0',
121
+ id: request.id,
122
+ result: {
123
+ tools,
124
+ },
125
+ };
126
+ }
127
+ if (request.method === 'tools/call') {
128
+ const { name, arguments: args } = request.params;
129
+ const result = await handleToolCall(name, args);
130
+ return {
131
+ jsonrpc: '2.0',
132
+ id: request.id,
133
+ result: {
134
+ type: 'text',
135
+ text: JSON.stringify(result, null, 2),
136
+ },
137
+ };
138
+ }
139
+ return {
140
+ jsonrpc: '2.0',
141
+ id: request.id,
142
+ error: {
143
+ code: -32601,
144
+ message: 'Method not found',
145
+ },
146
+ };
147
+ }
148
+ catch (error) {
149
+ return {
150
+ jsonrpc: '2.0',
151
+ id: request.id,
152
+ error: {
153
+ code: -32603,
154
+ message: error.message || 'Internal error',
155
+ data: {
156
+ type: error.constructor.name,
157
+ },
158
+ },
159
+ };
160
+ }
161
+ }
162
+ /**
163
+ * Main entry point
164
+ */
165
+ async function main() {
166
+ console.log('🚀 Gravity MCP Server starting...');
167
+ console.log(`📡 Connecting to extension on port ${port}...`);
168
+ // Connect to browser
169
+ try {
170
+ await bridge.connectBrowser(port);
171
+ console.log('✅ Connected to Gravity extension');
172
+ }
173
+ catch (error) {
174
+ console.error('❌ Failed to connect to extension:', error.message);
175
+ console.error('');
176
+ console.error('Make sure:');
177
+ console.error('1. Chrome/Edge is open');
178
+ console.error('2. Gravity extension is loaded (chrome://extensions)');
179
+ console.error('3. You clicked "Connect to Tab" in the extension popup');
180
+ console.error('4. Port 9224 is not blocked by firewall');
181
+ process.exit(1);
182
+ }
183
+ // Listen for stdin (MCP protocol)
184
+ process.stdin.setEncoding('utf-8');
185
+ let buffer = '';
186
+ process.stdin.on('data', async (chunk) => {
187
+ buffer += chunk;
188
+ // Process complete JSON objects
189
+ const lines = buffer.split('\n');
190
+ buffer = lines[lines.length - 1]; // Keep incomplete line in buffer
191
+ for (let i = 0; i < lines.length - 1; i++) {
192
+ const line = lines[i].trim();
193
+ if (!line)
194
+ continue;
195
+ try {
196
+ const request = JSON.parse(line);
197
+ const response = await processRequest(request);
198
+ console.log(JSON.stringify(response));
199
+ }
200
+ catch (error) {
201
+ console.error('Error processing request:', error.message);
202
+ }
203
+ }
204
+ });
205
+ process.stdin.on('end', async () => {
206
+ console.log('Shutting down...');
207
+ await bridge.disconnectBrowser();
208
+ process.exit(0);
209
+ });
210
+ // Handle errors
211
+ process.on('error', (error) => {
212
+ console.error('Fatal error:', error);
213
+ process.exit(1);
214
+ });
215
+ // Graceful shutdown
216
+ process.on('SIGINT', async () => {
217
+ console.log('\nShutting down gracefully...');
218
+ await bridge.disconnectBrowser();
219
+ process.exit(0);
220
+ });
221
+ process.on('SIGTERM', async () => {
222
+ console.log('\nShutting down gracefully...');
223
+ await bridge.disconnectBrowser();
224
+ process.exit(0);
225
+ });
226
+ }
227
+ main().catch((error) => {
228
+ console.error('Fatal error:', error);
229
+ process.exit(1);
230
+ });
231
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Layout diagnostics engine
3
+ * Analyzes layout issues and generates diagnostic reports
4
+ */
5
+ import { DiagnosticResult } from './types.js';
6
+ import { BrowserConnection } from './browser-connection.js';
7
+ export declare class DiagnosticsEngine {
8
+ private connection;
9
+ constructor(connection: BrowserConnection);
10
+ /**
11
+ * Diagnose layout issues for an element
12
+ */
13
+ diagnose(selector: string): Promise<DiagnosticResult>;
14
+ /**
15
+ * Validate CSS selector
16
+ */
17
+ private validateSelector;
18
+ /**
19
+ * Extract element bounds from box model
20
+ */
21
+ private extractBounds;
22
+ /**
23
+ * Check visibility issues
24
+ */
25
+ private checkVisibility;
26
+ /**
27
+ * Check offscreen issues
28
+ */
29
+ private checkOffscreen;
30
+ /**
31
+ * Check modal/positioning issues
32
+ */
33
+ private checkModalIssues;
34
+ /**
35
+ * Check overflow issues
36
+ */
37
+ private checkOverflow;
38
+ }
39
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAgD,MAAM,YAAY,CAAC;AAC5F,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,qBAAa,iBAAiB;IAChB,OAAO,CAAC,UAAU;gBAAV,UAAU,EAAE,iBAAiB;IAEjD;;OAEG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkG3D;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuBxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;IACH,OAAO,CAAC,eAAe;IA8CvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAmDtB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAoBxB;;OAEG;IACH,OAAO,CAAC,aAAa;CAetB"}