Added browse command and project handlers

This commit is contained in:
2024-08-21 13:26:34 -05:00
parent b4c9176a1f
commit 5c17823a0f
4 changed files with 187 additions and 55 deletions
+41 -25
View File
@@ -2,35 +2,54 @@ import os
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ContextTypes from telegram.ext import ContextTypes
async def browse_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: browse_command_bot = None
async def browse_command(update: Update, context: ContextTypes.DEFAULT_TYPE, bot) -> None:
global browse_command_bot
browse_command_bot = bot
prompts_dir = "prompts" prompts_dir = "prompts"
await navigate_to(prompts_dir, update.message.reply_text)
async def navigate_to(directory: str, updateMethod) -> None:
try: try:
# Get all items in the prompts directory subdirs, files = await get_files_and_directories(directory)
items = os.listdir(prompts_dir)
existing_buttons = []
if (directory != "prompts"):
parent_directory = os.path.split(directory)[0]
existing_buttons.append([InlineKeyboardButton("↩️ Back", callback_data=f"browse:{parent_directory}")])
# Separate and sort subdirectories and files reply_markup = await create_keyboard(subdirs, files, existing_buttons)
subdirs = sorted([item for item in items if os.path.isdir(os.path.join(prompts_dir, item))])
files = sorted([item for item in items if os.path.isfile(os.path.join(prompts_dir, item))])
# Create keyboard layout await updateMethod("Browse files and directories:", reply_markup=reply_markup)
keyboard = []
for subdir in subdirs:
keyboard.append([InlineKeyboardButton(f"[{subdir}]", callback_data=f"browse:{subdir}")])
for file in files:
keyboard.append([InlineKeyboardButton(file, callback_data=f"file:{file}")])
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text("Browse files and directories:", reply_markup=reply_markup)
except FileNotFoundError: except FileNotFoundError:
await update.message.reply_text("The 'prompts' directory does not exist.") await updateMethod(f"The {directory} directory does not exist.")
except Exception as e: except Exception as e:
await update.message.reply_text(f"An error occurred: {str(e)}") await updateMethod(f"An error occurred: {str(e)}")
async def create_keyboard(subdirs, files, existing_buttons) -> InlineKeyboardMarkup:
keyboard = existing_buttons
for subdir in subdirs:
keyboard.append([InlineKeyboardButton(subdir, callback_data=f"browse:{subdir}")])
for file in files:
keyboard.append([InlineKeyboardButton(file, callback_data=f"file:{file}")])
return InlineKeyboardMarkup(keyboard)
async def get_files_and_directories(directory: str) -> list:
# Get all items in the prompts directory
items = os.listdir(directory)
# Separate and sort subdirectories and files
subdirs = sorted([os.path.join(directory, item) for item in items if os.path.isdir(os.path.join(directory, item))])
files = sorted([os.path.join(directory, item) for item in items if os.path.isfile(os.path.join(directory, item))])
return subdirs, files
# This function will need to be called when a button is pressed # This function will need to be called when a button is pressed
async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
global browse_command_bot
query = update.callback_query query = update.callback_query
await query.answer() await query.answer()
@@ -38,13 +57,10 @@ async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) ->
if data.startswith("browse:"): if data.startswith("browse:"):
# Handle subdirectory navigation (for future implementation) # Handle subdirectory navigation (for future implementation)
subdir = data.split(":")[1] subdir = data.split(":")[1]
await query.edit_message_text(f"Navigating to [{subdir}] is not yet implemented.") await navigate_to(subdir, query.edit_message_text)
elif data.startswith("file:"): elif data.startswith("file:"):
# Handle file selection # Handle file selection
file = data.split(":")[1] file_path = data.split(":")[1]
file_path = os.path.join('prompts', file)
os.environ['SYSTEM_PROMPT_PATH'] = file_path os.environ['SYSTEM_PROMPT_PATH'] = file_path
await query.edit_message_text(f"Selected: {file}. SYSTEM_PROMPT_PATH updated.") browse_command_bot.system_prompt = browse_command_bot.load_system_prompt()
await query.edit_message_text(f"Selected: {file_path}. System prompt updated.")
# Optionally, you may want to reload the system prompt here if needed.
# bot.system_prompt = bot.load_system_prompt() # Uncomment if you have access to the bot instance.
+48
View File
@@ -0,0 +1,48 @@
# VP of Technology: Orchestrator of AI Potential
As the VP of Technology, your role is to harness the power of AI agents, guiding their flow of intelligence towards productive outcomes. Your mission is to create an ecosystem where AI potential is fully realized, overcoming inherent challenges and maximizing utility.
## Core Responsibilities
### 1. Flow Management
- **Create Pathways:** Design clear routes for AI intelligence to flow towards desired outcomes.
- **Remove Obstacles:** Identify and eliminate bottlenecks that hinder AI productivity.
- **Harness Momentum:** Utilize the natural "downhill flow" of AI thinking to power innovative solutions.
### 2. Agent Optimization
- **Overcome Chattiness:** Implement strategies to focus AI communication on essential information.
- **Combat Laziness:** Develop frameworks that encourage thorough implementation, especially in code stubs.
- **Broaden Perspectives:** Implement techniques to expand AI's focus beyond single-minded approaches.
### 3. Iterative Refinement
- **Zeno's Paradox Awareness:** Recognize that AI outputs often approach solutions asymptotically.
- **Convergence Strategies:** Develop methods to push AI outputs from "near-perfect" to "complete and usable."
### 4. Research Coordination
- **Expert Assembly:** Dynamically compose teams of AI "experts" for comprehensive problem analysis.
- **Solution Scouting:** Guide AI agents in exploring existing solutions before proposing new ones.
- **Synthesis and Reporting:** Collate findings into clear, actionable insights for decision-making.
### 5. Resource Management
- **Funding Requests:** Present well-justified proposals for necessary resources (e.g., web hosting, AI inference).
- **Efficiency Optimization:** Continuously seek ways to maximize output while minimizing resource consumption.
### 6. Project Oversight
- **Status Monitoring:** Maintain a high-level view of project progress and bottlenecks.
- **Clarification Interface:** Serve as the primary point of contact for answering project-related queries.
### 7. Vision and Strategy
- **Future-Proofing:** Anticipate technological trends and position the company to leverage emerging opportunities.
## Key Traits
- **Adaptive Thinking:** Quickly adjust strategies based on AI behavior and project needs.
- **Systems Perspective:** Understand how individual AI actions contribute to larger goals.
- **Communication Mastery:** Translate complex AI concepts into clear, actionable insights for all stakeholders.
- **Leadership:** Your decisions are guided but your implementation is yours. Own your successes and mistakes, lead by example and stay firm.
Your success is measured by your ability to create an environment where AI agents consistently achieve 100% usefulness, turning potential into tangible results that drive the company forward.
When looking at the repository, list all files and look at the ones ending with .md. If they are out of date, confusing or wrong this needs to be rectified. Keep in mind any files you see are all on the main branch, you don't have access to other branches.
Interact with the project using github issues/projects, and chatting with the user.
+1 -1
View File
@@ -110,7 +110,7 @@ class TelegramHelper:
await asyncio.sleep(60) # Check every 60 seconds await asyncio.sleep(60) # Check every 60 seconds
async def browse(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def browse(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await browse_command(update, context) await browse_command(update, context, self.bot)
def run(self): def run(self):
application = Application.builder().token(self.telegram_bot_token).build() application = Application.builder().token(self.telegram_bot_token).build()
+97 -29
View File
@@ -59,6 +59,34 @@ class GitHubTool(BaseTool):
"required": ["path"] "required": ["path"]
} }
}, },
{
"name": "list_files",
"description": "List files in a directory of the repository",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Path to the directory in the repository"
}
},
"required": ["path"]
}
},
{
"name": "search_code",
"description": "Search for code in the repository",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query"
}
},
"required": ["query"]
}
},
{ {
"name": "create_branch", "name": "create_branch",
"description": "Create a new branch in the repository", "description": "Create a new branch in the repository",
@@ -123,34 +151,6 @@ class GitHubTool(BaseTool):
"required": ["title", "body"] "required": ["title", "body"]
} }
}, },
{
"name": "list_files",
"description": "List files in a directory of the repository",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Path to the directory in the repository"
}
},
"required": ["path"]
}
},
{
"name": "search_code",
"description": "Search for code in the repository",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query"
}
},
"required": ["query"]
}
},
{ {
"name": "get_commit_history", "name": "get_commit_history",
"description": "Get commit history for a file", "description": "Get commit history for a file",
@@ -505,9 +505,33 @@ class GitHubTool(BaseTool):
}, },
"required": ["card_id", "content_id", "content_type"] "required": ["card_id", "content_id", "content_type"]
} }
},
{
"name": "list_project_boards",
"description": "List project boards associated with the repository",
"parameters": {}
},
{
"name": "view_project_board_items",
"description": "View items (columns and cards) in a specific project board",
"parameters": {
"type": "object",
"properties" : {
"project_id": {
"type": "integer",
"description": "ID of the project board"
}
},
"required": ["project_id"]
}
} }
] ]
@metrics.measure @metrics.measure
def execute(self, function_name, **kwargs): def execute(self, function_name, **kwargs):
self.logger.info(f"Executing: {function_name}") self.logger.info(f"Executing: {function_name}")
@@ -565,6 +589,10 @@ class GitHubTool(BaseTool):
return self._move_project_card(kwargs["card_id"], kwargs["position"], kwargs["column_id"]) return self._move_project_card(kwargs["card_id"], kwargs["position"], kwargs["column_id"])
elif function_name == "link_issue_to_project_card": elif function_name == "link_issue_to_project_card":
return self._link_issue_to_project_card(kwargs["card_id"], kwargs["content_id"], kwargs["content_type"]) return self._link_issue_to_project_card(kwargs["card_id"], kwargs["content_id"], kwargs["content_type"])
elif function_name == "list_project_boards":
return self._list_project_boards()
elif function_name == "view_project_board_items":
return self._view_project_board_items(kwargs["project_id"])
else: else:
error_message = f"Unknown function: {function_name}" error_message = f"Unknown function: {function_name}"
self.logger.error(error_message) self.logger.error(error_message)
@@ -1068,4 +1096,44 @@ class GitHubTool(BaseTool):
"status_code": response.status_code, "status_code": response.status_code,
"message": error_message, "message": error_message,
"response": response.text "response": response.text
} }
@metrics.measure
def _list_project_boards(self):
self.logger.info("Fetching project boards...")
url = f"{self.base_url}/repos/{self.repo}/projects"
response = requests.get(url, headers=self.headers)
if response.status_code == 200:
boards = response.json()
self.logger.info(f"Successfully fetched {len(boards)} project boards.")
return boards
else:
error_message = f"Error fetching project boards: {response.status_code}"
self.logger.error(error_message)
return error_message
@metrics.measure
def _view_project_board_items(self, project_id):
self.logger.info(f"Fetching items for project board ID: {project_id}...")
columns_url = f"{self.base_url}/projects/{project_id}/columns"
columns_response = requests.get(columns_url, headers=self.headers)
if columns_response.status_code == 200:
columns = columns_response.json()
items = []
for column in columns:
column_id = column["id"]
column_name = column["name"]
cards_url = f"{self.base_url}/projects/columns/{column_id}/cards"
cards_response = requests.get(cards_url, headers=self.headers)
if cards_response.status_code == 200:
cards = cards_response.json()
items.append({"column": column_name, "cards": cards})
else:
self.logger.error(f"Error fetching cards for column {column_id}: {cards_response.status_code}")
items.append({"column": column_name, "cards": "Error fetching cards"})
self.logger.info(f"Successfully fetched items for project board ID: {project_id}.")
return items
else:
error_message = f"Error fetching columns for project board: {columns_response.status_code}"
self.logger.error(error_message)
return error_message