Full sync - all projects, memory, configs

This commit is contained in:
2026-03-21 20:27:59 -05:00
parent 2447677d4a
commit b33de10902
395 changed files with 1635300 additions and 459211 deletions

View File

@ -0,0 +1,47 @@
# Tool Forge — Self-Creating Tools System
Agents detect when they need a tool that doesn't exist and write it on the fly.
RAG-backed tool discovery keeps context lean by only surfacing relevant tools.
## Architecture
```
Agent needs capability → search tool registry (RAG) → found? use it : create it → index new tool → execute
```
## Components
- **registry.py** — ChromaDB-backed tool registry with semantic search
- **forge.py** — Tool creation engine (generates Python tools from natural language specs)
- **runner.py** — Safe tool execution sandbox
- **cli.py** — CLI interface: `search`, `create`, `run`, `list`, `describe`
## Usage
```bash
# Search for an existing tool
python3 cli.py search "convert CSV to JSON"
# Create a new tool on the fly
python3 cli.py create "convert CSV to JSON" --desc "Takes a CSV file path, returns JSON array"
# Run a tool
python3 cli.py run csv_to_json --args '{"file_path": "data.csv"}'
# List all tools
python3 cli.py list
# Index existing tools from the tools/ directory
python3 cli.py index-existing
```
## For Agents
```python
from tool_forge import ToolForge
forge = ToolForge()
# Returns matching tools or creates one if none found
tool = forge.ensure_tool("convert CSV to JSON", auto_create=True)
result = tool.run(file_path="data.csv")
```

148
tools/tool-forge/forge.py Normal file
View File

@ -0,0 +1,148 @@
"""
Tool Forge — Creates new Python tools from natural language specifications.
Generates standalone, safe, importable tool modules.
"""
import os
import re
import json
import textwrap
from pathlib import Path
from registry import ToolRegistry, TOOLS_DIR
TOOL_TEMPLATE = '''\
"""
{description}
Auto-generated by Tool Forge.
Parameters: {params_doc}
"""
import json
import sys
{extra_imports}
def run({param_signature}):
"""{description}"""
{body}
def main():
"""CLI entry point."""
import argparse
parser = argparse.ArgumentParser(description="{description}")
{argparse_args}
args = parser.parse_args()
result = run(**vars(args))
if result is not None:
if isinstance(result, (dict, list)):
print(json.dumps(result, indent=2, default=str))
else:
print(result)
if __name__ == "__main__":
main()
'''
class ToolForge:
def __init__(self, registry: ToolRegistry = None):
self.registry = registry or ToolRegistry()
def create_tool(self, name: str, description: str, params: dict = None,
body: str = None, imports: list = None, tags: list = None) -> dict:
"""
Create a new tool and register it.
Args:
name: Tool name (snake_case)
description: What the tool does
params: Dict of {param_name: {"type": str, "desc": str, "default": any}}
body: Python function body (indented 4 spaces). If None, generates a stub.
imports: Extra import lines
tags: Searchable tags
"""
name = re.sub(r'[^a-z0-9_]', '_', name.lower().replace('-', '_').replace(' ', '_'))
name = re.sub(r'_+', '_', name).strip('_')
params = params or {}
tags = tags or []
imports = imports or []
# Build parameter signature
required = {k: v for k, v in params.items() if "default" not in v}
optional = {k: v for k, v in params.items() if "default" in v}
sig_parts = list(required.keys())
for k, v in optional.items():
sig_parts.append(f"{k}={repr(v['default'])}")
param_signature = ", ".join(sig_parts) if sig_parts else ""
# Params doc
params_doc = ", ".join(f"{k} ({v.get('type', 'any')}): {v.get('desc', '')}"
for k, v in params.items()) or "none"
# Argparse args
argparse_lines = []
for k, v in params.items():
type_str = v.get("type", "str")
py_type = {"str": "str", "int": "int", "float": "float", "bool": "bool"}.get(type_str, "str")
if "default" in v:
argparse_lines.append(
f' parser.add_argument("--{k}", type={py_type}, default={repr(v["default"])}, help="{v.get("desc", "")}")')
else:
argparse_lines.append(
f' parser.add_argument("{k}", type={py_type}, help="{v.get("desc", "")}")')
argparse_args = "\n".join(argparse_lines) if argparse_lines else ' pass'
# Body
if not body:
body = f' # TODO: Implement {name}\n raise NotImplementedError("Tool {name} needs implementation")'
extra_imports = "\n".join(f"import {i}" for i in imports)
source = TOOL_TEMPLATE.format(
description=description,
params_doc=params_doc,
param_signature=param_signature,
body=body,
extra_imports=extra_imports,
argparse_args=argparse_args,
)
# Write tool file
tool_path = os.path.join(TOOLS_DIR, f"{name}.py")
Path(tool_path).write_text(source)
os.chmod(tool_path, 0o755)
# Register in RAG
self.registry.register(name, description, tool_path, params, tags + ["auto-created"])
return {
"name": name,
"path": tool_path,
"description": description,
"params": params,
}
def ensure_tool(self, query: str, auto_create: bool = True,
params: dict = None, body: str = None) -> dict:
"""
Search for existing tool; create one if not found and auto_create is True.
Returns tool metadata.
"""
matches = self.registry.search(query, n=3, threshold=0.5)
if matches:
return matches[0]
if not auto_create:
return None
# Derive a name from the query
name = re.sub(r'[^a-z0-9 ]', '', query.lower())
name = '_'.join(name.split()[:5])
return self.create_tool(
name=name,
description=query,
params=params,
body=body,
)

