""" Functions Handler - manages Appwrite serverless functions Phase I.4: 14 tools - Functions: 5 (list, get, create, update, delete) - Deployments: 5 (list, get, create, delete, activate) - Executions: 4 (list, get, create, delete) """ import json from typing import Any from plugins.appwrite.client import AppwriteClient def get_tool_specifications() -> list[dict[str, Any]]: """Return tool specifications for ToolGenerator (14 tools)""" return [ # ===================== # FUNCTIONS (5) # ===================== { "name": "list_functions", "method_name": "list_functions", "description": "List all serverless functions in the project.", "schema": { "type": "object", "properties": { "queries": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Query strings for filtering", }, "search": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Search term to filter functions", }, }, "required": [], }, "scope": "read", }, { "name": "get_function", "method_name": "get_function", "description": "Get function details including deployment status and configuration.", "schema": { "type": "object", "properties": {"function_id": {"type": "string", "description": "Function ID"}}, "required": ["function_id"], }, "scope": "read", }, { "name": "create_function", "method_name": "create_function", "description": "Create a new serverless function.", "schema": { "type": "object", "properties": { "function_id": { "type": "string", "description": "Unique function ID. Use 'unique()' for auto-generation", }, "name": {"type": "string", "description": "Function name"}, "runtime": { "type": "string", "description": "Runtime (e.g., 'node-18.0', 'python-3.9', 'php-8.0', 'ruby-3.0')", "examples": [ "node-18.0", "node-20.0", "python-3.9", "python-3.11", "php-8.0", "php-8.2", "ruby-3.0", "go-1.21", "dart-3.0", "rust-1.70", ], }, "execute": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Execution permissions (e.g., ['any', 'users'])", }, "events": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Events to trigger function (e.g., ['databases.*.collections.*.documents.*.create'])", }, "schedule": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Cron schedule (e.g., '0 * * * *' for every hour)", }, "timeout": { "type": "integer", "description": "Execution timeout in seconds", "default": 15, "minimum": 1, "maximum": 900, }, "enabled": { "type": "boolean", "description": "Enable function", "default": True, }, "logging": { "type": "boolean", "description": "Enable logging", "default": True, }, "entrypoint": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Entrypoint file (e.g., 'src/main.js')", }, "commands": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Build commands", }, }, "required": ["function_id", "name", "runtime"], }, "scope": "write", }, { "name": "update_function", "method_name": "update_function", "description": "Update function configuration.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "name": {"type": "string", "description": "Function name"}, "runtime": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "New runtime", }, "execute": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "New execution permissions", }, "events": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "New trigger events", }, "schedule": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "New cron schedule", }, "timeout": { "anyOf": [{"type": "integer"}, {"type": "null"}], "description": "New timeout", }, "enabled": { "anyOf": [{"type": "boolean"}, {"type": "null"}], "description": "Enable/disable function", }, }, "required": ["function_id", "name"], }, "scope": "write", }, { "name": "delete_function", "method_name": "delete_function", "description": "Delete a function and all its deployments.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID to delete"} }, "required": ["function_id"], }, "scope": "admin", }, # ===================== # DEPLOYMENTS (5) # ===================== { "name": "list_deployments", "method_name": "list_deployments", "description": "List all deployments of a function.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "queries": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Query strings for filtering", }, "search": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Search term", }, }, "required": ["function_id"], }, "scope": "read", }, { "name": "get_deployment", "method_name": "get_deployment", "description": "Get deployment details including build status and logs.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "deployment_id": {"type": "string", "description": "Deployment ID"}, }, "required": ["function_id", "deployment_id"], }, "scope": "read", }, { "name": "delete_deployment", "method_name": "delete_deployment", "description": "Delete a deployment.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "deployment_id": {"type": "string", "description": "Deployment ID to delete"}, }, "required": ["function_id", "deployment_id"], }, "scope": "write", }, { "name": "activate_deployment", "method_name": "activate_deployment", "description": "Activate a deployment (set as the active version for the function).", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "deployment_id": {"type": "string", "description": "Deployment ID to activate"}, }, "required": ["function_id", "deployment_id"], }, "scope": "write", }, { "name": "get_active_deployment", "method_name": "get_active_deployment", "description": "Get the currently active deployment for a function.", "schema": { "type": "object", "properties": {"function_id": {"type": "string", "description": "Function ID"}}, "required": ["function_id"], }, "scope": "read", }, # ===================== # EXECUTIONS (4) # ===================== { "name": "list_executions", "method_name": "list_executions", "description": "List execution history for a function.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "queries": { "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Query strings for filtering", }, "search": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Search term", }, }, "required": ["function_id"], }, "scope": "read", }, { "name": "get_execution", "method_name": "get_execution", "description": "Get execution details including response, logs, and timing.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "execution_id": {"type": "string", "description": "Execution ID"}, }, "required": ["function_id", "execution_id"], }, "scope": "read", }, { "name": "execute_function", "method_name": "execute_function", "description": "Execute a function immediately.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "body": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Request body (JSON string)", }, "async_execution": { "type": "boolean", "description": "Run asynchronously (don't wait for response)", "default": False, }, "path": { "anyOf": [{"type": "string"}, {"type": "null"}], "description": "Custom execution path", }, "method": { "type": "string", "enum": ["GET", "POST", "PUT", "PATCH", "DELETE"], "description": "HTTP method", "default": "POST", }, "headers": { "anyOf": [{"type": "object"}, {"type": "null"}], "description": "Custom headers", }, }, "required": ["function_id"], }, "scope": "write", }, { "name": "delete_execution", "method_name": "delete_execution", "description": "Delete an execution log entry.", "schema": { "type": "object", "properties": { "function_id": {"type": "string", "description": "Function ID"}, "execution_id": {"type": "string", "description": "Execution ID to delete"}, }, "required": ["function_id", "execution_id"], }, "scope": "write", }, ] # ===================== # HANDLER FUNCTIONS # ===================== async def list_functions( client: AppwriteClient, queries: list[str] | None = None, search: str | None = None ) -> str: """List all functions.""" try: result = await client.list_functions(queries=queries, search=search) functions = result.get("functions", []) response = { "success": True, "total": result.get("total", len(functions)), "functions": functions, } return json.dumps(response, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def get_function(client: AppwriteClient, function_id: str) -> str: """Get function by ID.""" try: result = await client.get_function(function_id) return json.dumps({"success": True, "function": result}, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def create_function( client: AppwriteClient, function_id: str, name: str, runtime: str, execute: list[str] | None = None, events: list[str] | None = None, schedule: str | None = None, timeout: int = 15, enabled: bool = True, logging: bool = True, entrypoint: str | None = None, commands: str | None = None, ) -> str: """Create a new function.""" try: result = await client.create_function( function_id=function_id, name=name, runtime=runtime, execute=execute, events=events, schedule=schedule, timeout=timeout, enabled=enabled, logging=logging, entrypoint=entrypoint, commands=commands, ) return json.dumps( { "success": True, "message": f"Function '{name}' created successfully", "function": result, }, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def update_function( client: AppwriteClient, function_id: str, name: str, runtime: str | None = None, execute: list[str] | None = None, events: list[str] | None = None, schedule: str | None = None, timeout: int | None = None, enabled: bool | None = None, ) -> str: """Update function.""" try: result = await client.update_function( function_id=function_id, name=name, runtime=runtime, execute=execute, events=events, schedule=schedule, timeout=timeout, enabled=enabled, ) return json.dumps( {"success": True, "message": "Function updated successfully", "function": result}, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def delete_function(client: AppwriteClient, function_id: str) -> str: """Delete function.""" try: await client.delete_function(function_id) return json.dumps( {"success": True, "message": f"Function '{function_id}' deleted successfully"}, indent=2 ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def list_deployments( client: AppwriteClient, function_id: str, queries: list[str] | None = None, search: str | None = None, ) -> str: """List function deployments.""" try: result = await client.list_deployments( function_id=function_id, queries=queries, search=search ) deployments = result.get("deployments", []) response = { "success": True, "function_id": function_id, "total": result.get("total", len(deployments)), "deployments": deployments, } return json.dumps(response, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def get_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str: """Get deployment by ID.""" try: result = await client.get_deployment(function_id, deployment_id) return json.dumps({"success": True, "deployment": result}, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def delete_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str: """Delete deployment.""" try: await client.delete_deployment(function_id, deployment_id) return json.dumps( {"success": True, "message": f"Deployment '{deployment_id}' deleted successfully"}, indent=2, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def activate_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str: """Activate deployment.""" try: result = await client.update_deployment(function_id, deployment_id) return json.dumps( { "success": True, "message": f"Deployment '{deployment_id}' activated successfully", "deployment": result, }, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def get_active_deployment(client: AppwriteClient, function_id: str) -> str: """Get active deployment for function.""" try: func = await client.get_function(function_id) deployment_id = func.get("deployment") if not deployment_id: return json.dumps( { "success": True, "message": "No active deployment", "function_id": function_id, "active_deployment": None, }, indent=2, ) deployment = await client.get_deployment(function_id, deployment_id) return json.dumps( {"success": True, "function_id": function_id, "active_deployment": deployment}, indent=2, ensure_ascii=False, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def list_executions( client: AppwriteClient, function_id: str, queries: list[str] | None = None, search: str | None = None, ) -> str: """List function executions.""" try: result = await client.list_executions( function_id=function_id, queries=queries, search=search ) executions = result.get("executions", []) response = { "success": True, "function_id": function_id, "total": result.get("total", len(executions)), "executions": executions, } return json.dumps(response, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def get_execution(client: AppwriteClient, function_id: str, execution_id: str) -> str: """Get execution by ID.""" try: result = await client.get_execution(function_id, execution_id) return json.dumps({"success": True, "execution": result}, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def execute_function( client: AppwriteClient, function_id: str, body: str | None = None, async_execution: bool = False, path: str | None = None, method: str = "POST", headers: dict[str, str] | None = None, ) -> str: """Execute function.""" try: result = await client.create_execution( function_id=function_id, body=body, async_execution=async_execution, path=path, method=method, headers=headers, ) response = { "success": True, "execution_id": result.get("$id"), "status": result.get("status"), "status_code": result.get("responseStatusCode"), "duration": result.get("duration"), "response_body": result.get("responseBody"), "logs": result.get("logs"), "errors": result.get("errors"), } if async_execution: response["message"] = "Function execution started asynchronously" else: response["message"] = "Function executed successfully" return json.dumps(response, indent=2, ensure_ascii=False) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2) async def delete_execution(client: AppwriteClient, function_id: str, execution_id: str) -> str: """Delete execution.""" try: await client.delete_execution(function_id, execution_id) return json.dumps( {"success": True, "message": f"Execution '{execution_id}' deleted successfully"}, indent=2, ) except Exception as e: return json.dumps({"success": False, "error": str(e)}, indent=2)