yap2app 1.1.4 → 1.1.6

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/bridge.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import http from 'http';
2
+ import https from 'https';
2
3
  import fsSync from 'fs';
3
4
  import path from 'path';
4
5
  import util from 'util';
@@ -14,6 +15,46 @@ const fs = fsSync.promises || {
14
15
 
15
16
  const PORT = Number(process.env.YAP2APP_PORT) || 10420;
16
17
  const PROJECT_ROOT = process.cwd();
18
+ const CLOUD_RELAY_URL = process.env.YAP2APP_CLOUD_URL || 'https://yap2app-dot-cybage-hackathon.uc.r.appspot.com';
19
+ const PAIR_CODE = (process.env.YAP2APP_PAIR_CODE || ('CYB-' + Math.floor(100 + Math.random() * 900))).toUpperCase();
20
+
21
+ // Helper to send outbound HTTPS requests to the Yap2App Cloud Relay
22
+ function sendCloudRelayRequest(method, endpoint, payload) {
23
+ return new Promise((resolve) => {
24
+ try {
25
+ const url = new URL(`${CLOUD_RELAY_URL}${endpoint}`);
26
+ const body = payload ? JSON.stringify(payload) : '';
27
+ const req = https.request({
28
+ hostname: url.hostname,
29
+ port: 443,
30
+ path: url.pathname + url.search,
31
+ method: method,
32
+ headers: {
33
+ 'Content-Type': 'application/json',
34
+ 'Content-Length': Buffer.byteLength(body),
35
+ 'User-Agent': 'yap2app-cli/1.1.5'
36
+ },
37
+ timeout: 6000
38
+ }, (res) => {
39
+ let respData = '';
40
+ res.on('data', chunk => respData += chunk);
41
+ res.on('end', () => {
42
+ try {
43
+ resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, status: res.statusCode, data: JSON.parse(respData || '{}') });
44
+ } catch {
45
+ resolve({ ok: false, status: res.statusCode, data: null });
46
+ }
47
+ });
48
+ });
49
+ req.on('error', () => resolve({ ok: false, status: 0, data: null }));
50
+ req.on('timeout', () => { req.destroy(); resolve({ ok: false, status: 0, data: null }); });
51
+ if (body) req.write(body);
52
+ req.end();
53
+ } catch {
54
+ resolve({ ok: false, status: 0, data: null });
55
+ }
56
+ });
57
+ }
17
58
 
18
59
  // Bulletproof W3C Private Network Access (PNA) and Dynamic Origin CORS Headers
