Skip to content

Tengu Forge is a small, sharp control panel for running scripts on demand. Point it at your FastAPI backend, browse your scripts, fill in args/env, hit run, and watch the output + history stream back in a clean React UI—no agents, no workflow engine, just API → script → result.

License

Notifications You must be signed in to change notification settings

botwin-tokyo/tengu-forge

Repository files navigation

Tengu Forge

Tengu Forge is a small, sharp control panel for running scripts on demand.

There’s no agent tree, no orchestration maze, no hidden magic. The model is simple:

API call → run a script → return the result.

The React front end gives you a clean dashboard to browse scripts, inspect metadata, run them with arguments/env, and review history. The FastAPI backend handles execution and exposes a minimal, predictable API.


Features

  • 🧰 Script Catalog

    • List all available scripts with names, descriptions, tags, and categories.
    • Supports Python-based scripts today; HTTP “actions” can be treated similarly.
  • ▶️ On-Demand Execution

    • Run a script with structured arguments and optional environment overrides.
    • Capture stdout, stderr, exit code, start time, and duration.
    • Results flow straight into the UI’s output panel.
  • 📜 Run History

    • Per-script run history via GET /scripts/{id}/runs.
    • See previous output, failures, and arguments used.
  • 🌐 HTTP Actions

    • Create and store reusable HTTP actions (method, URL, headers, query params, body).
    • Managed directly from the UI.
  • 🔑 Configurable Backend

    • API URL and API key are set in the top bar of the UI.
    • Values are persisted on disk by the backend (no hard-coded keys).

High-Level Architecture

Frontend (already built):

  • React + TypeScript (Vite, Tailwind, shadcn)
  • Lives under src/
  • Core pieces:
    • useBackendConfig – stores backend URL + API key and connection state.
    • useApi – thin wrapper around the Tengu Forge backend API.
    • Sidebar – lists scripts and lets you select one.
    • ScriptDetails / RunTab / HistoryTab – show script metadata, run form, output, and history.
    • HTTPActionsManager – CRUD for reusable HTTP actions.
    • TopBar – config, connection, and theme toggle.

Backend (FastAPI, Python):

  • Lives under backend/
  • Key modules:
    • backend/app/main.py – FastAPI app, routes, CORS, dependency wiring.
    • backend/app/config.py – load/save API config (URL + key) from backend/config/config.json.
    • backend/app/models.py – Pydantic models for Script, RunResult, HTTPAction, backend config, etc.
    • backend/app/script_registry.py – in-memory registry that describes which scripts exist and how to run them.
    • backend/app/runs_store.py – in-memory run history store (can be swapped for a DB later).
    • backend/app/http_actions_store.py – simple JSON-backed store for HTTP actions.
    • backend/scripts/ – actual executable scripts (e.g. hello_world.py).

Execution is intentionally simple: the backend maps a scriptId to a file/command, shells out with subprocess, and returns the captured result.


API Overview

Current API surface (all paths relative to the configured backend URL).

All endpoints expect the API key in the header:

X-API-Key: YOUR_API_KEY

Health

GET /health

Returns a simple status so the frontend can verify connectivity and auth.

Scripts

GET /scripts

Returns a list of Script objects (id, name, description, type, arguments, tags, etc.).

GET /scripts/{id}/runs

Returns a list of RunResult records for the given script.

POST /scripts/{id}/run
Content-Type: application/json

{
  "arguments": { ... },
  "env": { "KEY": "VALUE", ... }
}

Runs the script and returns a RunResult with stdout/stderr/exit code/duration.

HTTP Actions

GET /http-actions

Returns an array of saved HTTP actions.

POST /http-actions
Content-Type: application/json

{
  "name": "My Action",
  "description": "Optional description",
  "method": "GET",
  "url": "https://example.com",
  "headers": [{ "key": "Authorization", "value": "Bearer ..." }],
  "queryParams": [{ "key": "q", "value": "test" }],
  "body": "{ "example": true }"
}

Creates a new HTTP action and returns it with an id and createdAt.


