neuroagent 1.3.0
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.
- package/LICENSE +21 -0
- package/README.md +273 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +215 -0
- package/neuroagent/__init__.py +29 -0
- package/neuroagent/agents/__init__.py +3 -0
- package/neuroagent/agents/agent.py +253 -0
- package/neuroagent/cli/__init__.py +3 -0
- package/neuroagent/cli/neuroagent_cli.py +182 -0
- package/neuroagent/examples/__init__.py +1 -0
- package/neuroagent/examples/dev_agent.py +31 -0
- package/neuroagent/examples/multi_agent_team.py +45 -0
- package/neuroagent/examples/website_agent.py +27 -0
- package/neuroagent/frontend/__init__.py +1 -0
- package/neuroagent/frontend/widget.js +409 -0
- package/neuroagent/llm/__init__.py +5 -0
- package/neuroagent/llm/base.py +46 -0
- package/neuroagent/llm/local_model_provider.py +76 -0
- package/neuroagent/llm/openai_provider.py +58 -0
- package/neuroagent/memory/__init__.py +5 -0
- package/neuroagent/memory/long_memory.py +52 -0
- package/neuroagent/memory/short_memory.py +39 -0
- package/neuroagent/memory/vector_memory.py +57 -0
- package/neuroagent/planner/__init__.py +3 -0
- package/neuroagent/planner/planner.py +90 -0
- package/neuroagent/server/__init__.py +16 -0
- package/neuroagent/server/api_server.py +191 -0
- package/neuroagent/server/websocket_server.py +108 -0
- package/neuroagent/team/__init__.py +3 -0
- package/neuroagent/team/team.py +134 -0
- package/neuroagent/tools/__init__.py +19 -0
- package/neuroagent/tools/base.py +45 -0
- package/neuroagent/tools/code_executor.py +69 -0
- package/neuroagent/tools/file_manager.py +62 -0
- package/neuroagent/tools/http_client.py +57 -0
- package/neuroagent/tools/web_search.py +48 -0
- package/neuroagent/utils/__init__.py +3 -0
- package/neuroagent/utils/helpers.py +31 -0
- package/package.json +56 -0
- package/requirements.txt +15 -0
- package/setup.py +61 -0
- package/src/index.d.ts +55 -0
- package/src/index.js +215 -0
- package/web_example/index.html +249 -0
- package/web_example/neuroagent.js +301 -0
- package/web_example/script.js +114 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import tempfile
|
|
3
|
+
import os
|
|
4
|
+
from typing import Dict, Any
|
|
5
|
+
from neuroagent.tools.base import Tool
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CodeExecutorTool(Tool):
|
|
9
|
+
def __init__(self):
|
|
10
|
+
super().__init__(
|
|
11
|
+
name="code_executor",
|
|
12
|
+
description="Execute Python or JavaScript code. Input: code string. Output: execution result."
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
async def execute(self, code: str, language: str = "python") -> Dict[str, Any]:
|
|
16
|
+
try:
|
|
17
|
+
if language == "python":
|
|
18
|
+
return await self._execute_python(code)
|
|
19
|
+
elif language == "javascript":
|
|
20
|
+
return await self._execute_javascript(code)
|
|
21
|
+
else:
|
|
22
|
+
return {"error": f"Unsupported language: {language}"}
|
|
23
|
+
except Exception as e:
|
|
24
|
+
return {"error": str(e), "output": None}
|
|
25
|
+
|
|
26
|
+
async def _execute_python(self, code: str) -> Dict[str, Any]:
|
|
27
|
+
import asyncio
|
|
28
|
+
|
|
29
|
+
def run_code():
|
|
30
|
+
output = []
|
|
31
|
+
errors = []
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
compiled = compile(code, "<string>", "exec")
|
|
35
|
+
exec_globals = {}
|
|
36
|
+
exec(compiled, exec_globals)
|
|
37
|
+
|
|
38
|
+
for key, value in exec_globals.items():
|
|
39
|
+
if not key.startswith("_"):
|
|
40
|
+
output.append(f"{key} = {repr(value)}")
|
|
41
|
+
|
|
42
|
+
return {"output": "\n".join(output) if output else "Code executed successfully", "error": None}
|
|
43
|
+
except Exception as e:
|
|
44
|
+
return {"output": None, "error": str(e)}
|
|
45
|
+
|
|
46
|
+
return await asyncio.to_thread(run_code)
|
|
47
|
+
|
|
48
|
+
async def _execute_javascript(self, code: str) -> Dict[str, Any]:
|
|
49
|
+
try:
|
|
50
|
+
import aiohttp
|
|
51
|
+
url = "https://api.jdoodle.com/v1/execute"
|
|
52
|
+
payload = {
|
|
53
|
+
"script": code,
|
|
54
|
+
"language": "nodejs",
|
|
55
|
+
"versionIndex": 0
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async with aiohttp.ClientSession() as session:
|
|
59
|
+
async with session.post(url, json=payload) as response:
|
|
60
|
+
data = await response.json()
|
|
61
|
+
return {"output": data.get("output", ""), "error": data.get("error")}
|
|
62
|
+
except Exception as e:
|
|
63
|
+
return {"output": None, "error": str(e)}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def code_executor(code: str, language: str = "python") -> Dict[str, Any]:
|
|
67
|
+
import asyncio
|
|
68
|
+
tool = CodeExecutorTool()
|
|
69
|
+
return asyncio.run(tool.execute(code, language))
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Dict, Any, Optional, List
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from neuroagent.tools.base import Tool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FileManagerTool(Tool):
|
|
8
|
+
def __init__(self, base_path: Optional[str] = None):
|
|
9
|
+
super().__init__(
|
|
10
|
+
name="file_manager",
|
|
11
|
+
description="Create, read, update, delete files. Actions: read, write, list, delete."
|
|
12
|
+
)
|
|
13
|
+
self.base_path = Path(base_path or os.getcwd())
|
|
14
|
+
|
|
15
|
+
async def execute(self, action: str, path: str = "", content: str = "") -> Dict[str, Any]:
|
|
16
|
+
try:
|
|
17
|
+
file_path = self.base_path / path
|
|
18
|
+
|
|
19
|
+
if action == "read":
|
|
20
|
+
if not file_path.exists():
|
|
21
|
+
return {"error": f"File not found: {path}"}
|
|
22
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
23
|
+
return {"content": f.read(), "path": path}
|
|
24
|
+
|
|
25
|
+
elif action == "write":
|
|
26
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
27
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
28
|
+
f.write(content)
|
|
29
|
+
return {"success": True, "path": path}
|
|
30
|
+
|
|
31
|
+
elif action == "list":
|
|
32
|
+
if not file_path.exists():
|
|
33
|
+
return {"error": f"Directory not found: {path}"}
|
|
34
|
+
items = []
|
|
35
|
+
for item in file_path.iterdir():
|
|
36
|
+
items.append({
|
|
37
|
+
"name": item.name,
|
|
38
|
+
"type": "directory" if item.is_dir() else "file"
|
|
39
|
+
})
|
|
40
|
+
return {"items": items, "path": path}
|
|
41
|
+
|
|
42
|
+
elif action == "delete":
|
|
43
|
+
if not file_path.exists():
|
|
44
|
+
return {"error": f"Path not found: {path}"}
|
|
45
|
+
if file_path.is_file():
|
|
46
|
+
file_path.unlink()
|
|
47
|
+
else:
|
|
48
|
+
import shutil
|
|
49
|
+
shutil.rmtree(file_path)
|
|
50
|
+
return {"success": True, "path": path}
|
|
51
|
+
|
|
52
|
+
else:
|
|
53
|
+
return {"error": f"Unknown action: {action}"}
|
|
54
|
+
|
|
55
|
+
except Exception as e:
|
|
56
|
+
return {"error": str(e)}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def file_manager(action: str, path: str = "", content: str = "") -> Dict[str, Any]:
|
|
60
|
+
import asyncio
|
|
61
|
+
tool = FileManagerTool()
|
|
62
|
+
return asyncio.run(tool.execute(action, path, content))
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import aiohttp
|
|
2
|
+
from typing import Dict, Any, Optional
|
|
3
|
+
from neuroagent.tools.base import Tool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class HTTPClientTool(Tool):
|
|
7
|
+
def __init__(self):
|
|
8
|
+
super().__init__(
|
|
9
|
+
name="http_client",
|
|
10
|
+
description="Make HTTP requests (GET, POST, PUT, DELETE). Input: url, method, headers, body."
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
async def execute(
|
|
14
|
+
self,
|
|
15
|
+
url: str,
|
|
16
|
+
method: str = "GET",
|
|
17
|
+
headers: Optional[Dict[str, str]] = None,
|
|
18
|
+
body: Optional[Dict[str, Any]] = None
|
|
19
|
+
) -> Dict[str, Any]:
|
|
20
|
+
try:
|
|
21
|
+
headers = headers or {"Content-Type": "application/json"}
|
|
22
|
+
|
|
23
|
+
async with aiohttp.ClientSession() as session:
|
|
24
|
+
async with session.request(
|
|
25
|
+
method=method.upper(),
|
|
26
|
+
url=url,
|
|
27
|
+
headers=headers,
|
|
28
|
+
json=body if body and method in ["POST", "PUT", "PATCH"] else None
|
|
29
|
+
) as response:
|
|
30
|
+
content = await response.text()
|
|
31
|
+
try:
|
|
32
|
+
json_data = await response.json()
|
|
33
|
+
return {
|
|
34
|
+
"status": response.status,
|
|
35
|
+
"headers": dict(response.headers),
|
|
36
|
+
"body": json_data
|
|
37
|
+
}
|
|
38
|
+
except:
|
|
39
|
+
return {
|
|
40
|
+
"status": response.status,
|
|
41
|
+
"headers": dict(response.headers),
|
|
42
|
+
"body": content
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
except Exception as e:
|
|
46
|
+
return {"error": str(e)}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def http_client(
|
|
50
|
+
url: str,
|
|
51
|
+
method: str = "GET",
|
|
52
|
+
headers: Optional[Dict[str, str]] = None,
|
|
53
|
+
body: Optional[Dict[str, Any]] = None
|
|
54
|
+
) -> Dict[str, Any]:
|
|
55
|
+
import asyncio
|
|
56
|
+
tool = HTTPClientTool()
|
|
57
|
+
return asyncio.run(tool.execute(url, method, headers, body))
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import aiohttp
|
|
2
|
+
from typing import Dict, Any, Optional
|
|
3
|
+
from neuroagent.tools.base import Tool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WebSearchTool(Tool):
|
|
7
|
+
def __init__(self, api_key: Optional[str] = None):
|
|
8
|
+
super().__init__(
|
|
9
|
+
name="web_search",
|
|
10
|
+
description="Search the web for information. Input: query string. Output: search results."
|
|
11
|
+
)
|
|
12
|
+
self.api_key = api_key
|
|
13
|
+
|
|
14
|
+
async def execute(self, query: str, num_results: int = 5) -> Dict[str, Any]:
|
|
15
|
+
try:
|
|
16
|
+
import os
|
|
17
|
+
search_api = os.getenv("SEARCH_API", "ddg")
|
|
18
|
+
|
|
19
|
+
if search_api == "ddg":
|
|
20
|
+
url = "https://api.duckduckgo.com/"
|
|
21
|
+
params = {
|
|
22
|
+
"q": query,
|
|
23
|
+
"format": "json",
|
|
24
|
+
"no_html": 1,
|
|
25
|
+
"skip_disambig": 1
|
|
26
|
+
}
|
|
27
|
+
async with aiohttp.ClientSession() as session:
|
|
28
|
+
async with session.get(url, params=params) as response:
|
|
29
|
+
data = await response.json()
|
|
30
|
+
results = []
|
|
31
|
+
for item in data.get("RelatedTopics", [])[:num_results]:
|
|
32
|
+
if "Text" in item:
|
|
33
|
+
results.append({
|
|
34
|
+
"title": item.get("Text", "").split(" - ")[0] if " - " in item.get("Text", "") else item.get("Text", ""),
|
|
35
|
+
"url": item.get("URL", ""),
|
|
36
|
+
"snippet": item.get("Text", "")
|
|
37
|
+
})
|
|
38
|
+
return {"results": results, "query": query}
|
|
39
|
+
else:
|
|
40
|
+
return {"error": "Search API not configured"}
|
|
41
|
+
except Exception as e:
|
|
42
|
+
return {"error": str(e)}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def web_search(query: str, num_results: int = 5) -> Dict[str, Any]:
|
|
46
|
+
import asyncio
|
|
47
|
+
tool = WebSearchTool()
|
|
48
|
+
return asyncio.run(tool.execute(query, num_results))
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
load_dotenv()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_env(key: str, default: Optional[str] = None) -> Optional[str]:
|
|
10
|
+
return os.getenv(key, default)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def require_env(key: str) -> str:
|
|
14
|
+
value = os.getenv(key)
|
|
15
|
+
if not value:
|
|
16
|
+
raise EnvironmentError(f"Required environment variable '{key}' is not set")
|
|
17
|
+
return value
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def format_response(content: str, max_length: int = 2000) -> str:
|
|
21
|
+
if len(content) <= max_length:
|
|
22
|
+
return content
|
|
23
|
+
return content[:max_length] + "..."
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def parse_json_safe(text: str):
|
|
27
|
+
import json
|
|
28
|
+
try:
|
|
29
|
+
return json.loads(text)
|
|
30
|
+
except json.JSONDecodeError:
|
|
31
|
+
return None
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "neuroagent",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "NeuroAgent - Build intelligent AI agents in minutes. A modern framework for creating AI agents with tools, memory, and multi-agent teams.",
|
|
5
|
+
"private": false,
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"src",
|
|
12
|
+
"neuroagent",
|
|
13
|
+
"web_example",
|
|
14
|
+
"server.js",
|
|
15
|
+
"setup.py",
|
|
16
|
+
"requirements.txt",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"package.json"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "node scripts/build.js",
|
|
23
|
+
"prepublishOnly": "npm run build",
|
|
24
|
+
"start-server": "node server.js",
|
|
25
|
+
"install-deps": "pip install -r requirements.txt",
|
|
26
|
+
"postinstall": "echo 'To install Python dependencies, run: pip install -r requirements.txt'"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/neuroagent/neuroagent.git"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"ai",
|
|
34
|
+
"agent",
|
|
35
|
+
"framework",
|
|
36
|
+
"gpt",
|
|
37
|
+
"openai",
|
|
38
|
+
"llm",
|
|
39
|
+
"chatbot",
|
|
40
|
+
"widget",
|
|
41
|
+
"chat",
|
|
42
|
+
"multi-agent",
|
|
43
|
+
"autogpt",
|
|
44
|
+
"crewai",
|
|
45
|
+
"langchain"
|
|
46
|
+
],
|
|
47
|
+
"author": "NeuroAgent Team",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/neuroagent/neuroagent/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://neuroagent.ai",
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=14.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/requirements.txt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
fastapi>=0.104.0
|
|
2
|
+
uvicorn>=0.24.0
|
|
3
|
+
pydantic>=2.5.0
|
|
4
|
+
openai>=1.3.0
|
|
5
|
+
anthropic>=0.18.0
|
|
6
|
+
python-dotenv>=1.0.0
|
|
7
|
+
aiohttp>=3.9.0
|
|
8
|
+
websockets>=12.0
|
|
9
|
+
numpy>=1.24.0
|
|
10
|
+
scikit-learn>=1.3.0
|
|
11
|
+
chromadb>=0.4.0
|
|
12
|
+
tiktoken>=0.5.0
|
|
13
|
+
rich>=13.7.0
|
|
14
|
+
click>=8.1.0
|
|
15
|
+
httpx>=0.25.0
|
package/setup.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="neuroagent",
|
|
5
|
+
version="0.2.0",
|
|
6
|
+
description="Modern AI Agent Framework - Create intelligent AI agents with few lines of code",
|
|
7
|
+
long_description=open("README.md", encoding="utf-8").read(),
|
|
8
|
+
long_description_content_type="text/markdown",
|
|
9
|
+
author="NeuroAgent Team",
|
|
10
|
+
author_email="team@neuroagent.ai",
|
|
11
|
+
url="https://github.com/neuroagent/neuroagent",
|
|
12
|
+
project_urls={
|
|
13
|
+
"Bug Tracker": "https://github.com/neuroagent/neuroagent/issues",
|
|
14
|
+
"Documentation": "https://docs.neuroagent.ai",
|
|
15
|
+
"Source Code": "https://github.com/neuroagent/neuroagent",
|
|
16
|
+
},
|
|
17
|
+
packages=find_packages(exclude=["examples", "tests"]),
|
|
18
|
+
include_package_data=True,
|
|
19
|
+
install_requires=[
|
|
20
|
+
"fastapi>=0.104.0",
|
|
21
|
+
"uvicorn>=0.24.0",
|
|
22
|
+
"pydantic>=2.5.0",
|
|
23
|
+
"openai>=1.3.0",
|
|
24
|
+
"anthropic>=0.18.0",
|
|
25
|
+
"python-dotenv>=1.0.0",
|
|
26
|
+
"aiohttp>=3.9.0",
|
|
27
|
+
"websockets>=12.0",
|
|
28
|
+
"numpy>=1.24.0",
|
|
29
|
+
"rich>=13.7.0",
|
|
30
|
+
"click>=8.1.0",
|
|
31
|
+
"httpx>=0.25.0",
|
|
32
|
+
],
|
|
33
|
+
extras_require={
|
|
34
|
+
"dev": [
|
|
35
|
+
"pytest>=7.4.0",
|
|
36
|
+
"pytest-asyncio>=0.21.0",
|
|
37
|
+
"pytest-cov>=4.1.0",
|
|
38
|
+
"black>=23.0.0",
|
|
39
|
+
"ruff>=0.1.0",
|
|
40
|
+
"mypy>=1.5.0",
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
entry_points={
|
|
44
|
+
"console_scripts": [
|
|
45
|
+
"neuroagent=neuroagent.cli.neuroagent_cli:main",
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
python_requires=">=3.10",
|
|
49
|
+
classifiers=[
|
|
50
|
+
"Development Status :: 3 - Alpha",
|
|
51
|
+
"Intended Audience :: Developers",
|
|
52
|
+
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
53
|
+
"License :: OSI Approved :: MIT License",
|
|
54
|
+
"Programming Language :: Python :: 3",
|
|
55
|
+
"Programming Language :: Python :: 3.10",
|
|
56
|
+
"Programming Language :: Python :: 3.11",
|
|
57
|
+
"Programming Language :: Python :: 3.12",
|
|
58
|
+
"Operating System :: OS Independent",
|
|
59
|
+
],
|
|
60
|
+
keywords="ai agent gpt openai llm chatbot multi-agent",
|
|
61
|
+
)
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface NeuroAgentConfig {
|
|
2
|
+
apiUrl?: string;
|
|
3
|
+
agent?: string;
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
theme?: 'light' | 'dark';
|
|
6
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
7
|
+
title?: string;
|
|
8
|
+
welcomeMessage?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ChatResponse {
|
|
12
|
+
response: string;
|
|
13
|
+
agent: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AgentList {
|
|
17
|
+
agents: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface AgentRequest {
|
|
21
|
+
name: string;
|
|
22
|
+
goal: string;
|
|
23
|
+
model?: string;
|
|
24
|
+
apiKey?: string;
|
|
25
|
+
enablePlanning?: boolean;
|
|
26
|
+
tools?: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export declare class NeuroAgentClient {
|
|
30
|
+
constructor(config: NeuroAgentConfig);
|
|
31
|
+
chat(message: string): Promise<ChatResponse>;
|
|
32
|
+
run(task: string): Promise<ChatResponse>;
|
|
33
|
+
createAgent(config: AgentRequest): Promise<any>;
|
|
34
|
+
listAgents(): Promise<AgentList>;
|
|
35
|
+
onWebSocket(event: 'open' | 'message' | 'error' | 'close', callback: (data?: any) => void): WebSocket;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export declare class NeuroAgentWidget {
|
|
39
|
+
constructor(config: NeuroAgentConfig);
|
|
40
|
+
open(): void;
|
|
41
|
+
close(): void;
|
|
42
|
+
toggle(): void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface NeuroAgentInit {
|
|
46
|
+
init(config: NeuroAgentConfig): NeuroAgentWidget;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
declare const NeuroAgent: {
|
|
50
|
+
init(config: NeuroAgentConfig): NeuroAgentWidget;
|
|
51
|
+
Client: typeof NeuroAgentClient;
|
|
52
|
+
Widget: typeof NeuroAgentWidget;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default NeuroAgent;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuroAgent - Modern AI Agent Framework
|
|
3
|
+
* JavaScript/TypeScript Client
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const API_URL = 'http://localhost:8000';
|
|
7
|
+
|
|
8
|
+
class NeuroAgentClient {
|
|
9
|
+
constructor(config = {}) {
|
|
10
|
+
this.apiUrl = config.apiUrl || API_URL;
|
|
11
|
+
this.agent = config.agent || 'default';
|
|
12
|
+
this.apiKey = config.apiKey || null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async request(endpoint, data) {
|
|
16
|
+
const headers = {
|
|
17
|
+
'Content-Type': 'application/json'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
if (this.apiKey) {
|
|
21
|
+
headers['Authorization'] = `Bearer ${this.apiKey}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const response = await fetch(`${this.apiUrl}${endpoint}`, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers,
|
|
27
|
+
body: JSON.stringify({
|
|
28
|
+
agent: this.agent,
|
|
29
|
+
...data
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return response.json();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async chat(message) {
|
|
37
|
+
return this.request('/agent/chat', { message });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async run(task) {
|
|
41
|
+
return this.request('/agent/run', { message: task });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async createAgent(config) {
|
|
45
|
+
const response = await fetch(`${this.apiUrl}/agents`, {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers: { 'Content-Type': 'application/json' },
|
|
48
|
+
body: JSON.stringify(config)
|
|
49
|
+
});
|
|
50
|
+
return response.json();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async listAgents() {
|
|
54
|
+
const response = await fetch(`${this.apiUrl}/agents`);
|
|
55
|
+
return response.json();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
onWebSocket(event, callback) {
|
|
59
|
+
const ws = new WebSocket(`${this.apiUrl.replace('http', 'ws')}/ws/${this.agent}`);
|
|
60
|
+
|
|
61
|
+
ws.onopen = () => {
|
|
62
|
+
if (event === 'open') callback();
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
ws.onmessage = (e) => {
|
|
66
|
+
const data = JSON.parse(e.data);
|
|
67
|
+
if (event === 'message') callback(data);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
ws.onerror = (error) => {
|
|
71
|
+
if (event === 'error') callback(error);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
ws.onclose = () => {
|
|
75
|
+
if (event === 'close') callback();
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return ws;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
class NeuroAgentWidget {
|
|
83
|
+
constructor(config) {
|
|
84
|
+
this.client = new NeuroAgentClient(config);
|
|
85
|
+
this.config = {
|
|
86
|
+
theme: config.theme || 'dark',
|
|
87
|
+
position: config.position || 'bottom-right',
|
|
88
|
+
title: config.title || 'AI Assistant',
|
|
89
|
+
welcomeMessage: config.welcomeMessage || 'Hello! How can I help you?',
|
|
90
|
+
...config
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
this.isOpen = false;
|
|
94
|
+
this.init();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
init() {
|
|
98
|
+
this.createStyles();
|
|
99
|
+
this.createWidget();
|
|
100
|
+
this.createChat();
|
|
101
|
+
this.bindEvents();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
createStyles() {
|
|
105
|
+
if (document.getElementById('neuroagent-styles')) return;
|
|
106
|
+
|
|
107
|
+
const styles = document.createElement('style');
|
|
108
|
+
styles.id = 'neuroagent-styles';
|
|
109
|
+
styles.textContent = `
|
|
110
|
+
.na-widget { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; position: fixed; z-index: 999999; }
|
|
111
|
+
.na-widget-btn { width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border: none; cursor: pointer; box-shadow: 0 4px 15px rgba(102,126,234,0.4); display: flex; align-items: center; justify-content: center; transition: transform 0.3s; }
|
|
112
|
+
.na-widget-btn:hover { transform: scale(1.1); }
|
|
113
|
+
.na-widget-btn svg { width: 30px; height: 30px; fill: white; }
|
|
114
|
+
.na-chat { position: fixed; width: 380px; height: 500px; background: white; border-radius: 16px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); display: none; flex-direction: column; overflow: hidden; }
|
|
115
|
+
.na-chat.open { display: flex; }
|
|
116
|
+
.na-chat-header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 16px; display: flex; align-items: center; justify-content: space-between; }
|
|
117
|
+
.na-chat-title { font-weight: 600; font-size: 16px; }
|
|
118
|
+
.na-chat-close { background: none; border: none; color: white; cursor: pointer; font-size: 20px; }
|
|
119
|
+
.na-messages { flex: 1; padding: 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; }
|
|
120
|
+
.na-msg { max-width: 80%; padding: 12px 16px; border-radius: 16px; font-size: 14px; line-height: 1.5; }
|
|
121
|
+
.na-msg.user { align-self: flex-end; background: #667eea; color: white; border-bottom-right-radius: 4px; }
|
|
122
|
+
.na-msg.assistant { align-self: flex-start; background: #f0f0f0; color: #333; border-bottom-left-radius: 4px; }
|
|
123
|
+
.na-msg.thinking { align-self: flex-start; background: #f0f0f0; color: #666; font-style: italic; }
|
|
124
|
+
.na-input-area { padding: 16px; border-top: 1px solid #eee; display: flex; gap: 8px; }
|
|
125
|
+
.na-input-area input { flex: 1; padding: 12px 16px; border: 1px solid #ddd; border-radius: 24px; outline: none; font-size: 14px; }
|
|
126
|
+
.na-input-area input:focus { border-color: #667eea; }
|
|
127
|
+
.na-input-area button { background: #667eea; color: white; border: none; padding: 12px 20px; border-radius: 24px; cursor: pointer; font-size: 14px; font-weight: 500; }
|
|
128
|
+
.na-input-area button:disabled { background: #ccc; cursor: not-allowed; }
|
|
129
|
+
.na-pos-bottom-right { bottom: 20px; right: 20px; }
|
|
130
|
+
.na-pos-bottom-left { bottom: 20px; left: 20px; }
|
|
131
|
+
.na-pos-top-right { top: 20px; right: 20px; }
|
|
132
|
+
.na-pos-top-left { top: 20px; left: 20px; }
|
|
133
|
+
.na-chat.na-pos-bottom-right, .na-chat.na-pos-bottom-left { bottom: 90px; }
|
|
134
|
+
.na-chat.na-pos-top-right, .na-chat.na-pos-top-left { top: 90px; }
|
|
135
|
+
.na-chat.na-pos-bottom-right, .na-chat.na-pos-top-right { right: 20px; }
|
|
136
|
+
.na-chat.na-pos-bottom-left, .na-chat.na-pos-top-left { left: 20px; }
|
|
137
|
+
`;
|
|
138
|
+
document.head.appendChild(styles);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
createWidget() {
|
|
142
|
+
this.widget = document.createElement('div');
|
|
143
|
+
this.widget.className = `na-widget na-pos-${this.config.position}`;
|
|
144
|
+
this.widget.innerHTML = `
|
|
145
|
+
<button class="na-widget-btn" title="${this.config.title}">
|
|
146
|
+
<svg viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z"/></svg>
|
|
147
|
+
</button>
|
|
148
|
+
`;
|
|
149
|
+
document.body.appendChild(this.widget);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
createChat() {
|
|
153
|
+
this.chat = document.createElement('div');
|
|
154
|
+
this.chat.className = `na-chat na-pos-${this.config.position}`;
|
|
155
|
+
this.chat.innerHTML = `
|
|
156
|
+
<div class="na-chat-header">
|
|
157
|
+
<span class="na-chat-title">${this.config.title}</span>
|
|
158
|
+
<button class="na-chat-close">×</button>
|
|
159
|
+
</div>
|
|
160
|
+
<div class="na-messages"></div>
|
|
161
|
+
<div class="na-input-area">
|
|
162
|
+
<input type="text" placeholder="Type a message..." />
|
|
163
|
+
<button>Send</button>
|
|
164
|
+
</div>
|
|
165
|
+
`;
|
|
166
|
+
document.body.appendChild(this.chat);
|
|
167
|
+
this.messagesEl = this.chat.querySelector('.na-messages');
|
|
168
|
+
this.inputEl = this.chat.querySelector('input');
|
|
169
|
+
this.sendBtn = this.chat.querySelector('button');
|
|
170
|
+
this.addMessage(this.config.welcomeMessage, 'assistant');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
bindEvents() {
|
|
174
|
+
this.widget.querySelector('.na-widget-btn').addEventListener('click', () => this.toggle());
|
|
175
|
+
this.chat.querySelector('.na-chat-close').addEventListener('click', () => this.close());
|
|
176
|
+
this.sendBtn.addEventListener('click', () => this.send());
|
|
177
|
+
this.inputEl.addEventListener('keypress', (e) => { if (e.key === 'Enter') this.send(); });
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
toggle() { this.isOpen ? this.close() : this.open(); }
|
|
181
|
+
open() { this.isOpen = true; this.chat.classList.add('open'); this.inputEl.focus(); }
|
|
182
|
+
close() { this.isOpen = false; this.chat.classList.remove('open'); }
|
|
183
|
+
|
|
184
|
+
addMessage(content, type = 'assistant') {
|
|
185
|
+
const msg = document.createElement('div');
|
|
186
|
+
msg.className = `na-msg ${type}`;
|
|
187
|
+
msg.textContent = content;
|
|
188
|
+
this.messagesEl.appendChild(msg);
|
|
189
|
+
this.messagesEl.scrollTop = this.messagesEl.scrollHeight;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async send() {
|
|
193
|
+
const msg = this.inputEl.value.trim();
|
|
194
|
+
if (!msg) return;
|
|
195
|
+
|
|
196
|
+
this.inputEl.value = '';
|
|
197
|
+
this.addMessage(msg, 'user');
|
|
198
|
+
this.sendBtn.disabled = true;
|
|
199
|
+
this.addMessage('Thinking...', 'thinking');
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
const response = await this.client.chat(msg);
|
|
203
|
+
this.messagesEl.lastElementChild?.remove();
|
|
204
|
+
this.addMessage(response.response || 'No response', 'assistant');
|
|
205
|
+
} catch (error) {
|
|
206
|
+
this.messagesEl.lastElementChild?.remove();
|
|
207
|
+
this.addMessage('Error connecting to server', 'assistant');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
this.sendBtn.disabled = false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = { NeuroAgentClient, NeuroAgentWidget };
|
|
215
|
+
module.exports.default = { NeuroAgentClient, NeuroAgentWidget };
|