feat: Enhance tool management and documentation in Castle
- Introduced category tools support in the `castle create` command. - Added detailed guides for creating components in CLAUDE.md. - Implemented new API endpoints for listing and retrieving tool details. - Updated component and tool models to include additional metadata. - Improved error handling and response structures in service actions. - Enhanced documentation for component registry and web APIs.
This commit is contained in:
@@ -17,8 +17,10 @@ from castle_cli.manifest import (
|
||||
ProxySpec,
|
||||
RunPythonUvTool,
|
||||
SystemdSpec,
|
||||
ToolSpec,
|
||||
ToolType,
|
||||
)
|
||||
from castle_cli.templates.scaffold import scaffold_project
|
||||
from castle_cli.templates.scaffold import scaffold_category_tool, scaffold_project
|
||||
|
||||
|
||||
def next_available_port(config: object) -> int:
|
||||
@@ -41,11 +43,16 @@ def run_create(args: argparse.Namespace) -> int:
|
||||
config = load_config()
|
||||
name = args.name
|
||||
proj_type = args.type
|
||||
category = getattr(args, "category", None)
|
||||
|
||||
if name in config.components:
|
||||
print(f"Error: component '{name}' already exists in castle.yaml")
|
||||
return 1
|
||||
|
||||
# Category tool: add to existing category package
|
||||
if proj_type == "tool" and category:
|
||||
return _create_category_tool(config, name, args.description, category)
|
||||
|
||||
project_dir = config.root / name
|
||||
if project_dir.exists():
|
||||
print(f"Error: directory '{name}' already exists")
|
||||
@@ -95,6 +102,10 @@ def run_create(args: argparse.Namespace) -> int:
|
||||
manifest = ComponentManifest(
|
||||
id=name,
|
||||
description=args.description or f"A castle {proj_type}",
|
||||
tool=ToolSpec(
|
||||
tool_type=ToolType.PYTHON_STANDALONE,
|
||||
source=f"{name}/",
|
||||
),
|
||||
install=InstallSpec(path=PathInstallSpec(alias=name)),
|
||||
)
|
||||
else:
|
||||
@@ -119,3 +130,65 @@ def run_create(args: argparse.Namespace) -> int:
|
||||
print(f" castle test {name}")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def _create_category_tool(config: object, name: str, description: str | None, category: str) -> int:
|
||||
"""Create a tool inside an existing category package."""
|
||||
category_dir = config.root / "tools" / category
|
||||
if not category_dir.exists():
|
||||
print(f"Error: category directory 'tools/{category}/' does not exist")
|
||||
print(" Create the category package first, then add tools to it.")
|
||||
return 1
|
||||
|
||||
package_name = name.replace("-", "_")
|
||||
desc = description or "A castle tool"
|
||||
|
||||
# Scaffold the .py and .md files into the category package
|
||||
scaffold_category_tool(
|
||||
category_dir=category_dir,
|
||||
tool_name=name,
|
||||
package_name=package_name,
|
||||
category=category,
|
||||
description=desc,
|
||||
)
|
||||
|
||||
# Append entry point to existing pyproject.toml
|
||||
pyproject_path = category_dir / "pyproject.toml"
|
||||
if pyproject_path.exists():
|
||||
content = pyproject_path.read_text()
|
||||
entry_line = f'{name} = "{category}.{package_name}:main"'
|
||||
if entry_line not in content:
|
||||
# Find [project.scripts] section and append
|
||||
if "[project.scripts]" in content:
|
||||
content = content.replace(
|
||||
"[project.scripts]",
|
||||
f"[project.scripts]\n{entry_line}",
|
||||
)
|
||||
pyproject_path.write_text(content)
|
||||
print(f" Added entry point to tools/{category}/pyproject.toml")
|
||||
else:
|
||||
print(" Warning: could not find [project.scripts] in pyproject.toml")
|
||||
|
||||
# Register in castle.yaml
|
||||
manifest = ComponentManifest(
|
||||
id=name,
|
||||
description=desc,
|
||||
tool=ToolSpec(
|
||||
tool_type=ToolType.PYTHON_STANDALONE,
|
||||
category=category,
|
||||
source=f"tools/{category}/",
|
||||
),
|
||||
install=InstallSpec(path=PathInstallSpec(alias=name)),
|
||||
)
|
||||
config.components[name] = manifest
|
||||
save_config(config)
|
||||
|
||||
print(f"Created tool '{name}' in tools/{category}/")
|
||||
print(f" Source: tools/{category}/src/{category}/{package_name}.py")
|
||||
print(" Registered in castle.yaml")
|
||||
print("\nNext steps:")
|
||||
print(f" Edit tools/{category}/src/{category}/{package_name}.py")
|
||||
print(f" cd tools/{category} && uv sync")
|
||||
print(f" castle tool info {name}")
|
||||
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user