""" Script to delete a specific tool from Upstash Redis. This connects directly to Upstash and removes the tool from all relevant Redis keys. """ import asyncio import redis.asyncio as redis import sys UPSTASH_URL = "rediss://default:AYVhAAIncDJmMjdkYzFiYmYyNTQ0NzY2YjZmMTRmOTZiNGMzMDliOXAyMzQxNDU@faithful-shrew-34145.upstash.io:6379" async def delete_tool(tool_name: str, user_id: str): """ Delete a tool from Upstash Redis. Args: tool_name: Name of the tool to delete user_id: User ID for namespacing """ # Connect to Upstash with TLS client = redis.from_url( UPSTASH_URL, decode_responses=True ) try: print(f"Connected to Upstash Redis") print(f"Deleting tool: {tool_name}") print(f"User ID: {user_id}") print("=" * 60) # Construct user-namespaced keys approved_tools_key = f"user:{user_id}:approved_tools" tool_projects_key = f"user:{user_id}:tool_projects" # Step 1: Get which project the tool belongs to project_id = await client.hget(tool_projects_key, tool_name) if project_id: print(f"\n1. Tool is in project: {project_id}") # Remove from project's tools set project_tools_key = f"user:{user_id}:project_tools:{project_id}" removed_from_set = await client.srem(project_tools_key, tool_name) print(f" Removed from {project_tools_key}: {removed_from_set > 0}") else: print(f"\n1. Tool not found in tool_projects mapping") # Step 2: Remove from tool_projects mapping removed_from_mapping = await client.hdel(tool_projects_key, tool_name) print(f"\n2. Removed from tool_projects mapping: {removed_from_mapping > 0}") # Step 3: Remove from approved_tools removed_from_approved = await client.hdel(approved_tools_key, tool_name) print(f"\n3. Removed from approved_tools: {removed_from_approved > 0}") # Step 4: Publish tools_changed notification notification_channel = f"user:{user_id}:tools_changed" await client.publish(notification_channel, "tools_updated") print(f"\n4. Published notification to {notification_channel}") print("\n" + "=" * 60) print(f"[OK] Tool '{tool_name}' successfully deleted!") print("=" * 60) # Verify deletion print("\nVerifying deletion:") still_in_approved = await client.hexists(approved_tools_key, tool_name) still_in_mapping = await client.hexists(tool_projects_key, tool_name) print(f" Still in approved_tools: {still_in_approved}") print(f" Still in tool_projects: {still_in_mapping}") if project_id: project_tools_key = f"user:{user_id}:project_tools:{project_id}" still_in_project = await client.sismember(project_tools_key, tool_name) print(f" Still in project set: {still_in_project}") except Exception as e: print(f"Error: {e}") raise finally: await client.aclose() async def main(): if len(sys.argv) < 3: print("Usage: python delete_tool_upstash.py ") print("Example: python delete_tool_upstash.py get_weather_forecast google_114049623254424116299") sys.exit(1) tool_name = sys.argv[1] user_id = sys.argv[2] print(f"Guardian Forge - Upstash Tool Deletion") print("=" * 60) confirm = input(f"Delete tool '{tool_name}' for user '{user_id}'? (yes/no): ") if confirm.lower() != "yes": print("Cancelled.") return await delete_tool(tool_name, user_id) if __name__ == "__main__": asyncio.run(main())