Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c0b830c
improve BaseTool and support MCP tools integration
ducphuE10 Jul 18, 2025
f1f4d7e
simple tool execution confirmation
ducphuE10 Jul 20, 2025
ed7ad2c
tmp remove legacy tool impl
ducphuE10 Jul 20, 2025
35de532
register core mcp tools and web_search/visit/dev tools
ducphuE10 Jul 21, 2025
c1c645a
Arrow selective instead input number / improve visualization of tools…
PhungVanDuy Jul 22, 2025
3006383
Merge branch 'feat/split_agent_controller' into refactor/tool
ducphuE10 Jul 22, 2025
2d69b7f
catch the tool error in mcp_tool.py
ducphuE10 Jul 22, 2025
278117a
move mcp and tool to a separate package
ducphuE10 Jul 22, 2025
55fac4b
add read_only field to tool
ducphuE10 Jul 22, 2025
d4ed725
dev core tool class and wrap the mcp
ducphuE10 Jul 23, 2025
679b6fb
unify input of tool execution method to tool_input: dict[str, Any]
ducphuE10 Jul 24, 2025
457693d
add wrapped mcp tool and function for fetching all tools in MCP
ducphuE10 Jul 24, 2025
eabca9a
add configuration and web related tool
ducphuE10 Jul 24, 2025
c0bcded
fix running http server
ducphuE10 Jul 24, 2025
ebd09c6
add helper and util
ducphuE10 Jul 24, 2025
98e253c
add video generation tools
ducphuE10 Jul 24, 2025
ae75f4a
add image generation tool
ducphuE10 Jul 24, 2025
11e3654
add await when create mcp server
ducphuE10 Jul 24, 2025
902c078
add fullstack dev tool
ducphuE10 Jul 24, 2025
46cc1bb
move tools from ii_agent to ii_tool
ducphuE10 Jul 24, 2025
fea82fa
fix ls tool
ducphuE10 Jul 24, 2025
358e2e4
remove unused files
ducphuE10 Jul 28, 2025
9f76843
enhance confirmation logic
ducphuE10 Jul 28, 2025
9ecbdb3
unify system prompt
ducphuE10 Jul 29, 2025
a0812fa
onboarding setup for tools
ducphuE10 Jul 29, 2025
96e3361
Feat:
khoangothe Jul 29, 2025
2ddfdeb
fix prompt terminal
ducphuE10 Jul 29, 2025
705e1c8
fix file_edit_tool confirmation type
ducphuE10 Jul 29, 2025
1879aaf
support tool return image
ducphuE10 Jul 29, 2025
b3a6140
Merge branch 'feat/split_agent_controller' into refactor/tool
ducphuE10 Jul 30, 2025
808c0c8
remove tmp system prompt in src/ii_tool
ducphuE10 Jul 30, 2025
b492ae6
feat: decouple tool
khoangothe Jul 30, 2025
b1ba2b1
chore: cleanup
khoangothe Jul 30, 2025
e487075
Merge branch 'feat/split_agent_controller' into refactor/tool
ducphuE10 Jul 30, 2025
a291637
chore: cleanup
khoangothe Jul 30, 2025
2527e76
Merge branch 'refactor/tool' into feat/web-template-mcp
khoangothe Jul 30, 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
148 changes: 46 additions & 102 deletions src/ii_tool/tools/dev/init_tool.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import subprocess

from typing import Any
from ii_tool.tools.dev.template_processor.registry import WebProcessorRegistry
from ii_tool.core.config import FullStackDevConfig
from ii_tool.tools.base import BaseTool, ToolResult
from ii_tool.core.workspace import WorkspaceManager
Expand All @@ -13,10 +13,9 @@

# Description
DESCRIPTION = """\
This tool initializes a fullstack web application environment by using the development template. It constructs a `frontend` and `backend` template directory inside the project path, and installs all necessary packages.
This tool initializes a fullstack web application environment by using the development template.

<backend_rules>
- Technology stack: Python, FastAPI, SQLite
- Write comprehensive tests for all endpoints and business logic
* Cover all scenarios for each endpoint, including edge cases
* All tests must be passed before proceeding
Expand All @@ -39,23 +38,28 @@
</deployment_rules>

<debug_rules>
- Use Python `requests` to call the backend endpoint
- Test backend endpoint by calling api with the suitable stack
- View the shell output to debug errors
- Search the internet about the error to find the solution if needed
</debug_rules>
"""

# Input schema
INPUT_SCHEMA = {
"type": "object",
"properties": {
"project_name": {
"type": "string",
"description": "A name for your project (lowercase, no spaces, use hyphens - if needed). Example: `my-app`, `todo-app`",
},
"type": "object",
"properties": {
"project_name": {
"type": "string",
"description": "A name for your project (lowercase, no spaces, use hyphens - if needed). Example: `my-app`, `todo-app`",
},
"required": ["project_name"],
}
"framework": {
"type": "string",
"description": "The framework to use for the project",
"enum": ["nextjs-shadcn", "react-tailwind-python"],
},
},
"required": ["project_name", "framework"],
}

