feat: deep-agent canvas, live observability, and multi-environment tooling

Self-hosted platform for building, testing, and shipping LangChain/LangGraph agents. Deep-agent sub-agents on the canvas, a live tracing/observability timeline, auto-provisioned built-in tools with import/export, per-environment tool variables, streamed evaluations, and per-user auth token forwarding.
This commit is contained in:
nihalashetty
2026-07-28 01:49:19 +05:30
commit ae67bff5a3
350 changed files with 58244 additions and 0 deletions
+82
View File
@@ -0,0 +1,82 @@
"""Code-tool (RestrictedPython sandbox) and SQL-tool (read-only) tests."""
from __future__ import annotations
import pytest
from forge.services.runtime import make_runtime_ctx
from forge.tools.code import CodeToolError, execute_code, run_code
from forge.tools.materialize import materialize_tool
from forge.tools.sql import SqlToolError, execute_sql
@pytest.fixture(autouse=True)
def _enable_code_tools(monkeypatch):
# Code tools are OFF by default in prod-safe config (unsandboxed RestrictedPython is not
# an isolation boundary - audit S5); these tests exercise the feature, so opt in.
from forge.config import settings
monkeypatch.setattr(settings, "enable_code_tools", True)
# --- code tool ---
async def test_code_tool_main_returns_value():
cfg = {"name": "adder", "kind": "code", "language": "python",
"source": "def main(a, b):\n return a + b\n",
"args_schema": {"properties": {"a": {"type": "integer"}, "b": {"type": "integer"}}, "required": ["a", "b"]}}
assert await execute_code(cfg, {"a": 2, "b": 5}) == 7
async def test_code_tool_allows_safe_import():
assert await execute_code({"source": "import math\ndef main(x):\n return math.sqrt(x)\n"}, {"x": 9}) == 3.0
async def test_code_tool_blocks_unsafe_import():
with pytest.raises(CodeToolError):
run_code("import os\ndef main():\n return os.getcwd()\n", {})
async def test_code_tool_blocks_dunder_escape():
with pytest.raises(CodeToolError):
run_code("def main():\n return ().__class__.__bases__\n", {})
async def test_code_tool_materializes_as_structured_tool():
cfg = {"name": "upper", "kind": "code",
"source": "def main(s):\n return s.upper()\n",
"args_schema": {"properties": {"s": {"type": "string"}}, "required": ["s"]}}
tool = materialize_tool(cfg, make_runtime_ctx("t", "p"))
assert await tool.ainvoke({"s": "hi"}) == "HI"
# --- sql tool (read-only) ---
async def test_sql_tool_rejects_writes():
cfg = {"name": "q", "kind": "sql", "query": "DELETE FROM users", "connection_url": "sqlite+aiosqlite:///:memory:"}
with pytest.raises(SqlToolError):
await execute_sql(cfg, {}, tenant_id="t", project_id="p")
async def test_sql_tool_rejects_multi_statement():
cfg = {"name": "q", "kind": "sql", "query": "SELECT 1; DROP TABLE users", "connection_url": "sqlite+aiosqlite:///:memory:"}
with pytest.raises(SqlToolError):
await execute_sql(cfg, {}, tenant_id="t", project_id="p")
async def test_sql_tool_reads_rows(tmp_path):
import sqlite3
db = tmp_path / "demo.db"
con = sqlite3.connect(db)
con.executescript("CREATE TABLE t(id INTEGER, name TEXT); INSERT INTO t VALUES (1,'a'),(2,'b');")
con.commit()
con.close()
cfg = {"name": "q", "kind": "sql", "connection_url": f"sqlite+aiosqlite:///{db.as_posix()}",
"query": "SELECT id, name FROM t WHERE id = :id",
"args_schema": {"properties": {"id": {"type": "integer"}}, "required": ["id"]}}
res = await execute_sql(cfg, {"id": 2}, tenant_id="t", project_id="p")
assert res["rows"] == [{"id": 2, "name": "b"}]