UNPKG

@wityai/root2-cli

Version:

Command-line interface for Root2 vector memory layer

348 lines • 13.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.importFileCommand = importFileCommand; const chalk_1 = __importDefault(require("chalk")); const inquirer_1 = __importDefault(require("inquirer")); const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const root2_api_client_1 = require("@wityai/root2-api-client"); const config_1 = require("../utils/config"); const formatting_1 = require("../utils/formatting"); const spinner_1 = require("../utils/spinner"); const memory_blocks_1 = require("./memory-blocks"); function importFileCommand(program) { program .command("import-file") .alias("if") .description("Import a single file into Root2 knowledge base") .argument("<filePath>", "Path to the file to import") .option("--memory-block <id>", "Memory block ID to import into") .option("--name <name>", "Custom name for the file (optional)") .option("--metadata <metadata>", "JSON string of metadata to attach") .option("--dry-run", "Preview what would be imported without actually importing") .option("-v, --verbose", "Show detailed progress information") .action(async (filePath, options) => { try { const config = await (0, config_1.validateConfig)(); const apiClient = new root2_api_client_1.Root2Api({ clientId: config.clientId, apiKey: config.apiKey, apiHost: config.apiHost, enableLogging: config.verbose || options.verbose || false, }); await importSingleFile(apiClient, filePath, options); } catch (error) { console.error(formatting_1.format.error(error instanceof Error ? error.message : "Unknown error")); process.exit(1); } }); program .command("import-file-interactive") .alias("ifi") .description("Import a file with interactive prompts") .action(async () => { try { const config = await (0, config_1.validateConfig)(); const apiClient = new root2_api_client_1.Root2Api({ clientId: config.clientId, apiKey: config.apiKey, apiHost: config.apiHost, enableLogging: config.verbose || false, }); await interactiveFileImport(apiClient); } catch (error) { console.error(formatting_1.format.error(error instanceof Error ? error.message : "Unknown error")); process.exit(1); } }); } async function importSingleFile(apiClient, filePath, options) { let memoryBlockId; if (options.memoryBlock) { if (!(0, memory_blocks_1.isValidMemoryBlockId)(options.memoryBlock)) { throw new Error(`Invalid memory block ID format: ${options.memoryBlock}`); } memoryBlockId = options.memoryBlock; } else { memoryBlockId = await (0, memory_blocks_1.selectMemoryBlock)(apiClient); } const resolvedPath = path.resolve(filePath); if (!(await fs.pathExists(resolvedPath))) { throw new Error(`File not found: ${filePath}`); } const stats = await fs.stat(resolvedPath); if (!stats.isFile()) { throw new Error(`Path is not a file: ${filePath}`); } let metadata; if (options.metadata) { try { metadata = JSON.parse(options.metadata); } catch (error) { throw new Error("Invalid metadata JSON format"); } } console.log(chalk_1.default.cyan("\nšŸ“„ File Import Information:")); console.log(` ${chalk_1.default.blue("File Path")}: ${formatting_1.format.filePath(resolvedPath)}`); console.log(` ${chalk_1.default.blue("File Size")}: ${formatFileSize(stats.size)}`); console.log(` ${chalk_1.default.blue("File Type")}: ${path.extname(resolvedPath) || "No extension"}`); console.log(` ${chalk_1.default.blue("Modified")}: ${stats.mtime.toLocaleDateString()}`); if (options.name) { console.log(` ${chalk_1.default.blue("Custom Name")}: ${options.name}`); } if (metadata) { console.log(` ${chalk_1.default.blue("Metadata")}: ${JSON.stringify(metadata, null, 2)}`); } if (options.dryRun) { console.log(formatting_1.format.info("\nšŸ” Dry run mode - no actual import will be performed")); console.log(formatting_1.format.success("āœ… File validation passed. Ready for import.")); return; } const { shouldProceed } = await inquirer_1.default.prompt([ { type: "confirm", name: "shouldProceed", message: "Proceed with import?", default: true, }, ]); if (!shouldProceed) { console.log(formatting_1.format.info("Import cancelled.")); return; } const importOptions = { fileName: options.name, metadata, verbose: options.verbose, }; const result = await (0, spinner_1.withSpinner)(`Importing file: ${path.basename(filePath)}...`, () => apiClient.importFile(memoryBlockId, { filePath: resolvedPath, fileName: importOptions.fileName, metadata: importOptions.metadata, }), { successText: "File imported successfully", errorText: "File import failed", }); if (result.success && result.data) { console.log(formatting_1.format.success("\nāœ… Import completed successfully!")); console.log(` ${chalk_1.default.blue("Import ID")}: ${result.data.id || "N/A"}`); console.log(` ${chalk_1.default.blue("Status")}: ${result.data.status || "N/A"}`); if (result.data.metadata) { console.log(` ${chalk_1.default.blue("Processed")}: ${result.data.metadata.processedAt || "N/A"}`); } if (options.verbose && result.data.metadata) { console.log("\nšŸ“Š Processing Details:"); console.log(formatting_1.format.json(result.data.metadata)); } } else { throw new Error(result.error || "Import failed with unknown error"); } } async function interactiveFileImport(apiClient) { console.log(chalk_1.default.cyan("\nšŸ“„ Interactive File Import\n")); const memoryBlockId = await (0, memory_blocks_1.selectMemoryBlock)(apiClient); const answers = await inquirer_1.default.prompt([ { type: "input", name: "filePath", message: "Enter the file path to import:", validate: async (input) => { if (!input.trim()) { return "File path is required"; } const resolvedPath = path.resolve(input.trim()); if (!(await fs.pathExists(resolvedPath))) { return `File not found: ${input}`; } const stats = await fs.stat(resolvedPath); if (!stats.isFile()) { return `Path is not a file: ${input}`; } return true; }, }, { type: "input", name: "customName", message: "Custom file name (optional):", default: "", }, { type: "confirm", name: "addMetadata", message: "Add metadata to the file?", default: false, }, ]); let metadata; if (answers.addMetadata) { const metadataAnswers = await collectMetadata(); if (Object.keys(metadataAnswers).length > 0) { metadata = metadataAnswers; } } const options = { memoryBlock: memoryBlockId, name: answers.customName || undefined, metadata: metadata ? JSON.stringify(metadata) : undefined, verbose: false, dryRun: false, }; await importSingleFile(apiClient, answers.filePath, options); } async function collectMetadata() { const metadata = {}; console.log(chalk_1.default.yellow("\nšŸ·ļø Adding Metadata (press Enter with empty key to finish):\n")); while (true) { const { key } = await inquirer_1.default.prompt([ { type: "input", name: "key", message: "Metadata key:", default: "", }, ]); if (!key.trim()) { break; } const { value, valueType } = await inquirer_1.default.prompt([ { type: "list", name: "valueType", message: "Value type:", choices: [ { name: "String", value: "string" }, { name: "Number", value: "number" }, { name: "Boolean", value: "boolean" }, { name: "JSON", value: "json" }, ], default: "string", }, { type: "input", name: "value", message: `Value for "${key}":`, validate: (input, answers) => { if (!input.trim() && answers.valueType !== "boolean") { return "Value is required"; } if (answers.valueType === "number" && isNaN(Number(input))) { return "Value must be a valid number"; } if (answers.valueType === "json") { try { JSON.parse(input); } catch { return "Value must be valid JSON"; } } return true; }, }, ]); switch (valueType) { case "number": metadata[key] = Number(value); break; case "boolean": metadata[key] = ["true", "yes", "1", "on"].includes(value.toLowerCase()); break; case "json": metadata[key] = JSON.parse(value); break; case "string": default: metadata[key] = value; break; } console.log(chalk_1.default.green(`āœ“ Added: ${key} = ${JSON.stringify(metadata[key])}`)); } return metadata; } function formatFileSize(bytes) { const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; if (bytes === 0) return "0 Bytes"; const i = Math.floor(Math.log(bytes) / Math.log(1024)); const size = bytes / Math.pow(1024, i); return `${Math.round(size * 100) / 100} ${sizes[i]}`; } function isSupportedFileType(filePath) { const supportedExtensions = [ ".txt", ".md", ".pdf", ".doc", ".docx", ".html", ".htm", ".json", ".csv", ".rtf", ".odt", ".pages", ]; const ext = path.extname(filePath).toLowerCase(); return supportedExtensions.includes(ext); } function getFileTypeDescription(filePath) { const ext = path.extname(filePath).toLowerCase(); const typeMap = { ".txt": "Plain Text", ".md": "Markdown", ".pdf": "PDF Document", ".doc": "Word Document (Legacy)", ".docx": "Word Document", ".html": "HTML Document", ".htm": "HTML Document", ".json": "JSON Data", ".csv": "CSV Data", ".rtf": "Rich Text Format", ".odt": "OpenDocument Text", ".pages": "Apple Pages", }; return typeMap[ext] || `${ext.toUpperCase()} File`; } //# sourceMappingURL=import-file.js.map