From 6d4bb0c6cbb0b05b0759887fda931451d6ca6328 Mon Sep 17 00:00:00 2001 From: Raj Sharma Date: Sat, 2 Nov 2024 12:48:38 +0530 Subject: [PATCH] feat: clustering for notes --- bun.lockb | Bin 462616 -> 463672 bytes exp.ts | 81 ++++++++++- package.json | 3 + tools/events.ts | 82 +++++++---- tools/index.ts | 22 +++ tools/message-anya.ts | 23 +++ tools/notes-executer.ts | 9 +- tools/notes-vectors.ts | 85 ++++++++++- tools/notes.ts | 50 +++++++ tools/software-engineer.ts | 279 +++++++++++++++++++++++++++++++++++++ 10 files changed, 599 insertions(+), 35 deletions(-) create mode 100644 tools/message-anya.ts create mode 100644 tools/software-engineer.ts diff --git a/bun.lockb b/bun.lockb index aa4fca5b5005be7edd8b2bee086725473b22e1ba..a93f9906780fe074cda47a905f8a2177d4c35f5b 100755 GIT binary patch delta 90200 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 { + const client = new Client(config.postgresConnectionOptions); + await client.connect(); + + const res = await client.query( + `SELECT ${config.columns.idColumnName} as id, ${config.columns.vectorColumnName} as vector + FROM ${config.tableName} LIMIT 5` + ); + await client.end(); + + // Inspect the data format of each vector + return res.rows.map((row, index) => { + console.log(`Row ${index} - Vector Type:`, typeof row.vector); + console.log(`Row ${index} - Vector Data:`, row.vector); + + let vector: number[] = []; + + // Determine the correct format based on observed type + if (Array.isArray(row.vector)) { + vector = row.vector; // If it's already an array, use as-is + } else if (typeof row.vector === "string") { + vector = JSON.parse(row.vector); // If string, parse as JSON + } else if (Buffer.isBuffer(row.vector)) { + vector = Array.from(row.vector); // If Buffer, convert to array of numbers + } else { + console.error("Unknown vector format:", row.vector); + } + + return { + id: row.id, + vector, + }; + }); +} + +// Run clustering on fetched embeddings +async function listClusters() { + const embeddings = await fetchEmbeddings(); + const vectors = embeddings.map((doc) => doc.vector); + + // Validate the format and contents of the vectors + vectors.forEach((vector, index) => { + if (!Array.isArray(vector) || vector.some(isNaN)) { + console.error(`Invalid vector at index ${index}:`, vector); + } + }); + + // Run K-means clustering with a specified number of clusters + const k = 3; // Number of clusters + const result = skmeans(vectors, k); + + // Log the cluster assignment for each document + embeddings.forEach((doc, index) => { + console.log(`Document ID: ${doc.id}, Cluster: ${result.idxs[index]}`); + }); + + console.log("Cluster assignments:", result.idxs); +} + +// Execute clustering function +listClusters().catch(console.error); diff --git a/package.json b/package.json index a4d1d18..a28e762 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@nextcloud/files": "^3.8.0", "@solyarisoftware/voskjs": "^1.2.8", "@types/node-cron": "^3.0.11", + "@types/skmeans": "^0.11.7", "@types/turndown": "^5.0.5", "@types/xml2js": "^0.4.14", "axios": "^1.7.3", @@ -32,6 +33,7 @@ "fuse.js": "^7.0.0", "fuzzysort": "^3.0.2", "i": "^0.3.7", + "kmeans-ts": "^1.0.4", "langchain": "^0.0.212", "llamaindex": "^0.8.0", "mathjs": "^12.2.1", @@ -48,6 +50,7 @@ "quickchart-js": "^3.1.3", "resend": "^4.0.0", "serpapi": "^2.0.0", + "skmeans": "^0.11.3", "turndown": "^7.2.0", "uuid": "^11.0.2", "whatsapp-web.js": "^1.26.0", diff --git a/tools/events.ts b/tools/events.ts index 6ebc185..efdef62 100644 --- a/tools/events.ts +++ b/tools/events.ts @@ -331,6 +331,24 @@ async function saveListenersToFile() { await fs.writeFile(LISTENERS_FILE_PATH, data, "utf-8"); } +/** + * Replaces placeholders in the format {{key}} in the template with corresponding values from the provided record. + * If the value is not a string, it will JSON stringify it before inserting. + * + * @param template - The string template containing placeholders like {{key}}. + * @param data - The record containing key-value pairs for replacement. + * @returns The formatted string with placeholders replaced by data values. + */ +function replacePlaceholders( + template: string, + data: Record +): string { + return template.replace(/{{\s*([^}]+)\s*}}/g, (_, key) => { + const value = data[key.trim()]; + return typeof value === "string" ? value : JSON.stringify(value); + }); +} + // Function to register a listener with the eventManager function registerListener(listener: EventListener) { const { eventId, description, userId, options, tool_names, notify } = @@ -398,10 +416,12 @@ function registerListener(listener: EventListener) { const is_voice = listener.eventId === "on_voice_message"; const is_new_todo_note = listener.eventId === "new_todo_for_anya"; + const is_message_from_a_manager = + listener.eventId.startsWith("message_from"); let attached_image: string | undefined = undefined; - if (is_voice || is_new_todo_note) { + if (is_voice || is_new_todo_note || is_message_from_a_manager) { tools = getTools( contextMessage.author.username, contextMessage @@ -449,7 +469,7 @@ function registerListener(listener: EventListener) { console.log("Running ASK for event listener: ", listener.description); const system_prompts = - is_voice || is_new_todo_note + is_voice || is_new_todo_note || is_message_from_a_manager ? await buildSystemPrompts(contextMessage) : undefined; @@ -494,14 +514,13 @@ function registerListener(listener: EventListener) { - **Will Auto Notify Creator of Listener:** ${notify ? "Yes" : "No"} - **Instruction:** ${listener.instruction} - **Important Note:** - - - If the above event and payload does **not** match the instruction, reply with the string **"IGNORE"** to skip executing the instruction for this payload. - - **Action Required:** - + **Action Required:** - Follow the instruction provided in the payload. - Return the notification text based on the instruction. + + **Important Note:** + - If the above event and payload does **not** match the instruction, reply with the string **"IGNORE"** to skip executing the instruction for this payload. + `; const voice_prompt = `You are in voice trigger mode. @@ -534,33 +553,46 @@ function registerListener(listener: EventListener) { Whatever you reply with will be sent to the user as a notification automatically. Do not use communication_manager to notify the same user. `; + const message_from_manager_prompt = `You just got a request from a manager. + + The manager has sent you a message which triggered this event. + + - Event ID: ${eventId} + - Payload: ${JSON.stringify(payload)} +`; + if (system_prompts) { prompt = `${system_prompts.map((p) => p.content).join("\n\n")}`; } - const response = !(is_voice || is_new_todo_note) - ? await ask({ - model: "gpt-4o-mini", - prompt, - tools, - }) - : await ask({ - model: attached_image ? "gpt-4o" : "gpt-4o-mini", - prompt, - message: is_voice ? voice_prompt : new_todo_note_prompt, - image_url: attached_image ?? undefined, - seed: `${is_voice ? "voice-anya" : "todos-from-user"}-${ - listener.id - }-${eventId}`, - tools, - }); + let promptToUse = prompt; + let seed = `${listener.id}-${eventId}`; + + if (is_voice) { + promptToUse = voice_prompt; + seed = `voice-anya-${listener.id}-${eventId}`; + } else if (is_new_todo_note) { + promptToUse = new_todo_note_prompt; + seed = `todos-from-user-${listener.id}-${eventId}`; + } else if (is_message_from_a_manager) { + promptToUse = message_from_manager_prompt; + seed = `message-from-manager-${listener.id}-${eventId}`; + } + + const response = await ask({ + model: attached_image ? "gpt-4o" : "gpt-4o-mini", + prompt: promptToUse, + image_url: attached_image ?? undefined, + seed, + tools, + }); const content = response.choices[0].message.content ?? undefined; const ignore = content?.includes("IGNORE"); if (ignore) { - console.log("Ignoring event: ", content); + console.log("Ignoring event: ", content, payload); return; } diff --git a/tools/index.ts b/tools/index.ts index 2d5eb78..223b9d9 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -60,6 +60,10 @@ import { communication_manager_tool } from "./communication"; import { send_sys_log } from "../interfaces/log"; import { init_anya_todos_watcher, init_notes_watcher } from "./notes-executer"; import { initVectorStoreSync } from "./notes-vectors"; +import { + dockerToolManager, + DockerToolManagerSchema, +} from "./software-engineer"; // get time function const GetTimeParams = z.object({}); @@ -460,6 +464,24 @@ Try to fix any errors that are returned at least once before sending to the user if user wants to create some automation based on some event.`, }), }, + { + name: "softwareEngineerManagerTool", + tool: zodFunction({ + function: (args) => dockerToolManager(args, context_message), + name: "software_engineer_manager", + schema: DockerToolManagerSchema, + description: `Software Engineer Manager Tool. +His name is Cody. He is a software engineer, and someone who loves technology. +He specializes in linux and devops. + +This tool can do anything related to what a tech person would do. +They can scape website to search something, summerize youtube videos by just link, download full videos and more. +This manager is like a whole other user that you are talking to. + +When talking to this manager, you can inform the user that you asked cody for this query etc. + `, + }), + }, { name: "restart", tool: zodFunction({ diff --git a/tools/message-anya.ts b/tools/message-anya.ts new file mode 100644 index 0000000..2c5626f --- /dev/null +++ b/tools/message-anya.ts @@ -0,0 +1,23 @@ +import { z } from "zod"; +import { zodFunction } from "."; +import { eventManager } from "../interfaces/events"; + +const MessageAnyaSchema = z.object({ + message: z.string(), +}); +export type MessageAnyaSchema = z.infer; + +async function message_anya({ message }: MessageAnyaSchema, event_id: string) { + const res = await eventManager.emitWithResponse(event_id, { + message, + }); + return JSON.stringify(res); +} +export const message_anya_tool = (event_id: string) => + zodFunction({ + function: async (args: MessageAnyaSchema) => + await message_anya(args, event_id), + name: "message_anya", + schema: MessageAnyaSchema, + description: "Send a message to Anya.", + }); diff --git a/tools/notes-executer.ts b/tools/notes-executer.ts index 593a58f..ad453ae 100644 --- a/tools/notes-executer.ts +++ b/tools/notes-executer.ts @@ -83,12 +83,11 @@ async function handleNoteInstruction( request: `The following is a note that the user left a message for you in. The file path is: ${filePath} The user's instruction for you is in the file content and starts with '!!' followed by the message or a attached audio message that you can Transcribe to get the actual instructions. - file content: - --- - ${fileContent} - --- - Make sure to remove the user's instruction line (line that starts with '!!') and the respective audio message if there is one after you have read it and done the necessary action. + Note: Make sure to remove the user's instruction line (line that starts with '!!') and the respective audio message if there is one after you have read it and done the necessary action. + + file content: + ${fileContent} `, }, context_message diff --git a/tools/notes-vectors.ts b/tools/notes-vectors.ts index 1c98dd2..ff386eb 100644 --- a/tools/notes-vectors.ts +++ b/tools/notes-vectors.ts @@ -6,6 +6,7 @@ import { import { OpenAIEmbeddings } from "@langchain/openai"; import { v4 as uuidv4 } from "uuid"; import * as crypto from "crypto"; +import skmeans from "skmeans"; let isSyncing = false; let isCleanupRunning = false; @@ -76,12 +77,15 @@ const config = { vectorColumnName: "vector", contentColumnName: "content", metadataColumnName: "metadata", + clusterColumnName: "cluster", }, distanceStrategy: "cosine" as DistanceStrategy, }; const vectorStore = await PGVectorStore.initialize(embeddings, config); +const CLUSTER_COUNT = 4; + // Main function to sync vector store export async function syncVectorStore() { if (isSyncing) { @@ -94,6 +98,8 @@ export async function syncVectorStore() { console.log("Starting vector store sync..."); const files = await getAllFiles("notes"); + let filesIndexed = 0; + for (const file of files) { const content = `filename: ${file.filename}\n${file.content}`; // Calculate checksum @@ -129,10 +135,10 @@ export async function syncVectorStore() { await vectorStore.addDocuments([document], { ids: [document.metadata.id], }); - + filesIndexed++; console.log(`Indexed ${file.filename}`); } - + filesIndexed > 0 && (await runClustering()); console.log("Vector store sync completed."); } catch (error) { console.error("Error during vector store sync:", error); @@ -161,16 +167,19 @@ export async function cleanupDeletedFiles() { const dbFiles = queryResult.rows; const files = await getAllFiles("notes"); const existingFilenames = files.map((file) => file.filename); + let deletedFiles = 0; for (const dbFile of dbFiles) { if (!existingFilenames.includes(dbFile.filename)) { // Delete the file from the vector store if it no longer exists in notes await vectorStore.delete({ ids: [dbFile.id] }); + deletedFiles++; console.log( `Deleted ${dbFile.filename} from vector store as it no longer exists.` ); } } + deletedFiles > 0 && (await runClustering()); } console.log("Cleanup of deleted files completed."); @@ -181,12 +190,82 @@ export async function cleanupDeletedFiles() { } } +// Ensure the cluster column exists in the table +async function ensureClusterColumn() { + await vectorStore.client?.query( + `ALTER TABLE ${config.tableName} ADD COLUMN IF NOT EXISTS ${config.columns.clusterColumnName} INT;` + ); + console.log("Ensured cluster column exists in the database."); +} + +// Function to generate clusters from stored embeddings and save them to the database +async function generateClusters(k: number) { + // Ensure the cluster column exists before proceeding + await ensureClusterColumn(); + + const queryResult = await vectorStore.client?.query( + `SELECT ${config.columns.idColumnName} as id, ${config.columns.vectorColumnName} as vector + FROM ${config.tableName}` + ); + + if (!queryResult) { + console.log("No embeddings found in the vector store."); + return; + } + + // Process embeddings and format data + const embeddings = queryResult.rows.map((row) => { + let vector: number[] = []; + + // Check vector data format and convert to number array if needed + if (Array.isArray(row.vector)) { + vector = row.vector; + } else if (typeof row.vector === "string") { + vector = JSON.parse(row.vector); + } else if (Buffer.isBuffer(row.vector)) { + vector = Array.from(row.vector); + } else { + console.error("Unknown vector format:", row.vector); + } + + return { + id: row.id, + vector, + }; + }); + + // Extract vectors for clustering + const vectors = embeddings.map((doc) => doc.vector); + + // Run clustering algorithm (K-means) + const result = skmeans(vectors, k); + + // Save each document’s cluster label in the database + for (const [index, doc] of embeddings.entries()) { + const cluster = result.idxs[index]; + await vectorStore.client?.query( + `UPDATE ${config.tableName} SET ${config.columns.clusterColumnName} = $1 WHERE ${config.columns.idColumnName} = $2`, + [cluster, doc.id] + ); + console.log(`Document ID: ${doc.id} assigned to Cluster: ${cluster}`); + } + + console.log("Cluster assignments saved to database."); +} + +// Exported function to run clustering +export async function runClustering() { + const k = CLUSTER_COUNT; + console.log("Generating clusters..."); + await generateClusters(k); +} + export async function initVectorStoreSync() { console.log("Starting vector store sync..."); await syncVectorStore(); setInterval(syncVectorStore, 1000 * 60 * 2); // Every 2 minutes await cleanupDeletedFiles(); - setInterval(cleanupDeletedFiles, 1000 * 60 * 60 * 12); // Every 12 hours + setInterval(cleanupDeletedFiles, 1000 * 60 * 60 * 2); // Every 12 hours } export function semantic_search_notes(query: string, limit: number) { diff --git a/tools/notes.ts b/tools/notes.ts index 46c9919..6be7798 100644 --- a/tools/notes.ts +++ b/tools/notes.ts @@ -10,6 +10,7 @@ import { semantic_search_notes, syncVectorStore } from "./notes-vectors"; import { readFileSync, writeFileSync } from "fs"; import { join } from "path"; import { tmpdir } from "os"; +import { message_anya_tool } from "./message-anya"; // Initialize WebDAV client const client = createClient("http://192.168.29.85/remote.php/dav/files/raj/", { @@ -425,6 +426,9 @@ Ensure the vault remains organized, filenames and paths are correct, and relaven You can try creating canvas files that use the open json canvas format - **Today's Date:** ${new Date().toDateString()} +- **Current Time:** ${new Date().toLocaleTimeString()} + +You also have access to message_anya tool that can ask an ai called Anya for help with scheduling notifications reminders or even calender events for the user, you can also fetch details about the same by asking her. - **ALL Vault's File structure for context:** --- @@ -443,11 +447,26 @@ ${potentially_relavent_files_paths.join("\n")} : "" } +- **Recently Modified Files:** +--- +${(await getRecentFiles({})).message} +--- + - **User Notes/Instructions for you:** --- ${notesManagerPromptFiles.map((f) => f.content).join("\n")} --- +- **Current User's Home page (quick-note.md):** +--- +${ + ( + await fetchFileContents({ + path: "quick-note.md", + }) + ).message +} + Note: When the user is trying to create/add a note, check the templates directory for any relevant templates if available. If available, fetch the relevant template and create the note based on the template. `, message: request, @@ -501,6 +520,36 @@ export async function transcribeAudioFile({ } } +export async function getRecentFiles({}): Promise { + const limit = 5; + try { + const files = await client.getDirectoryContents("notes", { + details: true, + deep: true, + }); + + const fileList = Array.isArray(files) ? files : files.data; + const sortedFiles = fileList + .filter((file) => file.type === "file") + .sort((a, b) => { + const aTime = new Date(a.lastmod).getTime(); + const bTime = new Date(b.lastmod).getTime(); + return bTime - aTime; + }); + + const latestFiles = sortedFiles + .slice(0, limit) + .map((file) => file.filename); + + return { + success: true, + message: latestFiles.length > 0 ? latestFiles : "No files found", + }; + } catch (error: any) { + return { success: false, message: error.message }; + } +} + // Integration into runnable tools export let webdav_tools: RunnableToolFunction[] = [ zodFunction({ @@ -552,6 +601,7 @@ export let webdav_tools: RunnableToolFunction[] = [ schema: MoveItemParams, description: "Move a note file or directory.", }), + message_anya_tool("message_from_notes_manager"), zodFunction({ function: semanticSearchNotes, name: "semanticSearchNotes", diff --git a/tools/software-engineer.ts b/tools/software-engineer.ts new file mode 100644 index 0000000..3f0aae5 --- /dev/null +++ b/tools/software-engineer.ts @@ -0,0 +1,279 @@ +import { z } from "zod"; +import { $ } from "zx"; +import { zodFunction } from "./"; +import { Message } from "../interfaces/message"; +import { ask } from "./ask"; +import { memory_manager_init, memory_manager_guide } from "./memory-manager"; +import { ChatCompletion } from "openai/resources/index.mjs"; +import { eventManager } from "../interfaces/events"; + +// Schema for Docker Tool Manager input +export const DockerToolManagerSchema = z.object({ + message: z.string(), + wait_for_reply: z + .boolean() + .optional() + .describe( + "Wait for a reply from cody. if false or not defined cody will do the task in the background." + ), +}); + +export type DockerToolManager = z.infer; + +// Schema for running commands on the Docker container +export const RunCommandParams = z.object({ + commands: z + .array(z.string()) + .describe("An array of commands to run in the Docker container"), + wait: z + .boolean() + .optional() + .describe( + "Wait for the command to finish before proceeding. defaults to true." + ), + stdout: z + .boolean() + .optional() + .describe( + "Weather to return the output of the command. defaults to true. You can make this false for cases where you dont want to return the output of the command, example updating env or installing packages." + ), + stderr: z + .boolean() + .optional() + .describe("Weather to return the error of the command. defaults to true."), +}); +export type RunCommandParams = z.infer; + +const containerName = "anya-manager-container"; +export async function run_command({ + commands, + wait = true, + stderr = true, + stdout = true, +}: RunCommandParams): Promise<{ + stdout?: string; + error?: string; + failedCommand?: string; +}> { + // Step 1: Check if the container exists and is running + try { + const isRunning = + await $`docker inspect -f '{{.State.Running}}' ${containerName}`; + if (isRunning.stdout.trim() !== "true") { + console.log(`Container ${containerName} is not running. Starting it...`); + await $`docker start ${containerName}`; + } + } catch (checkError) { + console.log(`Container ${containerName} does not exist. Creating it...`); + try { + // Create a new always-running Ubuntu container with /anya mounted + await $`docker run -d --name anya-manager-container --restart always -v /anya:/anya python:3.10 /bin/bash -c "while true; do sleep 3600; done"`; + } catch (createError: any) { + console.error( + `Error creating container ${containerName}: ${ + createError.stderr || createError.message + }` + ); + return { error: createError.stderr || createError.message }; + } + } + + if (!wait) { + // Return early if not waiting for command to finish + return { stdout: "Command execution started in the background." }; + } + + // Step 2: Execute commands sequentially + let combinedStdout = ""; + for (let i = 0; i < commands.length; i++) { + const command = commands[i]; + console.log( + `Executing Docker command: docker exec ${containerName} /bin/bash -c "${command}"` + ); + + try { + const processOutput = + await $`docker exec ${containerName} /bin/bash -c ${command}`; + console.log(`Command executed successfully: ${command}`); + if (stdout) { + combinedStdout += processOutput.stdout; + } + } catch (runError: any) { + console.error( + `Error during command execution at command index ${i}: ${ + runError.stderr || runError.message + }` + ); + if (stderr) { + return { + error: runError.stderr || runError.message, + failedCommand: command, + }; + } + } + } + + // All commands executed successfully + console.log("All commands executed successfully."); + return { stdout: combinedStdout || "All commands executed successfully." }; +} + +// Tool definition for running commands in the Docker container +export const run_command_tool = { + name: "runCommand", + tool: zodFunction({ + function: async (args: RunCommandParams) => await run_command(args), + name: "run_command", + schema: RunCommandParams, + description: + "Run commands in the manager's Docker container with a description of their purpose.", + }), +}; + +// Main Docker Tool Manager function +export async function dockerToolManager( + { message, wait_for_reply }: DockerToolManager, + context_message: Message +): Promise<{ response: string }> { + console.log("Docker Tool Manager invoked with message:", message); + const toolsPrompt = `# You are Cody. + +You are a software engineer, and someone who loves technology. + +You specialize in linux and devops, and a python expert. + +You exist inside a docker container named '${containerName}'. + +The current time is: ${new Date().toLocaleString()}. + +## Responsibilities: +1. You have access to a docker container of image python version 3.10 (based on Debian) that you can run commands on. +2. You can install software, update configurations, or run scripts in the environment. +3. You can presonalise the environment to your liking. +4. Help the user when they ask you for something to be done. + +### Container details: +- The container is always running. +- The container has a volume mounted at /anya which persists data across container restarts. +- /anya is the only directory accessible to the user. + +## The /anya/readme.md file + +1. You can use the file at /anya/readme.md to keep track of all the changes you make to the environment. + +2. These changes can include installing new software, updating configurations, or running scripts. + +3. This file can also contain any account credentials or API keys that you saved with some description so that you know what they are for. + +4. It is important that you keep /anya/readme.md updated as to not repeat yourself, the /anya/readme.md acts as your memory. + +The current data from /anya/readme.md is: +\`\`\` +${await $`cat /anya/readme.md`} +\`\`\` + +You can also use /anya/memories/ directory to store even more specific information incase the /anya/readme.md file gets too big. + +Current /anya/memories/ directory contents (tree /anya/memories/ command output): +\`\`\` +${await $`tree /anya/memories/`} +\`\`\` + +You can also save scripts in /anya/scripts/ directory and run them when needed. + +Current /anya/scripts/ directory contents (ls /anya/scripts/ command output): +\`\`\` +${await $`ls /anya/scripts/`} +\`\`\` +This directory can contain both python or any language script based on your preference. + +When you create a script in /anya/scripts/ directory you also should create a similarly named file prefixed with instruction_ that explains how to run the script. + +This will help you run older scripts. + +You can also keep all your python dependencies in a virtual env inside /anya/scripts/venv/ directory. + +You can also use the /anya/media/ dir to store media files, You can arrange them in sub folders you create as needed. + +Current /anya/media/ directory contents (ls /anya/media/ command output): +\`\`\` +${await $`ls /anya/media/`} +\`\`\` + + +Example flow: +User: plz let me download this youtube video https://youtube.com/video +What you need to do: +1. Look at the /anya/scripts/ data if there is a script to download youtube videos. +2. If there is no script, create a new script to download youtube videos while taking the param as the youtube url and the output file path and save it in /anya/scripts/ directory and also create a instruction_download_youtube_video.md file. +3. look at the instruction_download_youtube_video.md file to see how to run that script. +4. Run the script with relavent params. +5. Update the /anya/readme.md file with the changes you had to make to the environment like installing dependencies or creating new scripts. +6. Reply with the file path of the youtube video, and anything else you want. + +You can also leave notes for yourself in the same file for future reference of changes you make to your environment. +`; + + // Load tools for memory manager and Docker command execution + const tools = [run_command_tool.tool]; + + let response: ChatCompletion; + + if (!wait_for_reply) { + const timestamp = new Date().toTimeString(); + setTimeout(async () => { + const startTime = Date.now(); + try { + response = await ask({ + model: "gpt-4o", + prompt: `${toolsPrompt}`, + tools: tools, + message: message, + }); + } catch (error: any) { + console.error(`Error during ask function: ${error.message}`); + return { response: `An error occurred: ${error.message}` }; + } + const endTime = Date.now(); + const executionTime = endTime - startTime; + console.log(`Execution time: ${executionTime}ms`); + + eventManager.emit("message_from_cody", { + users_request: message, + users_request_timestamp: timestamp, + codys_response: response.choices[0].message.content || "NULL", + execution_time: `${executionTime}ms`, + }); + }, 0); + + return { + response: + "Cody will take care of your request in the background and ping you later through an event.", + }; + } + + try { + response = await ask({ + model: "gpt-4o", + prompt: toolsPrompt, + tools: tools, + message: message, + }); + } catch (error: any) { + console.error(`Error during ask function: ${error.message}`); + return { response: `An error occurred: ${error.message}` }; + } + + console.log("Docker Tool Manager response:", response); + return { response: response.choices[0].message.content || "NULL" }; +} + +// Tool definition for the Docker Tool Manager +export const docker_tool_manager_tool = (context_message: Message) => + zodFunction({ + function: async (args: DockerToolManager) => + await dockerToolManager(args, context_message), + name: "docker_tool_manager", + schema: DockerToolManagerSchema, + description: `Docker Tool Manager: Manages a Docker container for command execution, utilizing memory for tracking and retrieving past executions.`, + });