From ba8c3d319758c103fb89aad91ce8742b89ba2f01 Mon Sep 17 00:00:00 2001 From: Renato Byrro Date: Mon, 28 Jul 2025 15:46:58 -0300 Subject: [PATCH] Rename auto-docs command to simply 'docs' and some other small improvements (#518) Renames the `arcade generate-toolkit-docs` command to `arcade docs`. The `arcade generate-toolkit-docs` command is preserved for backwards compatibility, but it's now hidden. Also some minor improvements to CLI help strings and better error handling. Better error description when the toolkit is not installed locally (also now mentioning this requirement in the command help). --- libs/arcade-cli/arcade_cli/main.py | 134 ++++++++++++++++-- .../arcade_cli/toolkit_docs/__init__.py | 6 +- .../arcade_cli/toolkit_docs/utils.py | 5 +- 3 files changed, 127 insertions(+), 18 deletions(-) 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