import { R, Module, Process, Thread } from "./r2papi.js"; import { r2, R2PipeSync } from "./r2pipe.js"; /** * Class that interacts with the `r2ai` plugin (requires `rlang-python` and `r2i` r2pm packages to be installed). * Provides a way to script the interactions with different language models using javascript from inside radare2. * * @typedef R2AI */ export class R2AI { /** * Instance variable that informs if the `r2ai` plugin is loaded, must be true in order to use the rest of the methods of this class. * * @type {boolean} */ available: boolean = false; /** * Name of the model instantiated to be used for the subsequent calls. * * @type {string} */ model: string = ""; r2: R2PipeSync; constructor(r2: R2PipeSync, num?: number, model?: string) { this.r2 = r2; this.available = false; } checkAvailability(): boolean { if (this.available) { return true; } this.available = r2.cmd("r2ai -h").trim() !== ""; /* if (this.available) { if (num) { r2.call(`r2ai -n ${num}`) } // r2.call('r2ai -e DEBUG=1') if (model) { this.model = model; } } */ return this.available; } /** * Reset conversation messages */ reset() { this.checkAvailability(); if (this.available) { r2.call("r2ai -R"); } } /** * Set the role (system prompt) message for the language model to obey. * * @param {string} text containing the system prompt * @returns {boolean} true if successful */ setRole(msg: string): boolean { if (this.available) { r2.call(`r2ai -r ${msg}`); return true; } return false; } /** * Set the Model name or path to the GGUF file to use. * * @param {string} model name or path to GGUF file * @returns {boolean} true if successful */ setModel(modelName: string): boolean { if (this.available) { r2.call(`r2ai -m ${this.model}`); return true; } return false; } /** * Get the current selected model name. * * @returns {boolean} model name */ getModel(): string { if (this.available) { this.model = r2.call("r2ai -m").trim(); } return this.model; } /** * Get a list of suggestions for model names to use. * * @returns {string[]} array of strings containing the model names known to work */ listModels(): string[] { if (this.available) { const models = r2.call("r2ai -M"); return models .replace(/-m /, "") .trim() .split(/\n/g) .filter((x: string) => x.indexOf(":") !== -1); } return []; } /** * Send message to the language model to be appended to the current conversation (see `.reset()`) * * @param {string} text sent from the user to the language model * @returns {string} response from the language model */ query(msg: string): string { if (!this.available || msg == "") { return ""; } const fmsg = msg.trim().replace(/\n/g, "."); const response = r2.call(`r2ai ${fmsg}`); return response.trim(); } }