zugzbot 1.0.8 → 1.0.9

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.
@@ -165,6 +165,33 @@ const startServer = () => {
165
165
  return
166
166
  }
167
167
 
168
+ // 3b. Endpoint: Crear carpeta física para un proyecto si no existe (gestión de carpetas locales)
169
+ if (req.url === '/api-custom/create-folder' && req.method === 'POST') {
170
+ let body = ''
171
+ req.on('data', chunk => body += chunk)
172
+ req.on('end', () => {
173
+ try {
174
+ const parsed = JSON.parse(body)
175
+ const targetPath = parsed.path
176
+ if (targetPath && path.isAbsolute(targetPath)) {
177
+ if (!fs.existsSync(targetPath)) {
178
+ fs.mkdirSync(targetPath, { recursive: true })
179
+ console.log(`\x1b[32m%s\x1b[0m`, `📁 Carpeta física creada: ${targetPath}`)
180
+ }
181
+ res.writeHead(200, { 'Content-Type': 'application/json' })
182
+ res.end(JSON.stringify({ success: true, message: `Carpeta lista: ${targetPath}` }))
183
+ } else {
184
+ res.writeHead(400, { 'Content-Type': 'application/json' })
185
+ res.end(JSON.stringify({ error: 'Ruta absoluta inválida o ausente' }))
186
+ }
187
+ } catch (e) {
188
+ res.writeHead(500, { 'Content-Type': 'application/json' })
189
+ res.end(JSON.stringify({ error: 'Error al crear la carpeta', detail: e.message }))
190
+ }
191
+ })
192
+ return
193
+ }
194
+
168
195
  // 4. Proxy inverso para las APIs de Opencode (prefijo /api)
169
196
  if (req.url.startsWith('/api/')) {
170
197
  const targetPath = req.url.substring(4) // Quita el '/api'
@@ -183,8 +210,8 @@ const startServer = () => {
183
210
  await scanInstances()
184
211
  console.log('\x1b[33m%s\x1b[0m', `🔌 Proxyando peticiones de la API a Opencode en el puerto ${opencodePort}`)
185
212
 
186
- // Iniciar el túnel de Cloudflare Quick Tunnel
187
- startTunnel()
213
+ // El túnel de Cloudflare se ha desactivado para garantizar que el panel web sea 100% local y seguro.
214
+ console.log('\x1b[32m%s\x1b[0m', '🔒 Seguridad: Servidor operando exclusivamente en modo LOCAL (Cloudflare inactivo)')
188
215
  })
189
216
  }
190
217
 
@@ -263,35 +290,4 @@ const serveStatic = (req, res) => {
263
290
  })
264
291
  }
265
292
 
266
- const startTunnel = () => {
267
- console.log('\x1b[35m%s\x1b[0m', '🌐 Abriendo túnel seguro trycloudflare.com...')
268
-
269
- const cf = spawn('npx', ['-y', 'cloudflared', 'tunnel', '--url', `http://127.0.0.1:${PORT}`])
270
-
271
- cf.stdout.on('data', (data) => {
272
- parseCfOutput(data.toString())
273
- })
274
-
275
- cf.stderr.on('data', (data) => {
276
- parseCfOutput(data.toString())
277
- })
278
-
279
- cf.on('close', (code) => {
280
- console.log(`\x1b[31m%s\x1b[0m`, `⚠️ Túnel de Cloudflare finalizado (código: ${code}). Reintentando...`)
281
- setTimeout(startTunnel, 5000)
282
- })
283
- }
284
-
285
- const parseCfOutput = (text) => {
286
- const match = text.match(/https:\/\/[a-zA-Z0-9-]+\.trycloudflare\.com/)
287
- if (match && match[0] !== tunnelUrl) {
288
- tunnelUrl = match[0]
289
- console.log('\n\x1b[32m%s\x1b[0m', '=========================================================')
290
- console.log('\x1b[32m%s\x1b[0m', '🚀 ¡CENTRO DE CONTROL REMOTO DISPONIBLE!')
291
- console.log('\x1b[32m%s\x1b[0m', '📱 Controla tu arnés Opencode desde cualquier lugar en:')
292
- console.log('\x1b[36m%s\x1b[0m', ` 👉 ${tunnelUrl} 👈`)
293
- console.log('\x1b[32m%s\x1b[0m', '=========================================================\n')
294
- }
295
- }
296
-
297
293
  startServer()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zugzbot",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Fácil instalador del arnés SDD de Zugzbot para proyectos OpenCode",
5
5
  "type": "module",
6
6
  "bin": {