Claude-skill-registry-data main

Imported skill main from langchain

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry-data
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/main" ~/.claude/skills/majiayu000-claude-skill-registry-data-main-5e238b && rm -rf "$T"
manifest: data/main/SKILL.md
source content

"""Main entry point and CLI loop for deepagents."""

ruff: noqa: T201, E402, BLE001, PLR0912, PLR0915

Suppress deprecation warnings from langchain_core (e.g., Pydantic V1 on Python 3.14+)

ruff: noqa: E402

import warnings

warnings.filterwarnings("ignore", module="langchain_core._api.deprecation")

import argparse import asyncio import contextlib import os import sys import warnings from pathlib import Path

Suppress Pydantic v1 compatibility warnings from langchain on Python 3.14+

warnings.filterwarnings("ignore", message=".Pydantic V1.", category=UserWarning)

from rich.text import Text

from deepagents_cli._version import version

Now safe to import agent (which imports LangChain modules)

from deepagents_cli.agent import create_cli_agent, list_agents, reset_agent

CRITICAL: Import config FIRST to set LANGSMITH_PROJECT before LangChain loads

from deepagents_cli.config import ( console, create_model, settings, ) from deepagents_cli.integrations.sandbox_factory import create_sandbox from deepagents_cli.sessions import ( delete_thread_command, generate_thread_id, get_checkpointer, get_most_recent, get_thread_agent, list_threads_command, thread_exists, ) from deepagents_cli.skills import execute_skills_command, setup_skills_parser from deepagents_cli.tools import fetch_url, http_request, web_search from deepagents_cli.ui import show_help

def check_cli_dependencies() -> None: """Check if CLI optional dependencies are installed.""" missing = []

try:
    import requests  # noqa: F401
except ImportError:
    missing.append("requests")

try:
    import dotenv  # noqa: F401
except ImportError:
    missing.append("python-dotenv")

try:
    import tavily  # noqa: F401
except ImportError:
    missing.append("tavily-python")

try:
    import textual  # noqa: F401
except ImportError:
    missing.append("textual")

if missing:
    print("\n❌ Missing required CLI dependencies!")
    print("\nThe following packages are required to use the deepagents CLI:")
    for pkg in missing:
        print(f"  - {pkg}")
    print("\nPlease install them with:")
    print("  pip install deepagents[cli]")
    print("\nOr install all dependencies:")
    print("  pip install 'deepagents[cli]'")
    sys.exit(1)

def parse_args() -> argparse.Namespace: """Parse command line arguments.""" parser = argparse.ArgumentParser( description="DeepAgents - AI Coding Assistant", formatter_class=argparse.RawDescriptionHelpFormatter, add_help=False, ) parser.add_argument( "--version", action="version", version=f"deepagents {version}", )

subparsers = parser.add_subparsers(dest="command", help="Command to run")

# List command
subparsers.add_parser("list", help="List all available agents")

# Help command
subparsers.add_parser("help", help="Show help information")

# Reset command
reset_parser = subparsers.add_parser("reset", help="Reset an agent")
reset_parser.add_argument("--agent", required=True, help="Name of agent to reset")
reset_parser.add_argument(
    "--target", dest="source_agent", help="Copy prompt from another agent"
)

# Skills command - setup delegated to skills module
setup_skills_parser(subparsers)

# Threads command
threads_parser = subparsers.add_parser("threads", help="Manage conversation threads")
threads_sub = threads_parser.add_subparsers(dest="threads_command")

# threads list
threads_list = threads_sub.add_parser("list", help="List threads")
threads_list.add_argument(
    "--agent", default=None, help="Filter by agent name (default: show all)"
)
threads_list.add_argument("--limit", type=int, default=20, help="Max threads (default: 20)")

# threads delete
threads_delete = threads_sub.add_parser("delete", help="Delete a thread")
threads_delete.add_argument("thread_id", help="Thread ID to delete")

# Default interactive mode
parser.add_argument(
    "--agent",
    default="agent",
    help="Agent identifier for separate memory stores (default: agent).",
)

# Thread resume argument - matches PR #638: -r for most recent, -r <ID> for specific
parser.add_argument(
    "-r",
    "--resume",
    dest="resume_thread",
    nargs="?",
    const="__MOST_RECENT__",
    default=None,
    help="Resume thread: -r for most recent, -r <ID> for specific thread",
)

# Initial prompt - auto-submit when session starts
parser.add_argument(
    "-m",
    "--message",
    dest="initial_prompt",
    help="Initial prompt to auto-submit when session starts",
)

parser.add_argument(
    "--model",
    help="Model to use (e.g., claude-sonnet-4-5-20250929, gpt-5-mini). "
    "Provider is auto-detected from model name.",
)
parser.add_argument(
    "--auto-approve",
    action="store_true",
    help="Auto-approve tool usage without prompting (disables human-in-the-loop)",
)
parser.add_argument(
    "--sandbox",
    choices=["none", "modal", "daytona", "runloop"],
    default="none",
    help="Remote sandbox for code execution (default: none - local only)",
)
parser.add_argument(
    "--sandbox-id",
    help="Existing sandbox ID to reuse (skips creation and cleanup)",
)
parser.add_argument(
    "--sandbox-setup",
    help="Path to setup script to run in sandbox after creation",
)
return parser.parse_args()

async def run_textual_cli_async( assistant_id: str, *, auto_approve: bool = False, sandbox_type: str = "none", sandbox_id: str | None = None, model_name: str | None = None, thread_id: str | None = None, is_resumed: bool = False, initial_prompt: str | None = None, ) -> None: """Run the Textual CLI interface (async version).

Args:
    assistant_id: Agent identifier for memory storage
    auto_approve: Whether to auto-approve tool usage
    sandbox_type: Type of sandbox ("none", "modal", "runloop", "daytona")
    sandbox_id: Optional existing sandbox ID to reuse
    model_name: Optional model name to use
    thread_id: Thread ID to use (new or resumed)
    is_resumed: Whether this is a resumed session
    initial_prompt: Optional prompt to auto-submit when session starts
"""
from deepagents_cli.app import run_textual_app

