@wityai/root2-cli
Version:
Command-line interface for Root2 vector memory layer
348 lines ⢠13.2 kB
JavaScript
;
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