Skip to content

Interactive Wizard #235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6c0eea2
Terminal User Interface
tcdent Jan 23, 2025
5a91d7b
TUI progress.
tcdent Jan 24, 2025
a0a6308
Remove unused file.
tcdent Jan 24, 2025
81433cd
Full wizard workflow complete.
tcdent Jan 28, 2025
dd8ebd5
Cleanup directory structure. Typing fixes.
tcdent Jan 28, 2025
f709902
Ensure template writing is only called once.
tcdent Jan 28, 2025
7b5523b
Merge branch 'main' into wizard
tcdent Jan 28, 2025
f3196d3
Attempt at resolving RadioSelect state sync.
tcdent Jan 28, 2025
32fdc64
Background color. Ruff formatting.
tcdent Jan 29, 2025
d5819a8
Deprecate `init --wizard` command.
tcdent Jan 29, 2025
784bbd9
Merge branch 'main' into wizard
tcdent Jan 29, 2025
56a9a2c
Bugfixes.
tcdent Jan 29, 2025
7bed6f7
Fix form alignment. Allow skipping adding a tool. Additional validati…
tcdent Jan 29, 2025
7152353
Fix type checking.
tcdent Jan 29, 2025
4bb0b3e
Define human readable tool categories.
tcdent Jan 29, 2025
257b393
Move preferred models to new `providers` module with validation and h…
tcdent Jan 29, 2025
935d1d2
Wizard model selection bugfix. Added tests to ensure frameworks can a…
tcdent Jan 29, 2025
3d1cefa
Better colors.
tcdent Jan 30, 2025
30f0723
Log cleanup. Dependency cleanup.
tcdent Jan 30, 2025
09bdcac
Merge branch 'main' into wizard
tcdent Feb 6, 2025
132c877
Live resize. Pull frameworks info from `frameworks` module.
tcdent Feb 6, 2025
67dc514
Allow adding more tools to an agent.
tcdent Feb 6, 2025
7dc0e58
Fix bug when selecting last element in a scrollable list.
tcdent Feb 6, 2025
b37e483
Fix centering of logo.
tcdent Feb 6, 2025
c11cb59
Renders ad 80x24
tcdent Feb 6, 2025
4120070
Ignore type.
tcdent Feb 6, 2025
f3ba4fe
Update llms.txt
actions-user Feb 7, 2025
d3db89e
Undraw previous star instead of clearing grid to prevent flicker.
tcdent Feb 10, 2025
16f0fd5
Merge branch 'main' into wizard
tcdent Feb 10, 2025
81e1149
Standardize categories for new tools.
tcdent Feb 10, 2025
8531d46
Placeholder help text in wizard fields.
tcdent Feb 10, 2025
fa4f7ca
Docstrings for TUI.
tcdent Feb 10, 2025
4cc52c8
wizard smile
bboynton97 Feb 10, 2025
d2b063f
Merge branch 'wizard' of github.com:tcdent/AgentStack into wizard
bboynton97 Feb 10, 2025
a3e6642
fix proj_template import
bboynton97 Feb 13, 2025
d1e8f6a
16 color support.
tcdent Feb 14, 2025
d411d1e
Placeholder help text in wizard fields.
tcdent Feb 10, 2025
2fcbf23
Docstrings for TUI.
tcdent Feb 10, 2025
87df3dd
Restore variable.
tcdent Feb 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions agentstack/_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
TOOLS_CONFIG_FILENAME: str = 'config.json'


class ToolCategory(pydantic.BaseModel):
name: str
title: str # human readable title
description: str


class ToolConfig(pydantic.BaseModel):
"""
This represents the configuration data for a tool.
Expand Down Expand Up @@ -100,6 +106,19 @@ def module(self) -> ModuleType:
)


def get_all_tool_categories() -> list[ToolCategory]:
categories = []
filename = TOOLS_DIR / 'categories.json'
data = open_json_file(filename)
for name, category in data.items():
categories.append(ToolCategory(name=name, **category))
return categories


def get_all_tool_category_names() -> list[str]:
return [category.name for category in get_all_tool_categories()]


def get_all_tool_paths() -> list[Path]:
"""
Get all the paths to the tool configuration files.
Expand All @@ -121,3 +140,8 @@ def get_all_tool_names() -> list[str]:

def get_all_tools() -> list[ToolConfig]:
return [ToolConfig.from_tool_name(path) for path in get_all_tool_names()]


def get_tool(name: str) -> ToolConfig:
return ToolConfig.from_tool_name(name)