model = create_model(model_name)

# Show thread info
if is_resumed:
    console.print(f"[green]Resuming thread:[/green] {thread_id}")
else:
    console.print(f"[dim]Thread: {thread_id}[/dim]")

# Use async context manager for checkpointer
async with get_checkpointer() as checkpointer:
    # Create agent with conditional tools
    tools = [http_request, fetch_url]
    if settings.has_tavily:
        tools.append(web_search)

    # Handle sandbox mode
    sandbox_backend = None
    sandbox_cm = None

    if sandbox_type != "none":
        try:
            # Create sandbox context manager but keep it open
            sandbox_cm = create_sandbox(sandbox_type, sandbox_id=sandbox_id)
            sandbox_backend = sandbox_cm.__enter__()
        except (ImportError, ValueError, RuntimeError, NotImplementedError) as e:
            console.print()
            console.print("[red]❌ Sandbox creation failed[/red]")
            console.print(Text(str(e), style="dim"))
            sys.exit(1)

    try:
        agent, composite_backend = create_cli_agent(
            model=model,
            assistant_id=assistant_id,
            tools=tools,
            sandbox=sandbox_backend,
            sandbox_type=sandbox_type if sandbox_type != "none" else None,
            auto_approve=auto_approve,
            checkpointer=checkpointer,
        )

        # Run Textual app
        await run_textual_app(
            agent=agent,
            assistant_id=assistant_id,
            backend=composite_backend,
            auto_approve=auto_approve,
            cwd=Path.cwd(),
            thread_id=thread_id,
            initial_prompt=initial_prompt,
        )
    except Exception as e:
        error_text = Text("❌ Failed to create agent: ", style="red")
        error_text.append(str(e))
        console.print(error_text)
        sys.exit(1)
    finally:
        # Clean up sandbox if we created one
        if sandbox_cm is not None:
            with contextlib.suppress(Exception):
                sandbox_cm.__exit__(None, None, None)

def cli_main() -> None: """Entry point for console script.""" # Fix for gRPC fork issue on macOS # https://github.com/grpc/grpc/issues/37642 if sys.platform == "darwin": os.environ["GRPC_ENABLE_FORK_SUPPORT"] = "0"

# Note: LANGSMITH_PROJECT is already overridden in config.py (before LangChain imports)
# This ensures agent traces → DEEPAGENTS_LANGSMITH_PROJECT
# Shell commands → user's original LANGSMITH_PROJECT (via ShellMiddleware env)

# Check dependencies first
check_cli_dependencies()

try:
    args = parse_args()

    if args.command == "help":
        show_help()
    elif args.command == "list":
        list_agents()
    elif args.command == "reset":
        reset_agent(args.agent, args.source_agent)
    elif args.command == "skills":
        execute_skills_command(args)
    elif args.command == "threads":
        if args.threads_command == "list":
            asyncio.run(
                list_threads_command(
                    agent_name=getattr(args, "agent", None),
                    limit=getattr(args, "limit", 20),
                )
            )
        elif args.threads_command == "delete":
            asyncio.run(delete_thread_command(args.thread_id))
        else:
            console.print("[yellow]Usage: deepagents threads <list|delete>[/yellow]")
    else:
        # Interactive mode - handle thread resume
        thread_id = None
        is_resumed = False

        if args.resume_thread == "__MOST_RECENT__":
            # -r (no ID): Get most recent thread
            # If --agent specified, filter by that agent; otherwise get most recent overall
            agent_filter = args.agent if args.agent != "agent" else None
            thread_id = asyncio.run(get_most_recent(agent_filter))
            if thread_id:
                is_resumed = True
                agent_name = asyncio.run(get_thread_agent(thread_id))
                if agent_name:
                    args.agent = agent_name
            else:
                if agent_filter:
                    msg = Text("No previous thread for '", style="yellow")
                    msg.append(args.agent)
                    msg.append("', starting new.", style="yellow")
                else:
                    msg = Text("No previous threads, starting new.", style="yellow")
                console.print(msg)

        elif args.resume_thread:
            # -r <ID>: Resume specific thread
            if asyncio.run(thread_exists(args.resume_thread)):
                thread_id = args.resume_thread
                is_resumed = True
                if args.agent == "agent":
                    agent_name = asyncio.run(get_thread_agent(thread_id))
                    if agent_name:
                        args.agent = agent_name
            else:
                error_msg = Text("Thread '", style="red")
                error_msg.append(args.resume_thread)
                error_msg.append("' not found.", style="red")
                console.print(error_msg)
                console.print(
                    "[dim]Use 'deepagents threads list' to see available threads.[/dim]"
                )
                sys.exit(1)

        # Generate new thread ID if not resuming
        if thread_id is None:
            thread_id = generate_thread_id()

        # Run Textual CLI
        asyncio.run(
            run_textual_cli_async(
                assistant_id=args.agent,
                auto_approve=args.auto_approve,
                sandbox_type=args.sandbox,
                sandbox_id=args.sandbox_id,
                model_name=getattr(args, "model", None),
                thread_id=thread_id,
                is_resumed=is_resumed,
                initial_prompt=getattr(args, "initial_prompt", None),
            )
        )
except KeyboardInterrupt:
    # Clean exit on Ctrl+C - suppress ugly traceback
    console.print("\n\n[yellow]Interrupted[/yellow]")
    sys.exit(0)

if name == "main": cli_main()