groove-dev 0.12.6 → 0.12.8
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/node_modules/@groove-dev/daemon/src/api.js +61 -1
- package/node_modules/@groove-dev/gui/dist/assets/index-CeyNe9uc.js +73 -0
- package/node_modules/@groove-dev/gui/dist/index.html +1 -1
- package/node_modules/@groove-dev/gui/src/components/DirPicker.jsx +298 -0
- package/node_modules/@groove-dev/gui/src/components/SpawnPanel.jsx +53 -46
- package/package.json +1 -1
- package/packages/daemon/src/api.js +61 -1
- package/packages/gui/dist/assets/index-CeyNe9uc.js +73 -0
- package/packages/gui/dist/index.html +1 -1
- package/packages/gui/src/components/DirPicker.jsx +298 -0
- package/packages/gui/src/components/SpawnPanel.jsx +53 -46
- package/node_modules/@groove-dev/gui/dist/assets/index-B49YqEXS.js +0 -73
- package/packages/gui/dist/assets/index-B49YqEXS.js +0 -73
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import express from 'express';
|
|
5
5
|
import { resolve, dirname } from 'path';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
|
-
import { existsSync, readFileSync } from 'fs';
|
|
7
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
|
|
8
8
|
import { listProviders } from './providers/index.js';
|
|
9
9
|
import { validateAgentConfig } from './validate.js';
|
|
10
10
|
|
|
@@ -365,6 +365,66 @@ export function createApi(app, daemon) {
|
|
|
365
365
|
res.json(daemon.adaptive.getAllProfiles());
|
|
366
366
|
});
|
|
367
367
|
|
|
368
|
+
// --- Directory Browser ---
|
|
369
|
+
|
|
370
|
+
app.get('/api/browse', (req, res) => {
|
|
371
|
+
const relPath = req.query.path || '';
|
|
372
|
+
|
|
373
|
+
// Security: no absolute paths, no traversal
|
|
374
|
+
if (relPath.startsWith('/') || relPath.includes('..') || relPath.includes('\0')) {
|
|
375
|
+
return res.status(400).json({ error: 'Invalid path' });
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const fullPath = relPath ? resolve(daemon.projectDir, relPath) : daemon.projectDir;
|
|
379
|
+
|
|
380
|
+
// Must stay within project directory
|
|
381
|
+
if (!fullPath.startsWith(daemon.projectDir)) {
|
|
382
|
+
return res.status(400).json({ error: 'Path outside project' });
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (!existsSync(fullPath)) {
|
|
386
|
+
return res.status(404).json({ error: 'Directory not found' });
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
try {
|
|
390
|
+
const entries = readdirSync(fullPath, { withFileTypes: true })
|
|
391
|
+
.filter((e) => e.isDirectory() && !e.name.startsWith('.') && e.name !== 'node_modules')
|
|
392
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
393
|
+
.map((e) => {
|
|
394
|
+
const childPath = relPath ? `${relPath}/${e.name}` : e.name;
|
|
395
|
+
const childFull = resolve(fullPath, e.name);
|
|
396
|
+
let hasChildren = false;
|
|
397
|
+
let childCount = 0;
|
|
398
|
+
let fileCount = 0;
|
|
399
|
+
try {
|
|
400
|
+
const children = readdirSync(childFull, { withFileTypes: true });
|
|
401
|
+
for (const c of children) {
|
|
402
|
+
if (c.name.startsWith('.') || c.name === 'node_modules') continue;
|
|
403
|
+
if (c.isDirectory()) { childCount++; hasChildren = true; }
|
|
404
|
+
else fileCount++;
|
|
405
|
+
}
|
|
406
|
+
} catch { /* unreadable */ }
|
|
407
|
+
return { name: e.name, path: childPath, hasChildren, childCount, fileCount };
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// Count files in current dir
|
|
411
|
+
let currentFiles = 0;
|
|
412
|
+
try {
|
|
413
|
+
currentFiles = readdirSync(fullPath, { withFileTypes: true })
|
|
414
|
+
.filter((e) => e.isFile() && !e.name.startsWith('.')).length;
|
|
415
|
+
} catch { /* ignore */ }
|
|
416
|
+
|
|
417
|
+
res.json({
|
|
418
|
+
current: relPath || '.',
|
|
419
|
+
parent: relPath ? relPath.split('/').slice(0, -1).join('/') : null,
|
|
420
|
+
dirs: entries,
|
|
421
|
+
fileCount: currentFiles,
|
|
422
|
+
});
|
|
423
|
+
} catch (err) {
|
|
424
|
+
res.status(500).json({ error: err.message });
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
368
428
|
// --- Codebase Indexer ---
|
|
369
429
|
|
|
370
430
|
app.get('/api/indexer', (req, res) => {
|