code icon Code

List Workspace Contents

Lists files in skills/sauna and documents for reset preview

Source Code

import fs from "fs";
import path from "path";

const [skillsPath, documentsPath, excludeSkillId] = process.argv.slice(2);

if (!skillsPath || !documentsPath) {
  console.error("Usage: skillsPath documentsPath [excludeSkillId]");
  process.exit(1);
}

/**
 * Recursively get all files and directories
 */
function getContents(dir) {
  const results = { files: [], dirs: [], totalSize: 0 };

  if (!fs.existsSync(dir)) {
    return results;
  }

  const entries = fs.readdirSync(dir, { withFileTypes: true });

  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name);

    if (entry.isDirectory()) {
      results.dirs.push(fullPath);
      const subResults = getContents(fullPath);
      results.files.push(...subResults.files);
      results.dirs.push(...subResults.dirs);
      results.totalSize += subResults.totalSize;
    } else {
      const stats = fs.statSync(fullPath);
      results.files.push(fullPath);
      results.totalSize += stats.size;
    }
  }

  return results;
}

/**
 * Format bytes to human readable
 */
function formatBytes(bytes) {
  if (bytes === 0) return "0 B";
  const k = 1024;
  const sizes = ["B", "KB", "MB", "GB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
}

/**
 * Get top-level items (skills or files) for summary
 */
function getTopLevelItems(dir) {
  if (!fs.existsSync(dir)) {
    return [];
  }
  return fs.readdirSync(dir);
}

try {
  console.log("Scanning workspace for reset preview...\n");

  // Scan skills/sauna
  const skillsContents = getContents(skillsPath);
  const skillItems = getTopLevelItems(skillsPath);

  // Filter out the skill to preserve
  let excludedSkillName = null;
  if (excludeSkillId) {
    // Extract skill name from ID (e.g., "skill:workspace.reset.manager" -> look for matching folder)
    excludedSkillName = excludeSkillId.replace("skill:", "");
  }

  const skillsToDelete = skillItems.filter((item) => {
    if (!excludedSkillName) return true;
    // Check if this folder contains the skill we want to preserve
    const skillPath = path.join(skillsPath, item);
    if (fs.existsSync(skillPath) && fs.statSync(skillPath).isDirectory()) {
      const files = fs.readdirSync(skillPath);
      return !files.some((f) => f.includes(excludedSkillName));
    }
    return true;
  });

  // Scan documents
  const documentsContents = getContents(documentsPath);
  const documentItems = getTopLevelItems(documentsPath);

  // Build summary
  console.log("=== WORKSPACE RESET PREVIEW ===\n");

  console.log("šŸ“ skills/sauna:");
  if (skillItems.length === 0) {
    console.log("   (empty - nothing to delete)");
  } else {
    console.log(`   ${skillsToDelete.length} skill(s) will be deleted:`);
    for (const skill of skillsToDelete.slice(0, 10)) {
      console.log(`   - ${skill}`);
    }
    if (skillsToDelete.length > 10) {
      console.log(`   ... and ${skillsToDelete.length - 10} more`);
    }
    if (excludedSkillName && skillItems.length > skillsToDelete.length) {
      console.log(`   āœ“ Preserving: ${excludeSkillId}`);
    }
  }

  console.log("\nšŸ“„ documents:");
  if (documentItems.length === 0) {
    console.log("   (empty - nothing to delete)");
  } else {
    console.log(`   ${documentItems.length} item(s) will be deleted:`);
    for (const doc of documentItems.slice(0, 10)) {
      console.log(`   - ${doc}`);
    }
    if (documentItems.length > 10) {
      console.log(`   ... and ${documentItems.length - 10} more`);
    }
  }

  const totalFiles = skillsContents.files.length + documentsContents.files.length;
  const totalSize = skillsContents.totalSize + documentsContents.totalSize;

  console.log("\nšŸ“Š Summary:");
  console.log(`   Total files: ${totalFiles}`);
  console.log(`   Total size: ${formatBytes(totalSize)}`);

  // Output structured data for agent
  console.log(
    JSON.stringify({
      success: true,
      skills: {
        path: skillsPath,
        itemCount: skillsToDelete.length,
        items: skillsToDelete,
        preserved: excludeSkillId || null,
      },
      documents: {
        path: documentsPath,
        itemCount: documentItems.length,
        items: documentItems,
      },
      totals: {
        files: totalFiles,
        sizeBytes: totalSize,
        sizeHuman: formatBytes(totalSize),
      },
    })
  );
} catch (error) {
  console.error("Error scanning workspace:", error.message);
  process.exit(1);
}