ailock
Version:
AI-Proof File Guard - Protect sensitive files from accidental AI modifications
350 lines ⢠16 kB
JavaScript
import { Command } from 'commander';
import chalk from 'chalk';
import { getQuotaUsage, getQuotaStatusSummary, initializeUserConfig, getTrackedDirectories, validateDirectoryTracking, resetDirectoryTracking, repairDirectoryTracking } from '../core/directory-tracker.js';
import { loadUserConfig, getUserConfigDebugInfo, setOfflineMode, getOfflineMode, setAnalyticsEnabled, getAnalyticsEnabled, repairUserConfig, setPrivacyLevel, getPrivacyLevel, setTelemetryOptOut, getTelemetryOptOut } from '../core/user-config.js';
import { getApiService } from '../services/CliApiService.js';
import { info, success, error, warn } from '../utils/output.js';
/**
* Show detailed quota status
*/
async function showQuotaStatus() {
try {
const quotaUsage = await getQuotaUsage();
const quotaStatusSummary = await getQuotaStatusSummary();
info(chalk.blue.bold('š Directory Quota Status\n'));
// Overall status
if (quotaUsage.withinQuota) {
success(`ā
${quotaStatusSummary}`);
}
else {
error(`š« ${quotaStatusSummary}`);
}
// Detailed breakdown
info(chalk.cyan('\nš Quota Details:'));
info(chalk.gray(` Used: ${quotaUsage.used} directories`));
info(chalk.gray(` Limit: ${quotaUsage.quota} directories`));
info(chalk.gray(` Available: ${quotaUsage.available} directories`));
// Progress bar visualization
const progressBarWidth = 20;
const usedWidth = Math.min(progressBarWidth, Math.ceil((quotaUsage.used / quotaUsage.quota) * progressBarWidth));
const remainingWidth = progressBarWidth - usedWidth;
const usedBar = 'ā'.repeat(usedWidth);
const remainingBar = 'ā'.repeat(remainingWidth);
if (quotaUsage.withinQuota) {
info(chalk.green(` [${usedBar}${remainingBar}] ${Math.round((quotaUsage.used / quotaUsage.quota) * 100)}%`));
}
else {
info(chalk.red(` [${usedBar}${remainingBar}] ${Math.round((quotaUsage.used / quotaUsage.quota) * 100)}%`));
}
// Show locked directories
const trackedDirs = await getTrackedDirectories();
if (trackedDirs.length > 0) {
info(chalk.cyan('\nš Tracked Directories:'));
for (const dir of trackedDirs) {
info(chalk.gray(` š ${dir}`));
}
}
else {
info(chalk.yellow('\nš No directories are currently being tracked.'));
info(chalk.gray(' Lock some files to start using your quota.'));
}
// Recommendations
if (!quotaUsage.withinQuota) {
info(chalk.blue('\nš Increase Your Quota:'));
info(chalk.gray(' 1. Visit the ailock web portal'));
info(chalk.gray(' 2. Get auth codes through signup or referrals'));
info(chalk.gray(' 3. Run: ailock auth <your-auth-code>'));
info(chalk.gray(' 4. Continue protecting more directories'));
}
else if (quotaUsage.available <= 1) {
info(chalk.yellow('\nā ļø Running Low on Quota:'));
info(chalk.gray(' Consider getting more auth codes before you need them.'));
info(chalk.gray(' Visit the web portal to increase your quota.'));
}
}
catch (err) {
error('Failed to get quota status');
console.error(chalk.red('Details:'), err instanceof Error ? err.message : String(err));
}
}
/**
* Sync quota with the backend
*/
async function syncQuota() {
try {
info(chalk.cyan('š Syncing quota with backend...'));
const config = await loadUserConfig();
const apiService = getApiService();
// Try to get status from any available auth code
// In a real scenario, we'd need to store the user's current auth code
// For now, we'll just track the sync attempt
await apiService.trackUsage('status_check', {
metadata: { sync_requested: true }
});
success('ā
Sync completed');
info(chalk.gray(' Your local quota status has been updated.'));
}
catch (err) {
error('ā Failed to sync quota');
if (err instanceof Error && err.message.includes('offline')) {
info(chalk.gray(' You are in offline mode. Quota sync is not available.'));
}
else {
console.error(chalk.red('Details:'), err instanceof Error ? err.message : String(err));
info(chalk.gray(' Check your internet connection and try again.'));
}
}
}
/**
* Reset local quota tracking (for testing/troubleshooting)
*/
async function resetQuota(force) {
try {
if (!force) {
warn('ā ļø This will reset your local directory tracking.');
info(chalk.gray(' Use --force to confirm this action.'));
info(chalk.gray(' Your actual quota limit will not be affected.'));
return;
}
info(chalk.cyan('š Resetting local directory tracking...'));
await resetDirectoryTracking();
success('ā
Local directory tracking has been reset');
info(chalk.gray(' Your quota limit remains unchanged.'));
info(chalk.gray(' Locked directories are no longer being tracked for quota purposes.'));
info(chalk.gray(' Run: ailock status to see the current state.'));
}
catch (err) {
error('ā Failed to reset quota tracking');
console.error(chalk.red('Details:'), err instanceof Error ? err.message : String(err));
}
}
/**
* Show debug information
*/
async function showDebugInfo() {
try {
info(chalk.blue.bold('š Quota System Debug Information\n'));
// User configuration (without sensitive data)
const debugConfig = await getUserConfigDebugInfo();
info(chalk.cyan('š¤ User Configuration:'));
info(chalk.gray(` Machine UUID: ${debugConfig.machineUuid || 'Not set'}`));
info(chalk.gray(` Directory Quota: ${debugConfig.directoryQuota}`));
info(chalk.gray(` Tracked Directories: ${debugConfig.lockedDirectories.length}`));
info(chalk.gray(` Analytics Enabled: ${debugConfig.analyticsEnabled}`));
info(chalk.gray(` Offline Mode: ${debugConfig.offlineMode || false}`));
info(chalk.gray(` Last Sync: ${debugConfig.lastSyncAt || 'Never'}`));
info(chalk.gray(` Config Version: ${debugConfig.version}`));
// API configuration
const apiService = getApiService();
const apiInfo = apiService.getApiInfo();
info(chalk.cyan('\nš API Configuration:'));
info(chalk.gray(` Base URL: ${apiInfo.baseUrl}`));
info(chalk.gray(` Timeout: ${apiInfo.timeout}ms`));
info(chalk.gray(` Max Retries: ${apiInfo.maxRetries}`));
// Connectivity test
info(chalk.cyan('\nš” Connectivity Test:'));
const isConnected = await apiService.testConnectivity();
if (isConnected) {
success(' ā
API is reachable');
}
else {
error(' ā API is not reachable');
info(chalk.gray(' Check your internet connection or proxy settings'));
}
// Validation
const validationErrors = await validateDirectoryTracking();
info(chalk.cyan('\nā
Quota System Validation:'));
if (validationErrors.length === 0) {
success(' ā
No issues found');
}
else {
warn(` ā ļø Found ${validationErrors.length} issue(s):`);
for (const issue of validationErrors) {
warn(` ⢠${issue}`);
}
info(chalk.gray(' š” Run: ailock quota repair --auto # Attempt automatic repair'));
}
// Environment variables
const envVars = {
'AILOCK_API_URL': process.env.AILOCK_API_URL,
'AILOCK_DEBUG': process.env.AILOCK_DEBUG,
'AILOCK_OFFLINE': process.env.AILOCK_OFFLINE
};
info(chalk.cyan('\nš§ Environment Variables:'));
for (const [key, value] of Object.entries(envVars)) {
if (value) {
info(chalk.gray(` ${key}: ${value}`));
}
else {
info(chalk.gray(` ${key}: Not set`));
}
}
}
catch (err) {
error('ā Failed to get debug information');
console.error(chalk.red('Details:'), err instanceof Error ? err.message : String(err));
}
}
/**
* Repair quota system issues
*/
async function repairQuota(auto) {
try {
if (!auto) {
info(chalk.blue.bold('š§ Quota System Repair'));
info(chalk.gray(' This will attempt to fix issues with your quota configuration.'));
info(chalk.gray(' Use --auto to perform repairs without confirmation.'));
return;
}
info(chalk.cyan('š§ Repairing quota system issues...'));
// Repair user configuration
info(chalk.gray(' Checking user configuration...'));
const configRepairResult = await repairUserConfig();
if (configRepairResult.repaired) {
success('ā
User configuration repaired');
for (const fix of configRepairResult.issuesFixed) {
info(chalk.gray(` ⢠${fix}`));
}
if (configRepairResult.hadToReset) {
warn('ā ļø Configuration was reset to defaults');
info(chalk.gray(' Your quota and directory tracking have been reset.'));
}
}
else {
success('ā
User configuration is healthy');
}
// Repair directory tracking
info(chalk.gray(' Checking directory tracking...'));
const trackingRepairResult = await repairDirectoryTracking();
if (trackingRepairResult.repaired) {
success('ā
Directory tracking repaired');
for (const fix of trackingRepairResult.issuesFixed) {
info(chalk.gray(` ⢠${fix}`));
}
}
else {
success('ā
Directory tracking is healthy');
}
// Show remaining issues if any
if (trackingRepairResult.issuesRemaining.length > 0) {
warn('ā ļø Some issues could not be automatically resolved:');
for (const issue of trackingRepairResult.issuesRemaining) {
warn(` ⢠${issue}`);
}
info(chalk.gray(' You may need to manually resolve these issues or contact support.'));
}
if (configRepairResult.repaired || trackingRepairResult.repaired) {
info(chalk.blue('\nš Next Steps:'));
info(chalk.gray(' 1. Run: ailock status # Verify your current state'));
info(chalk.gray(' 2. Run: ailock quota status # Check quota information'));
if (configRepairResult.hadToReset) {
info(chalk.gray(' 3. Run: ailock auth <code> # Redeem auth codes if you have any'));
}
}
else {
success('\nš No repairs were needed - your quota system is healthy!');
}
}
catch (err) {
error('ā Failed to repair quota system');
console.error(chalk.red('Details:'), err instanceof Error ? err.message : String(err));
info(chalk.gray(' Try running with AILOCK_DEBUG=true for more information.'));
}
}
// Create the quota command with subcommands
export const quotaCommand = new Command('quota')
.description('Manage directory quota and usage tracking')
.addCommand(new Command('status')
.description('Show detailed quota status and usage')
.action(async () => {
await initializeUserConfig();
await showQuotaStatus();
}))
.addCommand(new Command('sync')
.description('Sync quota status with backend')
.action(async () => {
await initializeUserConfig();
await syncQuota();
}))
.addCommand(new Command('reset')
.description('Reset local directory tracking (for troubleshooting)')
.option('--force', 'Confirm the reset operation')
.action(async (options) => {
await initializeUserConfig();
await resetQuota(options.force);
}))
.addCommand(new Command('debug')
.description('Show debug information for troubleshooting')
.action(async () => {
await initializeUserConfig();
await showDebugInfo();
}))
.addCommand(new Command('config')
.description('Manage quota system configuration')
.option('--offline <mode>', 'Set offline mode (true/false)')
.option('--analytics <mode>', 'Set analytics enabled (true/false)')
.option('--privacy <level>', 'Set privacy level (minimal/standard/enhanced)')
.option('--telemetry <mode>', 'Set telemetry opt-out (true/false)')
.action(async (options) => {
await initializeUserConfig();
if (options.offline !== undefined) {
const offlineMode = options.offline.toLowerCase() === 'true';
await setOfflineMode(offlineMode);
success(`ā
Offline mode set to: ${offlineMode}`);
}
if (options.analytics !== undefined) {
const analyticsEnabled = options.analytics.toLowerCase() === 'true';
await setAnalyticsEnabled(analyticsEnabled);
success(`ā
Analytics enabled set to: ${analyticsEnabled}`);
}
if (options.privacy !== undefined) {
const privacyLevel = options.privacy.toLowerCase();
if (['minimal', 'standard', 'enhanced'].includes(privacyLevel)) {
await setPrivacyLevel(privacyLevel);
success(`ā
Privacy level set to: ${privacyLevel}`);
if (privacyLevel === 'enhanced') {
info(chalk.yellow(' Privacy level set to enhanced - analytics and telemetry disabled'));
}
}
else {
error('ā Invalid privacy level. Use: minimal, standard, or enhanced');
return;
}
}
if (options.telemetry !== undefined) {
const telemetryOptOut = options.telemetry.toLowerCase() === 'true';
await setTelemetryOptOut(telemetryOptOut);
success(`ā
Telemetry opt-out set to: ${telemetryOptOut}`);
}
if (!options.offline && !options.analytics && !options.privacy && !options.telemetry) {
// Show current configuration
const [offlineMode, analyticsEnabled, privacyLevel, telemetryOptOut] = await Promise.all([
getOfflineMode(),
getAnalyticsEnabled(),
getPrivacyLevel(),
getTelemetryOptOut()
]);
info(chalk.blue.bold('āļø Current Configuration:'));
info(chalk.gray(` Offline mode: ${offlineMode}`));
info(chalk.gray(` Analytics enabled: ${analyticsEnabled}`));
info(chalk.gray(` Privacy level: ${privacyLevel}`));
info(chalk.gray(` Telemetry opt-out: ${telemetryOptOut}`));
info(chalk.cyan('\nš” Usage:'));
info(chalk.gray(' ailock quota config --offline true # Enable offline mode'));
info(chalk.gray(' ailock quota config --analytics false # Disable analytics'));
info(chalk.gray(' ailock quota config --privacy enhanced # Set privacy to enhanced'));
info(chalk.gray(' ailock quota config --telemetry true # Opt out of telemetry'));
info(chalk.cyan('\nš Privacy Levels:'));
info(chalk.gray(' minimal - All tracking enabled (fastest development)'));
info(chalk.gray(' standard - Balanced privacy and functionality (default)'));
info(chalk.gray(' enhanced - Maximum privacy (disables analytics & telemetry)'));
}
}))
.addCommand(new Command('repair')
.description('Repair quota system issues and configuration problems')
.option('--auto', 'Perform repairs automatically without confirmation')
.action(async (options) => {
await initializeUserConfig();
await repairQuota(options.auto);
}));
//# sourceMappingURL=quota.js.map