View File

@ -0,0 +1,106 @@
"""
Tool Registry — ChromaDB-backed semantic search over tool catalog.
Keeps agent context lean by only surfacing relevant tools via RAG.
"""
import chromadb
import json
import os
from pathlib import Path
from typing import Optional
DB_PATH = os.path.join(os.path.dirname(__file__), ".chromadb")
TOOLS_DIR = os.path.join(os.path.dirname(__file__), "created_tools")
class ToolRegistry:
def __init__(self, db_path: str = DB_PATH):
self.client = chromadb.PersistentClient(path=db_path)
self.collection = self.client.get_or_create_collection(
name="tool_registry",
metadata={"hnsw:space": "cosine"}
)
os.makedirs(TOOLS_DIR, exist_ok=True)
def register(self, name: str, description: str, source_path: str,
params: dict = None, tags: list = None) -> dict:
"""Register a tool in the semantic index."""
doc = f"{name}: {description}"
if tags:
doc += f" tags: {', '.join(tags)}"
metadata = {
"name": name,
"description": description,
"source_path": source_path,
"params_json": json.dumps(params or {}),
"tags": ",".join(tags or []),
}
self.collection.upsert(
ids=[name],
documents=[doc],
metadatas=[metadata],
)
return metadata
def search(self, query: str, n: int = 5, threshold: float = 0.6) -> list[dict]:
"""Semantic search for tools. Returns matches above threshold."""
results = self.collection.query(
query_texts=[query],
n_results=min(n, max(self.collection.count(), 1)),
)
if not results["ids"][0]:
return []
tools = []
for i, id_ in enumerate(results["ids"][0]):
distance = results["distances"][0][i] if results["distances"] else 1.0
similarity = 1 - distance
if similarity >= threshold:
meta = results["metadatas"][0][i]
meta["similarity"] = round(similarity, 3)
tools.append(meta)
return tools
def get(self, name: str) -> Optional[dict]:
"""Get a specific tool by name."""
try:
result = self.collection.get(ids=[name])
if result["ids"]:
return result["metadatas"][0]
except Exception:
pass
return None
def list_all(self) -> list[dict]:
"""List all registered tools."""
result = self.collection.get()
return result["metadatas"] if result["metadatas"] else []
def delete(self, name: str):
"""Remove a tool from the registry."""
self.collection.delete(ids=[name])
def index_existing_tools(self, tools_dir: str = None) -> int:
"""Index existing Python tools from a directory by extracting docstrings."""
tools_dir = tools_dir or os.path.join(os.path.dirname(__file__), "..")
count = 0
for f in Path(tools_dir).glob("*.py"):
if f.name.startswith("_"):
continue
try:
source = f.read_text()
# Extract first docstring
desc = ""
if '"""' in source:
parts = source.split('"""')
if len(parts) >= 3:
desc = parts[1].strip().split("\n")[0]
if not desc:
desc = f"Tool: {f.stem}"
name = f.stem.replace("-", "_")
self.register(name, desc, str(f.resolve()), tags=["existing"])
count += 1
except Exception:
continue
return count