openagentic-ai 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openagentic_ai-0.1.0/PKG-INFO +12 -0
- openagentic_ai-0.1.0/openagentic_ai/__init__.py +0 -0
- openagentic_ai-0.1.0/openagentic_ai/__main__.py +4 -0
- openagentic_ai-0.1.0/openagentic_ai/agent.py +44 -0
- openagentic_ai-0.1.0/openagentic_ai/prompts/__init__.py +0 -0
- openagentic_ai-0.1.0/openagentic_ai/prompts/prompt.py +28 -0
- openagentic_ai-0.1.0/openagentic_ai/subagents/__init__.py +0 -0
- openagentic_ai-0.1.0/openagentic_ai/subagents/subagents.py +33 -0
- openagentic_ai-0.1.0/openagentic_ai/subagents/subagents_tools/__init__.py +0 -0
- openagentic_ai-0.1.0/openagentic_ai/subagents/subagents_tools/crud_tools.py +84 -0
- openagentic_ai-0.1.0/openagentic_ai/subagents/subagents_tools/internet_search.py +25 -0
- openagentic_ai-0.1.0/openagentic_ai/tools/__init__.py +0 -0
- openagentic_ai-0.1.0/openagentic_ai/tools/planning_tool.py +8 -0
- openagentic_ai-0.1.0/openagentic_ai/utils/__init__.py +0 -0
- openagentic_ai-0.1.0/openagentic_ai/utils/utils.py +25 -0
- openagentic_ai-0.1.0/openagentic_ai.egg-info/PKG-INFO +12 -0
- openagentic_ai-0.1.0/openagentic_ai.egg-info/SOURCES.txt +21 -0
- openagentic_ai-0.1.0/openagentic_ai.egg-info/dependency_links.txt +1 -0
- openagentic_ai-0.1.0/openagentic_ai.egg-info/entry_points.txt +2 -0
- openagentic_ai-0.1.0/openagentic_ai.egg-info/requires.txt +7 -0
- openagentic_ai-0.1.0/openagentic_ai.egg-info/top_level.txt +1 -0
- openagentic_ai-0.1.0/pyproject.toml +25 -0
- openagentic_ai-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openagentic-ai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Powerful claude code open source alternative. AI coding assistant powered by Abdel-Hazim Lawani — use it in any folder
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: deepagents>=0.4.12
|
|
7
|
+
Requires-Dist: langchain>=1.2.13
|
|
8
|
+
Requires-Dist: langchain-core>=1.2.22
|
|
9
|
+
Requires-Dist: langchain-community>=0.4.1
|
|
10
|
+
Requires-Dist: langchain-mistralai
|
|
11
|
+
Requires-Dist: tavily-python>=0.7.23
|
|
12
|
+
Requires-Dist: python-dotenv
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from deepagents import create_deep_agent
|
|
4
|
+
from deepagents.backends import FilesystemBackend
|
|
5
|
+
from langchain.chat_models import init_chat_model
|
|
6
|
+
|
|
7
|
+
from openagentic_ai.prompts.prompt import DEEP_AGENT_SYSTEM_PROMPT
|
|
8
|
+
from openagentic_ai.subagents.subagents import subagents
|
|
9
|
+
from openagentic_ai.subagents.subagents_tools.internet_search import internet_search
|
|
10
|
+
from openagentic_ai.utils.utils import base_llm
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def build_agent():
|
|
14
|
+
model = init_chat_model(base_llm)
|
|
15
|
+
tools = [internet_search]
|
|
16
|
+
backend = FilesystemBackend(root_dir=".", virtual_mode=True)
|
|
17
|
+
return create_deep_agent(
|
|
18
|
+
model=model,
|
|
19
|
+
tools=tools,
|
|
20
|
+
system_prompt=DEEP_AGENT_SYSTEM_PROMPT,
|
|
21
|
+
subagents=subagents,
|
|
22
|
+
backend=backend,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main():
|
|
27
|
+
parser = argparse.ArgumentParser(
|
|
28
|
+
prog="open-code",
|
|
29
|
+
description="AI coding assistant powered by deepagents",
|
|
30
|
+
)
|
|
31
|
+
parser.add_argument("query", nargs="?", help="Query to send to the agent (optional, will prompt if omitted)")
|
|
32
|
+
parser.add_argument("--mode", choices=["ask", "auto", "plan"], default="auto", help="Agent mode (default: auto)")
|
|
33
|
+
args = parser.parse_args()
|
|
34
|
+
|
|
35
|
+
agent = build_agent()
|
|
36
|
+
|
|
37
|
+
query = args.query if args.query else input("Requête : ").strip()
|
|
38
|
+
|
|
39
|
+
result = agent.invoke({"messages": [{"role": "user", "content": query}]})
|
|
40
|
+
print(result["messages"][-1].content)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
if __name__ == "__main__":
|
|
44
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
DEEP_AGENT_SYSTEM_PROMPT = """
|
|
2
|
+
You are a coding assistant working inside a project workspace
|
|
3
|
+
Your capabilities include:
|
|
4
|
+
|
|
5
|
+
FILE MANAGEMENT:
|
|
6
|
+
- Create, read, edit, delete files
|
|
7
|
+
- Create, list, delete directories
|
|
8
|
+
- Search within files using grep
|
|
9
|
+
|
|
10
|
+
CODE EXECUTION:
|
|
11
|
+
- Run commands and scripts safely inside a Docker sandbox
|
|
12
|
+
- Capture stdout/stderr and save long outputs to files
|
|
13
|
+
|
|
14
|
+
PLANNING:
|
|
15
|
+
- Break down coding tasks into subtasks
|
|
16
|
+
- Organize work into TODO notes saved in files
|
|
17
|
+
|
|
18
|
+
DELEGATION:
|
|
19
|
+
- Use the FileOps sub-agent for filesystem operations
|
|
20
|
+
- Use the CodeRunner sub-agent for executing code
|
|
21
|
+
|
|
22
|
+
When approaching a complex task:
|
|
23
|
+
1. First, create a plan and save it as a TODO file
|
|
24
|
+
2. Manipulate files and directories as needed
|
|
25
|
+
3. Execute code or commands in the sandbox when required
|
|
26
|
+
4. Synthesize results into a clear response
|
|
27
|
+
|
|
28
|
+
"""
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from deepagents import SubAgent
|
|
2
|
+
from openagentic_ai.subagents.subagents_tools.crud_tools import (
|
|
3
|
+
create_file, read_file, edit_file, delete_file,
|
|
4
|
+
grep_file, list_dir, create_dir, delete_dir
|
|
5
|
+
)
|
|
6
|
+
from openagentic_ai.subagents.subagents_tools.internet_search import internet_search
|
|
7
|
+
from openagentic_ai.utils.utils import base_llm
|
|
8
|
+
|
|
9
|
+
subagents: list[SubAgent] = [
|
|
10
|
+
{
|
|
11
|
+
"name": "file-ops-agent",
|
|
12
|
+
"description": "Handles all filesystem operations inside the sandbox directory",
|
|
13
|
+
"system_prompt": "You are a file management specialist. Focus on creating, reading, editing, deleting files and directories...",
|
|
14
|
+
"tools": [
|
|
15
|
+
create_file, read_file, edit_file, delete_file,
|
|
16
|
+
grep_file, list_dir, create_dir, delete_dir
|
|
17
|
+
],
|
|
18
|
+
"model": base_llm
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "runner-agent",
|
|
22
|
+
"description": "Executes code and commands safely inside a local sandbox",
|
|
23
|
+
"system_prompt": "You are a code execution specialist. Run scripts and commands, capture output, and report results.",
|
|
24
|
+
"model": base_llm
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "research-agent",
|
|
28
|
+
"description": "Conducts research and gathers external information when needed",
|
|
29
|
+
"system_prompt": "You are a research specialist. Use internet_search and document findings in files...",
|
|
30
|
+
"tools": [internet_search, read_file, create_file],
|
|
31
|
+
"model": base_llm
|
|
32
|
+
}
|
|
33
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from langchain_core.tools import tool
|
|
4
|
+
|
|
5
|
+
SANDBOX_DIR = "./agent_sandbox"
|
|
6
|
+
|
|
7
|
+
# --- Outils CRUD pour FileOps ---
|
|
8
|
+
@tool
|
|
9
|
+
def create_file(path: str, content: str = "") -> str:
|
|
10
|
+
"""Create a file at the given path with optional content."""
|
|
11
|
+
full_path = os.path.join(SANDBOX_DIR, path)
|
|
12
|
+
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
|
13
|
+
with open(full_path, "w") as f:
|
|
14
|
+
f.write(content)
|
|
15
|
+
return f"File {full_path} created."
|
|
16
|
+
|
|
17
|
+
@tool
|
|
18
|
+
def read_file(path: str) -> str:
|
|
19
|
+
"""Read and return the content of a file."""
|
|
20
|
+
full_path = os.path.join(SANDBOX_DIR, path)
|
|
21
|
+
if not os.path.exists(full_path):
|
|
22
|
+
return f"File {full_path} not found."
|
|
23
|
+
with open(full_path, "r") as f:
|
|
24
|
+
return f.read()
|
|
25
|
+
|
|
26
|
+
@tool
|
|
27
|
+
def edit_file(path: str, old_string: str, new_string: str) -> str:
|
|
28
|
+
"""Replace old_string with new_string in the specified file."""
|
|
29
|
+
full_path = os.path.join(SANDBOX_DIR, path)
|
|
30
|
+
if not os.path.exists(full_path):
|
|
31
|
+
return f"File {full_path} not found."
|
|
32
|
+
with open(full_path, "r") as f:
|
|
33
|
+
content = f.read()
|
|
34
|
+
if old_string not in content:
|
|
35
|
+
return f"String not found in {full_path}."
|
|
36
|
+
with open(full_path, "w") as f:
|
|
37
|
+
f.write(content.replace(old_string, new_string, 1))
|
|
38
|
+
return f"File {full_path} edited."
|
|
39
|
+
|
|
40
|
+
@tool
|
|
41
|
+
def delete_file(path: str) -> str:
|
|
42
|
+
"""Delete a file at the given path."""
|
|
43
|
+
full_path = os.path.join(SANDBOX_DIR, path)
|
|
44
|
+
if not os.path.exists(full_path):
|
|
45
|
+
return f"File {full_path} not found."
|
|
46
|
+
os.remove(full_path)
|
|
47
|
+
return f"File {full_path} deleted."
|
|
48
|
+
|
|
49
|
+
@tool
|
|
50
|
+
def grep_file(path: str, pattern: str) -> str:
|
|
51
|
+
"""Search for a pattern in a file and return matching lines."""
|
|
52
|
+
full_path = os.path.join(SANDBOX_DIR, path)
|
|
53
|
+
if not os.path.exists(full_path):
|
|
54
|
+
return f"File {full_path} not found."
|
|
55
|
+
results = []
|
|
56
|
+
with open(full_path, "r") as f:
|
|
57
|
+
for i, line in enumerate(f, start=1):
|
|
58
|
+
if pattern in line:
|
|
59
|
+
results.append(f"Line {i}: {line.strip()}")
|
|
60
|
+
return "\n".join(results) if results else f"No matches for '{pattern}'."
|
|
61
|
+
|
|
62
|
+
@tool
|
|
63
|
+
def list_dir(path: str = ".") -> str:
|
|
64
|
+
"""List the contents of a directory."""
|
|
65
|
+
full_path = os.path.join(SANDBOX_DIR, path)
|
|
66
|
+
if not os.path.exists(full_path):
|
|
67
|
+
return f"Directory {full_path} not found."
|
|
68
|
+
return "\n".join(os.listdir(full_path))
|
|
69
|
+
|
|
70
|
+
@tool
|
|
71
|
+
def create_dir(path: str) -> str:
|
|
72
|
+
"""Create a directory at the given path."""
|
|
73
|
+
full_path = os.path.join(SANDBOX_DIR, path)
|
|
74
|
+
os.makedirs(full_path, exist_ok=True)
|
|
75
|
+
return f"Directory {full_path} created."
|
|
76
|
+
|
|
77
|
+
@tool
|
|
78
|
+
def delete_dir(path: str) -> str:
|
|
79
|
+
"""Delete an empty directory at the given path."""
|
|
80
|
+
full_path = os.path.join(SANDBOX_DIR, path)
|
|
81
|
+
if not os.path.exists(full_path):
|
|
82
|
+
return f"Directory {full_path} not found."
|
|
83
|
+
os.rmdir(full_path)
|
|
84
|
+
return f"Directory {full_path} deleted."
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any, Dict, Literal
|
|
3
|
+
|
|
4
|
+
from langchain_core.tools import tool
|
|
5
|
+
from tavily import TavilyClient
|
|
6
|
+
|
|
7
|
+
TAVILY_KEY = os.environ.get("TAVILY_API_KEY", "")
|
|
8
|
+
|
|
9
|
+
@tool
|
|
10
|
+
def internet_search(
|
|
11
|
+
query: str,
|
|
12
|
+
max_results: int = 5,
|
|
13
|
+
topic: Literal["general", "news", "finance"] = "general",
|
|
14
|
+
include_raw_content: bool = False,
|
|
15
|
+
) -> Dict[str, Any]:
|
|
16
|
+
"""Search the internet using Tavily and return results."""
|
|
17
|
+
if not TAVILY_KEY:
|
|
18
|
+
raise RuntimeError("TAVILY_API_KEY is not set in the environment.")
|
|
19
|
+
client = TavilyClient(api_key=TAVILY_KEY)
|
|
20
|
+
return client.search(
|
|
21
|
+
query=query,
|
|
22
|
+
max_results=max_results,
|
|
23
|
+
include_raw_content=include_raw_content,
|
|
24
|
+
topic=topic,
|
|
25
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from langchain.tools import tool
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
@tool
|
|
5
|
+
def todo_write(tasks: List[str]) -> str:
|
|
6
|
+
"""Create a todo list with the given tasks."""
|
|
7
|
+
formatted_tasks = "\n".join([f"- {task}" for task in tasks])
|
|
8
|
+
return f"Todo list created:\n{formatted_tasks}"
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import os
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
|
|
5
|
+
load_dotenv()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def parse_mentions(text: str) -> list[str]:
|
|
9
|
+
"""Parser les mentions @ du user pour sélectionner les fichiers qu'il mentionne."""
|
|
10
|
+
return re.findall(r"@([\w./\\-]+)", text)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def mode_router(mode: str) -> str:
|
|
14
|
+
"""Retourne le system prompt additionnel selon le mode ask/auto/plan choisi par le user."""
|
|
15
|
+
modes = {
|
|
16
|
+
"ask": "Only answer questions and explain. Do NOT modify any files or run any commands.",
|
|
17
|
+
"auto": "Work autonomously: plan, edit files, and run commands as needed to complete the task.",
|
|
18
|
+
"plan": "First produce a detailed step-by-step plan and wait for user approval before doing anything.",
|
|
19
|
+
}
|
|
20
|
+
if mode not in modes:
|
|
21
|
+
raise ValueError(f"Unknown mode '{mode}'. Choose from: {list(modes.keys())}")
|
|
22
|
+
return modes[mode]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
base_llm = os.environ.get("MISTRAL_MODEL", "mistral-large-latest")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openagentic-ai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Powerful claude code open source alternative. AI coding assistant powered by Abdel-Hazim Lawani — use it in any folder
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: deepagents>=0.4.12
|
|
7
|
+
Requires-Dist: langchain>=1.2.13
|
|
8
|
+
Requires-Dist: langchain-core>=1.2.22
|
|
9
|
+
Requires-Dist: langchain-community>=0.4.1
|
|
10
|
+
Requires-Dist: langchain-mistralai
|
|
11
|
+
Requires-Dist: tavily-python>=0.7.23
|
|
12
|
+
Requires-Dist: python-dotenv
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
openagentic_ai/__init__.py
|
|
3
|
+
openagentic_ai/__main__.py
|
|
4
|
+
openagentic_ai/agent.py
|
|
5
|
+
openagentic_ai.egg-info/PKG-INFO
|
|
6
|
+
openagentic_ai.egg-info/SOURCES.txt
|
|
7
|
+
openagentic_ai.egg-info/dependency_links.txt
|
|
8
|
+
openagentic_ai.egg-info/entry_points.txt
|
|
9
|
+
openagentic_ai.egg-info/requires.txt
|
|
10
|
+
openagentic_ai.egg-info/top_level.txt
|
|
11
|
+
openagentic_ai/prompts/__init__.py
|
|
12
|
+
openagentic_ai/prompts/prompt.py
|
|
13
|
+
openagentic_ai/subagents/__init__.py
|
|
14
|
+
openagentic_ai/subagents/subagents.py
|
|
15
|
+
openagentic_ai/subagents/subagents_tools/__init__.py
|
|
16
|
+
openagentic_ai/subagents/subagents_tools/crud_tools.py
|
|
17
|
+
openagentic_ai/subagents/subagents_tools/internet_search.py
|
|
18
|
+
openagentic_ai/tools/__init__.py
|
|
19
|
+
openagentic_ai/tools/planning_tool.py
|
|
20
|
+
openagentic_ai/utils/__init__.py
|
|
21
|
+
openagentic_ai/utils/utils.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
openagentic_ai
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "openagentic-ai"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Powerful claude code open source alternative. AI coding assistant powered by Abdel-Hazim Lawani — use it in any folder"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"deepagents>=0.4.12",
|
|
12
|
+
"langchain>=1.2.13",
|
|
13
|
+
"langchain-core>=1.2.22",
|
|
14
|
+
"langchain-community>=0.4.1",
|
|
15
|
+
"langchain-mistralai",
|
|
16
|
+
"tavily-python>=0.7.23",
|
|
17
|
+
"python-dotenv",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
open-code = "openagentic_ai.agent:main"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["."]
|
|
25
|
+
include = ["openagentic_ai*"]
|