class FullStackInitTool(BaseTool):
name = NAME
Expand All @@ -78,97 +82,37 @@ async def execute(
tool_input: dict[str, Any],
) -> ToolResult:
project_name = tool_input["project_name"]

# Create the frontend directory if it doesn't exist
workspace_dir = str(self.workspace_manager.get_workspace_path())
project_dir = f"{workspace_dir}/{project_name}"
frontend_dir = f"{project_dir}/frontend"
backend_dir = f"{project_dir}/backend"

framework = tool_input["framework"]
project_dir = os.path.join(
self.workspace_manager.get_workspace_path(), project_name
)
if os.path.exists(project_dir):
return ToolResult(
llm_content=f"Project directory {project_dir} already exists, please choose a different project name",
user_display_content="Project directory already exists, please choose a different project name",
is_error=True,
)

os.makedirs(project_dir, exist_ok=True)

print("Creating project directory: ", project_dir)

template_path = self.settings.template_path.rstrip("/")

get_template_command = f"cp -r {template_path}/* {project_dir}"
subprocess.run(get_template_command, shell=True)

print("Copy template done, see the project directory: ", project_dir)

# Install dependencies
# frontend
frontend_install_command = f"bun install"
subprocess.run(frontend_install_command, shell=True, cwd=frontend_dir)

frontend_add_command = "bun add axios lucide-react react-router-dom"
subprocess.run(frontend_add_command, shell=True, cwd=frontend_dir)

# backend
backend_install_command = "pip install -r requirements.txt"
subprocess.run(backend_install_command, shell=True, cwd=backend_dir)

print("Installed dependencies")

output_message = f"""Successfully initialized codebase:
```
{project_name}
├── backend/
│ ├── README.md
│ ├── requirements.txt
│ └── src/
│ ├── __init__.py
│ ├── main.py
│ └── tests/
│ └── __init__.py
└── frontend/
├── README.md
├── eslint.config.js
├── index.html
├── package.json
├── public/
│ └── _redirects
├── src/
│ ├── App.jsx
│ ├── components/
│ ├── context/
│ ├── index.css
│ ├── lib/
│ ├── main.jsx
│ ├── pages/
│ └── services/
└── vite.config.js
```

Installed dependencies:
- Frontend:
* `bun install`
* `bun install tailwindcss @tailwindcss/vite`
* `bun add axios lucide-react react-router-dom`
- Backend:
* `pip install -r requirements.txt`
* Contents of `requirements.txt`:
```
fastapi
uvicorn
sqlalchemy
python-dotenv
pydantic
pydantic-settings
pytest
pytest-asyncio
httpx
openai
bcrypt
python-jose[cryptography]
python-multipart
cryptography
requests
```

You don't need to re-install the dependencies above, they are already installed"""

return ToolResult(llm_content=output_message, user_display_content="Successfully initialized fullstack web application")
processor = WebProcessorRegistry.create(
framework,
project_dir,
)
try:
processor.start_up_project()
except Exception as e:
return ToolResult(
llm_content=f"Failed to start up project in {project_dir}: {e}",
user_display_content=f"Failed to start up project in {project_dir}: {e}",
is_error=True,
)

return ToolResult(
llm_content=f"Successfully initialized fullstack web application in {project_dir}. Tool output: {processor.get_project_rule()}",
user_display_content=f"Successfully initialized fullstack web application in {project_dir}. Tool output: {processor.get_project_rule()}",
is_error=False,
)

async def execute_mcp_wrapper(
self,
Expand All @@ -178,4 +122,4 @@ async def execute_mcp_wrapper(
tool_input={
"project_name": project_name,
}
)
)
12 changes: 12 additions & 0 deletions src/ii_tool/tools/dev/template_processor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Import all processors to ensure their decorators run and register them
from .nextjs_shadcn import NextShadcnProcessor
from .react_tailwind_python import ReactTailwindPythonProcessor

# Export the registry for easy access
from .registry import WebProcessorRegistry

__all__ = [
"WebProcessorRegistry",
"NextShadcnProcessor",
"ReactTailwindPythonProcessor",
]
46 changes: 46 additions & 0 deletions src/ii_tool/tools/dev/template_processor/base_processor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from abc import ABC, abstractmethod
import subprocess
from typing_extensions import final
from ii_tool.tools.utils import get_project_root


class BaseProcessor(ABC):
project_rule: str
template_name: str

def __init__(
self,
project_dir: str,
):
self.project_dir = project_dir

@abstractmethod
def install_dependencies(self):
raise NotImplementedError("install_dependencies method not implemented")

