Add CLI commands (init, run, test, prompt)
This commit is contained in:
139
src/promptforge/cli/commands/prompt.py
Normal file
139
src/promptforge/cli/commands/prompt.py
Normal file
@@ -0,0 +1,139 @@
|
||||
import sys
|
||||
import click
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from promptforge.core.prompt import Prompt, PromptVariable, VariableType
|
||||
from promptforge.core.template import TemplateEngine
|
||||
from promptforge.core.git_manager import GitManager
|
||||
|
||||
|
||||
@click.group()
|
||||
def prompt():
|
||||
"""Manage prompts."""
|
||||
pass
|
||||
|
||||
|
||||
@prompt.command("create")
|
||||
@click.argument("name")
|
||||
@click.option("--content", "-c", help="Prompt content")
|
||||
@click.option("--description", "-d", help="Prompt description")
|
||||
@click.option("--provider", "-p", help="Default provider")
|
||||
@click.option("--tag", "-t", multiple=True, help="Tags for the prompt")
|
||||
@click.pass_obj
|
||||
def create(ctx, name: str, content: str, description: str, provider: str, tag: tuple):
|
||||
"""Create a new prompt."""
|
||||
prompts_dir = ctx["prompts_dir"]
|
||||
|
||||
if not content:
|
||||
click.echo("Enter prompt content (end with Ctrl+D on new line):")
|
||||
content = click.get_text_stream("stdin").read()
|
||||
|
||||
variables = []
|
||||
if "{" in content and "}" in content:
|
||||
template_engine = TemplateEngine()
|
||||
var_names = template_engine.get_variables(content)
|
||||
for var_name in var_names:
|
||||
var_type = click.prompt(
|
||||
f"Variable '{var_name}' type",
|
||||
type=click.Choice(["string", "integer", "float", "boolean", "choice"]),
|
||||
default="string",
|
||||
)
|
||||
is_required = click.confirm(f"Is '{var_name}' required?", default=True)
|
||||
default_val = None
|
||||
if not is_required:
|
||||
default_val = click.prompt(f"Default value for '{var_name}'", default="")
|
||||
variables.append(PromptVariable(
|
||||
name=var_name,
|
||||
type=VariableType(var_type),
|
||||
required=is_required,
|
||||
default=default_val,
|
||||
))
|
||||
|
||||
prompt = Prompt(
|
||||
name=name,
|
||||
description=description,
|
||||
content=content,
|
||||
provider=provider,
|
||||
tags=list(tag),
|
||||
variables=variables,
|
||||
)
|
||||
|
||||
filepath = prompt.save(prompts_dir)
|
||||
click.echo(f"Created prompt: {filepath}")
|
||||
|
||||
git_manager = GitManager(prompts_dir)
|
||||
if (prompts_dir / ".git").exists():
|
||||
try:
|
||||
git_manager.commit(f"Add prompt: {name}")
|
||||
click.echo("Committed to git")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@prompt.command("list")
|
||||
@click.pass_obj
|
||||
def list_prompts(ctx):
|
||||
"""List all prompts."""
|
||||
prompts_dir = ctx["prompts_dir"]
|
||||
prompts = Prompt.list(prompts_dir)
|
||||
|
||||
if not prompts:
|
||||
click.echo("No prompts found. Create one with 'pf prompt create'")
|
||||
return
|
||||
|
||||
for prompt in prompts:
|
||||
status = "✓" if prompt.provider else "○"
|
||||
click.echo(f"{status} {prompt.name} (v{prompt.version})")
|
||||
if prompt.description:
|
||||
click.echo(f" {prompt.description}")
|
||||
|
||||
|
||||
@prompt.command("show")
|
||||
@click.argument("name")
|
||||
@click.pass_obj
|
||||
def show(ctx, name: str):
|
||||
"""Show prompt details."""
|
||||
prompts_dir = ctx["prompts_dir"]
|
||||
prompts = Prompt.list(prompts_dir)
|
||||
|
||||
prompt = next((p for p in prompts if p.name == name), None)
|
||||
if not prompt:
|
||||
click.echo(f"Prompt '{name}' not found", err=True)
|
||||
raise click.Abort()
|
||||
|
||||
click.echo(f"Name: {prompt.name}")
|
||||
click.echo(f"Version: {prompt.version}")
|
||||
if prompt.description:
|
||||
click.echo(f"Description: {prompt.description}")
|
||||
if prompt.provider:
|
||||
click.echo(f"Provider: {prompt.provider}")
|
||||
if prompt.tags:
|
||||
click.echo(f"Tags: {', '.join(prompt.tags)}")
|
||||
click.echo(f"\n--- Content ---")
|
||||
click.echo(prompt.content)
|
||||
|
||||
|
||||
@prompt.command("delete")
|
||||
@click.argument("name")
|
||||
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation")
|
||||
@click.pass_obj
|
||||
def delete(ctx, name: str, yes: bool):
|
||||
"""Delete a prompt."""
|
||||
prompts_dir = ctx["prompts_dir"]
|
||||
prompts = Prompt.list(prompts_dir)
|
||||
|
||||
prompt = next((p for p in prompts if p.name == name), None)
|
||||
if not prompt:
|
||||
click.echo(f"Prompt '{name}' not found", err=True)
|
||||
raise click.Abort()
|
||||
|
||||
if not yes and not click.confirm(f"Delete prompt '{name}'?"):
|
||||
raise click.Abort()
|
||||
|
||||
filepath = prompts_dir / f"{name.lower().replace(' ', '_').replace('/', '_')}.yaml"
|
||||
if filepath.exists():
|
||||
filepath.unlink()
|
||||
click.echo(f"Deleted prompt: {name}")
|
||||
else:
|
||||
click.echo(f"Prompt file not found", err=True)
|
||||
raise click.Abort()
|
||||
Reference in New Issue
Block a user