agent-nuvira 2.2.0 → 2.3.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/server.ts"],"names":[],"mappings":"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"}
@@ -4436,9 +4436,10 @@ function handleRequest(req, res) {
4436
4436
  }
4437
4437
  return;
4438
4438
  }
4439
- // POST /api/browse/resolve-folder — given a folder name, search from home
4440
- // directory and common locations to find its absolute path. Used by the
4441
- // native folder picker (webkitdirectory) which only returns the folder name.
4439
+ // POST /api/browse/resolve-folder — given a folder name (and optional sub-path
4440
+ // from webkitRelativePath), search the filesystem to find its absolute path.
4441
+ // The native folder picker (webkitdirectory) only returns relative paths, so
4442
+ // we reconstruct the absolute path by searching from common root directories.
4442
4443
  if (pathname === '/api/browse/resolve-folder' && req.method === 'POST') {
4443
4444
  const session = adminSessions.validate(bearerToken(req));
4444
4445
  if (!session) {
@@ -4453,10 +4454,12 @@ function handleRequest(req, res) {
4453
4454
  try {
4454
4455
  const body = await readJsonBody(req);
4455
4456
  const folderName = typeof body?.name === 'string' ? body.name.trim() : '';
4457
+ const subPath = typeof body?.subPath === 'string' ? body.subPath.trim() : '';
4456
4458
  if (!folderName) {
4457
4459
  writeJson(res, 400, { ok: false, error: 'Missing folder name.' });
4458
4460
  return;
4459
4461
  }
4462
+ // Collect root directories to search from.
4460
4463
  const roots = [homedir()];
4461
4464
  const plat = process.platform;
4462
4465
  if (plat === 'darwin') {
@@ -4468,9 +4471,17 @@ function handleRequest(req, res) {
4468
4471
  roots.push(join('/Users', u.name));
4469
4472
  }
4470
4473
  catch { /* skip */ }
4474
+ // External volumes on macOS.
4475
+ try {
4476
+ const vols = readdirSync('/Volumes', { withFileTypes: true })
4477
+ .filter((e) => e.isDirectory());
4478
+ for (const v of vols)
4479
+ roots.push(join('/Volumes', v.name));
4480
+ }
4481
+ catch { /* skip */ }
4471
4482
  }
4472
4483
  else if (plat === 'linux') {
4473
- roots.push('/home');
4484
+ roots.push('/home', '/root');
4474
4485
  try {
4475
4486
  const users = readdirSync('/home', { withFileTypes: true })
4476
4487
  .filter((e) => e.isDirectory() && !e.name.startsWith('.'));
@@ -4478,11 +4489,10 @@ function handleRequest(req, res) {
4478
4489
  roots.push(join('/home', u.name));
4479
4490
  }
4480
4491
  catch { /* skip */ }
4481
- roots.push('/root');
4482
4492
  }
4483
4493
  else if (plat === 'win32') {
4484
4494
  for (const ch of 'CDEFGH'.split('')) {
4485
- const dp = ch + ':\\';
4495
+ const dp = ch + ':';
4486
4496
  try {
4487
4497
  if (existsSync(dp))
4488
4498
  roots.push(dp);
@@ -4490,34 +4500,109 @@ function handleRequest(req, res) {
4490
4500
  catch { /* skip */ }
4491
4501
  }
4492
4502
  }
4493
- for (const root of roots) {
4503
+ // Helper: check if a path exists and is a directory.
4504
+ const isDir = (p) => {
4494
4505
  try {
4495
- const candidate = join(root, folderName);
4496
- if (existsSync(candidate) && statSync(candidate).isDirectory()) {
4506
+ return existsSync(p) && statSync(p).isDirectory();
4507
+ }
4508
+ catch {
4509
+ return false;
4510
+ }
4511
+ };
4512
+ // Step 1: If we have a sub-path, try constructing the full path directly.
4513
+ // e.g. subPath="Documents/Projects" + folderName="myapp"
4514
+ // -> ~/Documents/Projects/myapp
4515
+ if (subPath) {
4516
+ for (const root of roots) {
4517
+ const candidate = join(root, subPath, folderName);
4518
+ if (isDir(candidate)) {
4497
4519
  writeJson(res, 200, { ok: true, path: candidate });
4498
4520
  return;
4499
4521
  }
4500
4522
  }
4501
- catch { /* skip */ }
4502
4523
  }
4503
- const commonSubdirs = ['Documents', 'Desktop', 'Downloads', 'Projects', 'Code', 'dev', 'work', 'src', 'repos'];
4524
+ // Step 2: Direct children of each root.
4525
+ for (const root of roots) {
4526
+ const candidate = join(root, folderName);
4527
+ if (isDir(candidate)) {
4528
+ writeJson(res, 200, { ok: true, path: candidate });
4529
+ return;
4530
+ }
4531
+ }
4532
+ // Step 3: One level deep in common directories.
4533
+ const commonSubdirs = ['Documents', 'Desktop', 'Downloads', 'Projects', 'Code', 'dev', 'work', 'src', 'repos', 'Documents/Projects', 'Documents/Code'];
4504
4534
  for (const root of roots) {
4505
4535
  for (const sub of commonSubdirs) {
4506
- try {
4507
- const parentDir = join(root, sub);
4508
- if (!existsSync(parentDir) || !statSync(parentDir).isDirectory())
4536
+ const parentDir = join(root, sub);
4537
+ const candidate = join(parentDir, folderName);
4538
+ if (isDir(candidate)) {
4539
+ writeJson(res, 200, { ok: true, path: candidate });
4540
+ return;
4541
+ }
4542
+ }
4543
+ }
4544
+ // Step 4: Recursive search from home (depth-limited to 4 levels).
4545
+ // Skips hidden dirs and known large directories.
4546
+ const skipDirs = new Set(['node_modules', '.git', '.cache', '.npm', '.nvm', '.volta', '.cargo', '.rustup', 'Library', '.Trash', '__pycache__', '.venv', 'venv']);
4547
+ let found = '';
4548
+ const searchDepth = (dir, depth) => {
4549
+ if (found || depth > 4)
4550
+ return;
4551
+ try {
4552
+ const entries = readdirSync(dir, { withFileTypes: true });
4553
+ for (const e of entries) {
4554
+ if (found)
4555
+ return;
4556
+ if (!e.isDirectory() || e.name.startsWith('.') || skipDirs.has(e.name))
4509
4557
  continue;
4510
- const found = readdirSync(parentDir, { withFileTypes: true })
4511
- .filter((e) => e.isDirectory() && e.name === folderName);
4512
- if (found.length > 0) {
4513
- writeJson(res, 200, { ok: true, path: join(parentDir, folderName) });
4558
+ const full = join(dir, e.name);
4559
+ if (e.name === folderName) {
4560
+ found = full;
4514
4561
  return;
4515
4562
  }
4563
+ searchDepth(full, depth + 1);
4516
4564
  }
4517
- catch { /* skip */ }
4518
4565
  }
4566
+ catch { /* permission denied, etc. */ }
4567
+ };
4568
+ searchDepth(homedir(), 0);
4569
+ if (found) {
4570
+ writeJson(res, 200, { ok: true, path: found });
4571
+ return;
4572
+ }
4573
+ // Step 5: Broader recursive search from root (depth 2 only, skip system dirs).
4574
+ const systemSkip = new Set([...skipDirs, 'System', 'usr', 'bin', 'sbin', 'etc', 'var', 'tmp', 'opt', 'proc', 'dev', 'sys', 'boot', 'run']);
4575
+ found = '';
4576
+ const searchRoot = (dir, depth) => {
4577
+ if (found || depth > 2)
4578
+ return;
4579
+ try {
4580
+ const entries = readdirSync(dir, { withFileTypes: true });
4581
+ for (const e of entries) {
4582
+ if (found)
4583
+ return;
4584
+ if (!e.isDirectory() || e.name.startsWith('.') || systemSkip.has(e.name))
4585
+ continue;
4586
+ const full = join(dir, e.name);
4587
+ if (e.name === folderName) {
4588
+ found = full;
4589
+ return;
4590
+ }
4591
+ searchRoot(full, depth + 1);
4592
+ }
4593
+ }
4594
+ catch { /* skip */ }
4595
+ };
4596
+ for (const root of roots) {
4597
+ searchRoot(root, 0);
4598
+ if (found)
4599
+ break;
4600
+ }
4601
+ if (found) {
4602
+ writeJson(res, 200, { ok: true, path: found });
4603
+ return;
4519
4604
  }
4520
- writeJson(res, 200, { ok: false, error: 'Could not find folder in common locations. Try typing the full path.' });
4605
+ writeJson(res, 200, { ok: false, error: 'Could not find folder. Try typing the full path manually.' });
4521
4606
  }
4522
4607
  catch {
4523
4608
  writeJson(res, 500, { ok: false, error: 'Failed to resolve folder.' });