19
60
  function getCorsHeaders(req) {
@@ -107,9 +148,10 @@ const server = http.createServer(async (req, res) => {
107
148
  res.writeHead(200, headers);
108
149
  res.end(JSON.stringify({
109
150
  status: 'healthy',
110
- service: 'Yap2App-Localhost-Bridge',
111
- version: '1.1.4',
151
+ service: 'yap2app-bridge',
152
+ version: '1.1.6',
112
153
  port: PORT,
154
+ pair_code: PAIR_CODE,
113
155
  project_root: PROJECT_ROOT,
114
156
  project_name: path.basename(PROJECT_ROOT),
115
157
  ready: true
@@ -121,12 +163,12 @@ const server = http.createServer(async (req, res) => {
121
163
  if (req.method === 'GET' && (pathname === '/api/context' || pathname === '/context')) {
122
164
  try {
123
165
  const promptQuery = searchParams.get('q') || '';
124
- console.log(`[Yap2App Bridge] 🔍 Scanning shallow codebase context in: ${PROJECT_ROOT}${promptQuery ? ` (ranking for query: "${promptQuery}")` : ''}`);
166
+ console.log(` [bridge] Scanning codebase in ${path.basename(PROJECT_ROOT)}${promptQuery ? ` (query: "${promptQuery}")` : ''}`);
125
167
  const context = await scanCodebase(PROJECT_ROOT, promptQuery);
126
168
  res.writeHead(200, headers);
127
169
  res.end(JSON.stringify(context));
128
170
  } catch (e) {
129
- console.error('[Yap2App Bridge] Context scan error:', e);
171
+ console.error(' [bridge] Context scan error:', e.message);
130
172
  res.writeHead(500, headers);
131
173
  res.end(JSON.stringify({ error: e.message }));
132
174
  }
@@ -169,7 +211,7 @@ const server = http.createServer(async (req, res) => {
169
211
  diffs: diffResults
170
212
  }));
171
213
  } catch (e) {
172
- console.error('[Yap2App Bridge] Diff error:', e);
214
+ console.error(' [bridge] Diff error:', e.message);
173
215
  res.writeHead(500, headers);
174
216
  res.end(JSON.stringify({ error: e.message }));
175
217
  }
@@ -195,7 +237,7 @@ const server = http.createServer(async (req, res) => {
195
237
 
196
238
  // Write file with utf8 encoding
197
239
  await fs.writeFile(fullPath, file.content, 'utf8');
198
- console.log(`[Yap2App Bridge] ✍️ Successfully wrote: ${file.path}`);
240
+ console.log(` [bridge] Wrote ${file.path}`);
199
241
  written.push(file.path);
200
242
  }
201
243
 
@@ -208,7 +250,7 @@ const server = http.createServer(async (req, res) => {
208
250
  message: `Successfully wrote ${written.length} files to ${path.basename(PROJECT_ROOT)}`
209
251
  }));
210
252
  } catch (e) {
211
- console.error('[Yap2App Bridge] Write to disk error:', e);
253
+ console.error(' [bridge] Write error:', e.message);
212
254
  res.writeHead(500, headers);
213
255
  res.end(JSON.stringify({ error: e.message }));
214
256
  }
@@ -224,26 +266,75 @@ const server = http.createServer(async (req, res) => {
224
266
  // Gracefully handle EADDRINUSE without crashing
225
267
  server.on('error', (err) => {
226
268
  if (err && err.code === 'EADDRINUSE') {
227
- console.log(`\n===============================================================`);
228
- console.log(`📡 Yap2App Localhost Bridge is ALREADY active on port ${PORT}!`);
229
- console.log(`📁 Active Workspace: ${PROJECT_ROOT}`);
230
- console.log(`🌐 Ready for 1-click sync from Yap2App Web Studio UI...`);
231
- console.log(`===============================================================\n`);
269
+ console.log(`\n Yap2App Bridge\n`);
270
+ console.log(` Port ${PORT} is active. Cloud Relay connected.`);
271
+ console.log(` Workspace: ${PROJECT_ROOT}`);
272
+ console.log(` Pair Code: ${PAIR_CODE}`);
273
+ console.log(` Web Studio: ${CLOUD_RELAY_URL}\n`);
232
274
  return;
233
275
  }
234
- console.error('[Yap2App Bridge Error]:', err);
276
+ console.error(' [bridge] Error:', err.message || err);
235
277
  });
236
278
 
237
- export function startBridge(port = PORT) {
279
+ export async function startBridge(port = PORT) {
238
280
  server.listen(port, '0.0.0.0', () => {
239
- console.log(`\n===============================================================`);
240
- console.log(`🚀 Yap2App Localhost Bridge & Shallow Scanner is ACTIVE!`);
241
- console.log(`📡 Listening on: http://127.0.0.1:${port}`);
242
- console.log(`📁 Active Workspace: ${PROJECT_ROOT}`);
243
- console.log(`🛡️ Enterprise Diff & W3C PNA Security Gate Enabled`);
244
- console.log(`===============================================================\n`);
245
- console.log(`Ready for 1-click sync from Yap2App Web Studio UI...\n`);
281
+ console.log(`\n Yap2App Bridge v1.1.6\n`);
282
+ console.log(` Local: http://127.0.0.1:${port}`);
283
+ console.log(` Workspace: ${PROJECT_ROOT}`);
284
+ console.log(` Pair Code: ${PAIR_CODE}`);
285
+ console.log(` Web Studio: ${CLOUD_RELAY_URL}\n`);
286
+ console.log(` Ready for sync.\n`);
246
287
  });
288
+
289
+ // Initial scan and Cloud Relay registration
290
+ try {
291
+ const initialContext = await scanCodebase(PROJECT_ROOT);
292
+ await sendCloudRelayRequest('POST', '/api/v1/bridge/heartbeat', {
293
+ pair_code: PAIR_CODE,
294
+ project_name: path.basename(PROJECT_ROOT),
295
+ project_root: PROJECT_ROOT,
296
+ framework: initialContext.framework,
297
+ context: initialContext,
298
+ version: '1.1.6'
299
+ });
300
+ } catch (e) {}
301
+
302
+ // Periodic Cloud Relay heartbeat & write execution loop (every 3.5 seconds)
303
+ setInterval(async () => {
304
+ try {
305
+ const context = await scanCodebase(PROJECT_ROOT);
306
+ const hbResult = await sendCloudRelayRequest('POST', '/api/v1/bridge/heartbeat', {
307
+ pair_code: PAIR_CODE,
308
+ project_name: path.basename(PROJECT_ROOT),
309
+ project_root: PROJECT_ROOT,
310
+ framework: context.framework,
311
+ context: context,
312
+ version: '1.1.6'
313
+ });
314
+
315
+ // If pending write tasks, fetch and execute them on local disk
316
+ if (hbResult && hbResult.data && hbResult.data.pending_writes_count > 0) {
317
+ const pollResult = await sendCloudRelayRequest('GET', `/api/v1/bridge/poll-writes?pair_code=${PAIR_CODE}`);
318
+ const tasks = (pollResult.data && pollResult.data.pending_tasks) || [];
319
+ for (const task of tasks) {
320
+ const written = [];
321
+ for (const file of (task.files || [])) {
322
+ const fullPath = path.join(PROJECT_ROOT, file.path);
323
+ await fs.mkdir(path.dirname(fullPath), { recursive: true });
324
+ await fs.writeFile(fullPath, file.content, 'utf8');
325
+ console.log(` [bridge] Wrote ${file.path}`);
326
+ written.push(file.path);
327
+ }
328
+ await sendCloudRelayRequest('POST', '/api/v1/bridge/complete-write', {
329
+ task_id: task.task_id,
330
+ success: true,
331
+ written,
332
+ message: `Wrote ${written.length} file(s) directly to ${path.basename(PROJECT_ROOT)}`
333
+ });
334
+ }
335
+ }
336
+ } catch {}
337
+ }, 3500);
247
338
  }
248
339
 
249
340
  // Direct execution
@@ -252,3 +343,4 @@ if (isDirectRun) {
252
343
  startBridge();
253
344
  }
254
345
 
346
+
package/mcp.js CHANGED
@@ -155,7 +155,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
155
155
  export async function runMcpServer() {
156
156
  const transport = new StdioServerTransport();
157
157
  await server.connect(transport);
158
- console.error("⚡ Yap2App MCP Server running on stdio");
158
+ console.error("Yap2App MCP Server running on stdio");
159
159
  }
160
160
 
161
161
  const isDirectRun = Boolean(typeof process !== 'undefined' && process.argv && process.argv[1] && (process.argv[1].endsWith('mcp.js') || process.argv[1].endsWith('mcp')));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yap2app",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Autonomous Vibe-to-Prod Localhost Bridge & Model Context Protocol (MCP) Server",
5
5
  "main": "bin/cli.bundle.js",
6
6
  "bin": {