@final
def copy_project_template(self):
out = subprocess.run(
f"cp -rf {get_project_root()}/.templates/{self.template_name}/* .",
shell=True,
cwd=self.project_dir,
capture_output=True,
)
if out.returncode != 0:
raise Exception(
f"Failed to copy project template: {out.stderr.decode('utf-8')}. Please initialize the project manually"
)

@final
def start_up_project(self):
try:
self.copy_project_template()
self.install_dependencies()
except Exception as e:
raise Exception(f"Failed to start up project: {e}")

@final
def get_project_rule(self) -> str:
if self.project_rule is None:
raise Exception("Project rule is not set")
return self.project_rule
93 changes: 93 additions & 0 deletions src/ii_tool/tools/dev/template_processor/nextjs_shadcn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import subprocess
from ii_tool.tools.dev.template_processor.base_processor import BaseProcessor
from ii_tool.tools.dev.template_processor.registry import WebProcessorRegistry


def deployment_rule(project_path: str) -> str:
return f"""
Project directory `{project_path}` created successfully. Application code is in `{project_path}/src`. File tree:
```
{project_path}/
│ ├── .gitignore # Git ignore file
│ ├── biome.json # Biome linter/formatter configuration
│ ├── jest.config.js # Jest configuration
│ ├── bun.lock # Lock file for dependencies
│ ├── components.json # shadcn/ui configuration
│ ├── eslint.config.mjs # ESLint configuration
│ ├── next-env.d.ts # Next.js TypeScript declarations
│ ├── next.config.js # Next.js configuration
│ ├── package.json # Project dependencies and scripts
│ ├── postcss.config.mjs # PostCSS configuration
│ ├── README.md # Project documentation
│ ├── __tests__/ # Jest test directory
│ ├── src/ # Source code directory
│ │ ├── app/ # Next.js App Router directory
│ │ │ ├── ClientBody.tsx # Client-side body component
│ │ │ ├── globals.css # Global styles
│ │ │ ├── layout.tsx # Root layout component
│ │ ├── page.tsx # Home page component
│ └── lib/ # Utility functions and libraries
│ └── utils.ts # Utility functions
│ └── components/ # Components directory
│ └── ui/ # shadcn/ui components
│ └── button.tsx # Button component
│ ├── tailwind.config.ts # Tailwind CSS configuration
└── tsconfig.json # TypeScript configuration
```
IMPORTANT NOTE: This project is built with TypeScript(tsx) and Next.js App Router.
Add components with `cd {project_path} && bunx shadcn@latest add -y -o`. Import components with `@/` alias. Note, 'toast' is deprecated, use 'sonner' instead. Before editing, run `cd {project_path} && bun install` to install dependencies. Run `cd {project_path} && bun run dev` to start the dev server ASAP to catch any runtime errors. Remember that all terminal commands must be run from the project directory.
Any database operations must be done with Prisma ORM.
Authentication must be done with NextAuth. Use bcrypt for password hashing.
Use Chart.js for charts. Moveable for Draggable, Resizable, Scalable, Rotatable, Warpable, Pinchable, Groupable, Snappable components.
Use AOS for scroll animations. React-Player for video player.
Advance animations must be done with Framer Motion, Anime.js, and React Three Fiber.
Before writing the frontend integration, you must write an openapi spec for the backend then you must write test for all the expected http requests and responses using supertest (already installed).
Run the test by running `bun test`. Any backend operations must pass all test before you begin your deployment
The integration must follow the api contract strictly. Your predecessor was killed because he did not follow the api contract.

IMPORTANT: All the todo list must be done before you can return to the user.

If you need to use websocket, follow this guide: https://socket.io/how-to/use-with-nextjs
You must use socket.io and (IMPORTANT) socket.io-client for websocket.
Socket.io rules:
"Separate concerns, sanitize data, handle failures gracefully"

NEVER send objects with circular references or function properties
ALWAYS validate data serializability before transmission
SEPARATE connection management from business logic storage
SANITIZE all data crossing network boundaries
CLEANUP resources and event listeners to prevent memory leaks
HANDLE network failures, timeouts, and reconnections
VALIDATE all incoming data on both client and server
TEST with multiple concurrent connections under load

APPLIES TO: Any real-time system (WebSockets, Server-Sent Events, WebRTC, polling)


Banned libraries (will break with this template): Quill

"""


@WebProcessorRegistry.register("nextjs-shadcn")
class NextShadcnProcessor(BaseProcessor):
template_name = "nextjs-shadcn"

def __init__(
self,
project_dir: str,
):
super().__init__(project_dir)
self.project_rule = deployment_rule(project_dir)

def install_dependencies(self):
install_result = subprocess.run(
"bun install",
shell=True,
cwd=self.project_dir,
capture_output=True,
)
if install_result.returncode != 0:
raise Exception(
f"Failed to install dependencies automatically: {install_result.stderr.decode('utf-8')}. Please fix the error and run `bun install` in the project directory manually"
)
Loading