File size: 3,989 Bytes
f8b5d42 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
// Plugin CAN ONLY BE USE IN DEVELOPMENT.
const { input } = require("@inquirer/prompts");
const chalk = require("chalk");
const { RetryError } = require("../error");
/**
* Command-line Interface plugin. It prints the messages on the console and asks for feedback
* while the conversation is running in the background.
*/
const cli = {
name: "cli",
startupConfig: {
params: {},
},
plugin: function ({ simulateStream = true } = {}) {
return {
name: this.name,
setup(aibitat) {
let printing = [];
aibitat.onError(async (error) => {
let errorMessage =
error?.message || "An error occurred while running the agent.";
console.error(chalk.red(` error: ${errorMessage}`), error);
});
aibitat.onStart(() => {
console.log();
console.log("🚀 starting chat ...\n");
printing = [Promise.resolve()];
});
aibitat.onMessage(async (message) => {
const next = new Promise(async (resolve) => {
await Promise.all(printing);
await this.print(message, simulateStream);
resolve();
});
printing.push(next);
});
aibitat.onTerminate(async () => {
await Promise.all(printing);
console.log("🚀 chat finished");
});
aibitat.onInterrupt(async (node) => {
await Promise.all(printing);
const feedback = await this.askForFeedback(node);
// Add an extra line after the message
console.log();
if (feedback === "exit") {
console.log("🚀 chat finished");
return process.exit(0);
}
await aibitat.continue(feedback);
});
},
/**
* Print a message on the terminal
*
* @param message
* // message Type { from: string; to: string; content?: string } & {
state: 'loading' | 'error' | 'success' | 'interrupt'
}
* @param simulateStream
*/
print: async function (message = {}, simulateStream = true) {
const replying = chalk.dim(`(to ${message.to})`);
const reference = `${chalk.magenta("✎")} ${chalk.bold(
message.from
)} ${replying}:`;
if (!simulateStream) {
console.log(reference);
console.log(message.content);
// Add an extra line after the message
console.log();
return;
}
process.stdout.write(`${reference}\n`);
// Emulate streaming by breaking the cached response into chunks
const chunks = message.content?.split(" ") || [];
const stream = new ReadableStream({
async start(controller) {
for (const chunk of chunks) {
const bytes = new TextEncoder().encode(chunk + " ");
controller.enqueue(bytes);
await new Promise((r) =>
setTimeout(
r,
// get a random number between 10ms and 50ms to simulate a random delay
Math.floor(Math.random() * 40) + 10
)
);
}
controller.close();
},
});
// Stream the response to the chat
for await (const chunk of stream) {
process.stdout.write(new TextDecoder().decode(chunk));
}
// Add an extra line after the message
console.log();
console.log();
},
/**
* Ask for feedback to the user using the terminal
*
* @param node //{ from: string; to: string }
* @returns
*/
askForFeedback: function (node = {}) {
return input({
message: `Provide feedback to ${chalk.yellow(
node.to
)} as ${chalk.yellow(
node.from
)}. Press enter to skip and use auto-reply, or type 'exit' to end the conversation: `,
});
},
};
},
};
module.exports = { cli };
|