46 changes: 46 additions & 0 deletions agentstack/_tools/categories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"browsing": {
"title": "Browsing",
"description": "Tools that are used to browse the web."
},
"code-execution": {
"title": "Code Execution",
"description": "Tools that are used to execute code."
},
"computer-control": {
"title": "Computer Control",
"description": "Tools that are used to control a computer."
},
"database": {
"title": "Database",
"description": "Tools that are used to interact with databases."
},
"finance": {
"title": "Finance",
"description": "Tools that are used to interact with financial services."
},
"image-analysis": {
"title": "Image Analysis",
"description": "Tools that are used to analyze images."
},
"network-protocols": {
"title": "Network Protocols",
"description": "Tools that are used to interact with network protocols."
},
"search": {
"title": "Search",
"description": "Tools that are used to search for information."
},
"storage": {
"title": "Storage",
"description": "Tools that are used to interact with storage."
},
"unified-apis": {
"title": "Unified APIs",
"description": "Tools that provide a unified API for interacting with multiple services."
},
"web-retrieval": {
"title": "Web Retrieval",
"description": "Tools that are used to retrieve information from the web."
}
}
2 changes: 1 addition & 1 deletion agentstack/_tools/payman/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "payman",
"category": "financial-infra",
"category": "finance",
"tools": [
"send_payment",
"search_available_payees",
Expand Down
2 changes: 1 addition & 1 deletion agentstack/_tools/stripe/config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "stripe",
"url": "https://github.com/stripe/agent-toolkit",
"category": "application-specific",
"category": "finance",
"env": {
"STRIPE_SECRET_KEY": null
},
Expand Down
2 changes: 1 addition & 1 deletion agentstack/_tools/weaviate/config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "weaviate",
"url": "https://github.com/weaviate/weaviate-python-client",
"category": "vector-store",
"category": "database",
"env": {
"WEAVIATE_URL": null,
"WEAVIATE_API_KEY": null,
Expand Down
4 changes: 1 addition & 3 deletions agentstack/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from .cli import configure_default_model, welcome_message, get_validated_input, parse_insertion_point
from .cli import LOGO, configure_default_model, welcome_message, get_validated_input, parse_insertion_point
from .init import init_project
from .wizard import run_wizard
from .run import run_project
from .tools import list_tools, add_tool, remove_tool
from .tasks import add_task
from .agents import add_agent
from .templates import insert_template, export_template

27 changes: 12 additions & 15 deletions agentstack/cli/cli.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
from typing import Optional
import os, sys
from art import text2art
import inquirer
from agentstack import conf, log
from agentstack.conf import ConfigFile
from agentstack.exceptions import ValidationError
from agentstack.utils import validator_not_empty, is_snake_case
from agentstack import providers
from agentstack.generation import InsertionPoint


PREFERRED_MODELS = [
'groq/deepseek-r1-distill-llama-70b',
'deepseek/deepseek-chat',
'deepseek/deepseek-coder',
'deepseek/deepseek-reasoner',
'openai/gpt-4o',
'anthropic/claude-3-5-sonnet',
'openai/o1-preview',
'openai/gpt-4-turbo',
'anthropic/claude-3-opus',
]
LOGO = """\
___ ___ ___ ___ ___ ___ ___ ___ ___ ___
/\ \ /\ \ /\ \ /\__\ /\ \ /\ \ /\ \ /\ \ /\ \ /\__\
/::\ \ /::\ \ /::\ \ /:| _|_ \:\ \ /::\ \ \:\ \ /::\ \ /::\ \ /:/ _/_
/::\:\__\ /:/\:\__\ /::\:\__\ /::|/\__\ /::\__\ /\:\:\__\ /::\__\ /::\:\__\ /:/\:\__\ /::-"\__\\
\/\::/ / \:\:\/__/ \:\:\/ / \/|::/ / /:/\/__/ \:\:\/__/ /:/\/__/ \/\::/ / \:\ \/__/ \;:;-",-"
/:/ / \::/ / \:\/ / |:/ / \/__/ \::/ / \/__/ /:/ / \:\__\ |:| |
\/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \|__|
"""


def welcome_message():
title = text2art("AgentStack", font="smisome1")
tagline = "The easiest way to build a robust agent application!"
border = "-" * len(tagline)

# Print the welcome message with ASCII art
log.info(title)
log.info(LOGO)
log.info(border)
log.info(tagline)
log.info(border)
Expand All @@ -45,7 +42,7 @@ def configure_default_model():
other_msg = "Other (enter a model name)"
model = inquirer.list_input(
message="Which model would you like to use?",
choices=PREFERRED_MODELS + [other_msg],
choices=providers.get_preferred_model_ids() + [other_msg],
)

if model == other_msg: # If the user selects "Other", prompt for a model name
Expand Down
14 changes: 4 additions & 10 deletions agentstack/cli/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from agentstack.templates import get_all_templates, TemplateConfig

from agentstack.cli import welcome_message
from agentstack.cli.wizard import run_wizard
from agentstack.cli.templates import insert_template


Expand Down Expand Up @@ -67,7 +66,7 @@ def init_project(
slug_name: Optional[str] = None,
template: Optional[str] = None,
framework: Optional[str] = None,
use_wizard: bool = False,
template_data: Optional[TemplateConfig] = None,
):
"""
Initialize a new project in the current directory.
Expand All @@ -78,9 +77,6 @@ def init_project(
- insert Tasks, Agents and Tools
"""
# TODO prevent the user from passing the --path argument to init
if template and use_wizard:
raise Exception("Template and wizard flags cannot be used together")

require_uv()
welcome_message()

Expand All @@ -102,16 +98,14 @@ def init_project(
if os.path.exists(conf.PATH): # cookiecutter requires the directory to not exist
raise Exception(f"Directory already exists: {conf.PATH}")

if use_wizard:
log.debug("Initializing new project with wizard.")
template_data = run_wizard(slug_name)
elif template:
if not template_data and template:
log.debug(f"Initializing new project with template: {template}")
template_data = TemplateConfig.from_user_input(template)
else:
elif not template_data:
log.debug("Initializing new project with template selection.")
template_data = select_template(slug_name, framework)

assert template_data # appease type checker
log.notify("🦾 Creating a new AgentStack project...")
log.info(f"Using project directory: {conf.PATH.absolute()}")

Expand Down
Loading