diff --git a/libs/arcade-cli/arcade_cli/main.py b/libs/arcade-cli/arcade_cli/main.py index 54246509..1d7ce27e 100644 --- a/libs/arcade-cli/arcade_cli/main.py +++ b/libs/arcade-cli/arcade_cli/main.py @@ -18,7 +18,6 @@ from rich.text import Text from tqdm import tqdm import arcade_cli.worker as worker -from arcade_cli import toolkit_docs from arcade_cli.authn import LocalAuthCallbackServer, check_existing_login from arcade_cli.constants import ( CREDENTIALS_FILE_PATH, @@ -33,6 +32,7 @@ from arcade_cli.display import ( display_tool_messages, ) from arcade_cli.show import show_logic +from arcade_cli.toolkit_docs import generate_toolkit_docs from arcade_cli.utils import ( OrderCommands, compute_base_url, @@ -782,8 +782,15 @@ def dashboard( handle_cli_error("Failed to open dashboard", e, debug) -@cli.command(help="Generate Toolkit documentation", rich_help_panel="Tool Development") -def generate_toolkit_docs( +@cli.command( + help=( + "Generate documentation for a toolkit. " + "Note: make sure to have the toolkit installed in your current Python environment " + "before running this command." + ), + rich_help_panel="Tool Development", +) +def docs( toolkit_name: str = typer.Option( ..., "--toolkit-name", "-n", help="The name of the toolkit to generate documentation for." ), @@ -791,13 +798,16 @@ def generate_toolkit_docs( ..., "--toolkit-dir", "-t", - help="The path to the toolkit root directory.", + help=( + "The path to the toolkit root directory (where the toolkit code is implemented). " + "Works with relative and absolute paths." + ), ), docs_dir: str = typer.Option( ..., "--docs-dir", "-r", - help="The path to the documentation root directory.", + help="The path to the root of the Arcade docs repository. Works with relative and absolute paths.", ), docs_section: str = typer.Option( "", @@ -805,6 +815,105 @@ def generate_toolkit_docs( "-s", help=( "The section of the docs to generate documentation for. E.g. 'productivity', 'sales'. " + "This should be the name of the folder in /pages/toolkits. " + "Defaults to an empty string (generate the docs in the root of /pages/toolkits)" + ), + ), + openai_model: str = typer.Option( + "gpt-4o-mini", + "--openai-model", + "-m", + help=( + "A few parts of the documentation are generated using OpenAI API. " + "This argument controls which OpenAI model to use. " + "E.g. 'gpt-4o', 'gpt-4o-mini'." + ), + show_default=True, + ), + openai_api_key: str = typer.Option( + None, + "--openai-api-key", + "-o", + help="The OpenAI API key. If not provided, will get it from the `OPENAI_API_KEY` env var.", + ), + skip_tool_call_examples: bool = typer.Option( + False, + "--skip-tool-call-examples", + "-se", + help="Whether to skip generating tool call examples in Python and Javascript.", + show_default=True, + ), + debug: bool = typer.Option(False, "--debug", "-d", help="Show debug information"), +) -> None: + try: + success = generate_toolkit_docs( + console=console, + toolkit_name=toolkit_name, + toolkit_dir=toolkit_dir, + docs_dir=docs_dir, + docs_section=docs_section, + openai_model=openai_model, + openai_api_key=openai_api_key, + tool_call_examples=not skip_tool_call_examples, + debug=debug, + ) + except Exception as error: + handle_cli_error( + message=f"Failed to generate documentation for '{toolkit_name}' in '{docs_dir}'", + error=error, + debug=debug, + ) + success = False + + if success: + console.print( + f"Generated documentation for '{toolkit_name}' in '{docs_dir}'", + style="bold green", + ) + else: + console.print( + f"Failed to generate documentation for '{toolkit_name}' in '{docs_dir}'", + style="bold red", + ) + + +@cli.command( + name="generate-toolkit-docs", + help=( + "Generate documentation for a toolkit. " + "Note: make sure to have the toolkit installed in your current Python environment " + "before running this command. " + "Obs.: this command is here for backwards compatibility, use `arcade docs` instead." + ), + rich_help_panel="Tool Development", + hidden=True, +) +def generate_toolkit_docs_command( + toolkit_name: str = typer.Option( + ..., "--toolkit-name", "-n", help="The name of the toolkit to generate documentation for." + ), + toolkit_dir: str = typer.Option( + ..., + "--toolkit-dir", + "-t", + help=( + "The path to the toolkit root directory (where the toolkit code is implemented). " + "Works with relative and absolute paths." + ), + ), + docs_dir: str = typer.Option( + ..., + "--docs-dir", + "-r", + help="The path to the root of the Arcade docs repository. Works with relative and absolute paths.", + ), + docs_section: str = typer.Option( + "", + "--docs-section", + "-s", + help=( + "The section of the docs to generate documentation for. E.g. 'productivity', 'sales'. " + "This should be the name of the folder in /pages/toolkits. " "Defaults to an empty string (generate the docs in the root of /pages/toolkits)" ), ), @@ -826,31 +935,26 @@ def generate_toolkit_docs( help="The OpenAI API key. If not provided, will get it from the `OPENAI_API_KEY` env var.", ), tool_call_examples: bool = typer.Option( - False, + True, "--tool-call-examples", "-e", - help="Whether to generate tool call examples", + help="Whether to generate tool call examples in Python and Javascript.", show_default=True, ), debug: bool = typer.Option(False, "--debug", "-d", help="Show debug information"), ) -> None: - toolkit_docs.generate_toolkit_docs( - console=console, + skip_tool_call_examples = not tool_call_examples + docs( toolkit_name=toolkit_name, toolkit_dir=toolkit_dir, docs_dir=docs_dir, docs_section=docs_section, openai_model=openai_model, openai_api_key=openai_api_key, - tool_call_examples=tool_call_examples, + skip_tool_call_examples=skip_tool_call_examples, debug=debug, ) - console.print( - f"Generated documentation for '{toolkit_name}' in '{docs_dir}'", - style="bold green", - ) - @cli.callback() def main_callback( diff --git a/libs/arcade-cli/arcade_cli/toolkit_docs/__init__.py b/libs/arcade-cli/arcade_cli/toolkit_docs/__init__.py index 2457930d..1b6bd71f 100644 --- a/libs/arcade-cli/arcade_cli/toolkit_docs/__init__.py +++ b/libs/arcade-cli/arcade_cli/toolkit_docs/__init__.py @@ -31,7 +31,7 @@ def generate_toolkit_docs( openai_api_key: str | None = None, tool_call_examples: bool = True, debug: bool = False, -) -> None: +) -> bool: openai.api_key = resolve_api_key(openai_api_key, "OPENAI_API_KEY") if not openai.api_key: @@ -39,7 +39,7 @@ def generate_toolkit_docs( "❌ Provide --openai-api-key argument or set the OPENAI_API_KEY environment variable", style="red", ) - return + return False print_debug = partial(print_debug_func, debug, console) @@ -85,3 +85,5 @@ def generate_toolkit_docs( write_file(example_path, example) print_debug(f"Done generating docs for {toolkit_name}") + + return True diff --git a/libs/arcade-cli/arcade_cli/toolkit_docs/utils.py b/libs/arcade-cli/arcade_cli/toolkit_docs/utils.py index 4e9cb910..a34b972d 100644 --- a/libs/arcade-cli/arcade_cli/toolkit_docs/utils.py +++ b/libs/arcade-cli/arcade_cli/toolkit_docs/utils.py @@ -74,7 +74,10 @@ def get_list_of_tools(toolkit_name: str) -> list[ToolDefinition]: tools.append(tool) if not tools: - raise ValueError(f"Tools not found for toolkit {toolkit_name}") + raise ValueError( + f"Tools not found for the toolkit '{toolkit_name}'. Make sure to have the toolkit " + "installed in your current Python environment." + ) return tools