Project Structure

The core layout (simplified):

tengu-forge/
├─ backend/
│  ├─ app/
│  │  ├─ main.py
│  │  ├─ config.py
│  │  ├─ models.py
│  │  ├─ script_registry.py
│  │  ├─ runs_store.py
│  │  └─ http_actions_store.py
│  ├─ scripts/
│  │  └─ hello_world.py
│  ├─ config/
│  │  └─ config.json        # created on first save from the UI
│  ├─ data/                 # runtime data (e.g. http-actions.json)
│  └─ requirements.txt
├─ src/
│  ├─ hooks/
│  │  ├─ useApi.ts
│  │  └─ useBackendConfig.ts
│  ├─ components/
│  │  ├─ TopBar.tsx
│  │  ├─ Sidebar.tsx
│  │  ├─ ScriptDetails.tsx
│  │  ├─ RunTab.tsx
│  │  ├─ HistoryTab.tsx
│  │  ├─ OutputPanel.tsx
│  │  └─ HTTPActionsManager.tsx
│  ├─ pages/
│  │  └─ Index.tsx
│  └─ types/
│     └─ tengu.ts
└─ README.md

Getting Started

Prerequisites

  • Node.js (LTS)
  • npm or pnpm
  • Python 3.10+
  • Git

Clone the repo:

git clone https://github.com/TianJieHeng/tengu-forge.git
cd tengu-forge

Backend Setup (FastAPI)

Create and activate a virtual environment:

cd backend
python -m venv .venv
source .venv/bin/activate    # Windows: .venv\Scripts\activate

Install dependencies:

pip install -r requirements.txt

Run the backend:

uvicorn backend.app.main:app --reload --host 0.0.0.0 --port 8000

By default the app listens on http://localhost:8000.

Note: The backend expects an API key via X-API-Key. You set and persist this through the UI, which will write it into backend/config/config.json on first save.


Frontend Setup (React + Vite)

From the repo root:

npm install
npm run dev

Vite will print a local URL like http://localhost:5173. Open that in your browser.


Connecting the UI to the Backend

  1. Start the backend (uvicorn ...) and frontend (npm run dev).
  2. Open the frontend in your browser.
  3. In the top bar:
    • Set API URL to http://localhost:8000
    • Set API Key to any value you want (e.g. tengu-dev-key)
  4. Click Save.
  5. Click Connect.

If the health check passes, the connection indicator will show that you’re connected, and the sidebar will populate with scripts (e.g. the Hello World example).


Adding Scripts

Scripts live in backend/scripts/ and are described in backend/app/script_registry.py.

1. Add a Python Script

Example: backend/scripts/hello_world.py

#!/usr/bin/env python3
import argparse
import time

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--name", default="world")
    args = parser.parse_args()

    print(f"Hello, {args.name}! This is Tengu Forge.")
    print(f"Timestamp: {int(time.time())}")

if __name__ == "__main__":
    main()

2. Register the Script

In backend/app/script_registry.py, you register it with an ID and metadata (name, description, arguments, etc.). The frontend reads that via GET /scripts and shows it automatically in the sidebar and script details panel.

From there you can:

  • Select the script in the UI.
  • Fill in arguments via the generated form.
  • Click Run to execute and view the output + history.

Security Notes

  • All API calls require X-API-Key. The key is stored in backend/config/config.json, written from the UI.
  • This is designed for trusted environments (your own Jetson, homelab, dev server).
  • If you expose it over the internet, put it behind a proper reverse proxy with TLS and real auth.

Roadmap / Ideas

  • Optional persistent DB for run history.
  • Per-script timeouts and resource limits.
  • Better HTTP action execution + templating.
  • Role-based restrictions for “dangerous” scripts.

License

Review LICENSE.txt

About

Tengu Forge is a small, sharp control panel for running scripts on demand. Point it at your FastAPI backend, browse your scripts, fill in args/env, hit run, and watch the output + history stream back in a clean React UI—no agents, no workflow engine, just API → script → result.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published