Skip to content
This repository was archived by the owner on Nov 26, 2025. It is now read-only.

Latest commit

 

History

History
397 lines (294 loc) · 8.08 KB

File metadata and controls

397 lines (294 loc) · 8.08 KB

Plugins

Rohas supports a powerful plugin system that allows you to extend functionality with custom tools and integrations.

Table of Contents

  1. Plugin Types
  2. Built-in Plugins
  3. Subprocess Plugins
  4. Embedded Plugins
  5. HTTP Plugins
  6. WASM Plugins
  7. Creating Plugins
  8. Plugin Manifest

Plugin Types

Rohas supports several plugin types:

  1. Built-in Plugins - Native Rust plugins (CSV, Excel, PostgreSQL)
  2. Subprocess Plugins - External executables (Python, JavaScript, etc.)
  3. Embedded Plugins - Python/JavaScript embedded in the runtime
  4. HTTP Plugins - Remote plugins via HTTP
  5. WASM Plugins - WebAssembly plugins

Built-in Plugins

Built-in plugins are compiled into Rohas and available by default.

CSV Loader

Load CSV files with type safety:

type SaleDataRecord = record {
    date: string,
    product: string,
    category: string,
    quantity: number,
    price: number,
    region: string,
}

salesData = call csvLoader<[SaleDataRecord]>("examples/sales_data.csv")

for sale in salesData {
    prompt "Analyze sale: {sale.product} - {sale.quantity} units"
}

Excel Loader

Load Excel files:

data = call excelLoader("data.xlsx", "Sheet1")

PostgreSQL

Query PostgreSQL databases:

connectionString = "postgresql://user:password@localhost/dbname"
query = "SELECT * FROM users WHERE age > 18"
users = call postgresQuery(connectionString, query)

Subprocess Plugins

Subprocess plugins run external executables. They're defined in plugin.toml:

name = "calculatorTool"
type = "subprocess"
description = "Calculator tool (Python subprocess)"
version = "1.0.0"
path = "calculatorTool.py"
interpreter = "python3"
args = []

Python Plugin Example

Create plugins/calculator-tool/calculatorTool.py:

import sys
import json

def main():
    if len(sys.argv) < 2:
        print(json.dumps({"error": "Invalid arguments"}))
        sys.exit(1)
    
    operation = sys.argv[1]
    args = [float(x) for x in sys.argv[2:]]
    
    if operation == "add":
        result = sum(args)
    elif operation == "multiply":
        result = 1
        for x in args:
            result *= x
    elif operation == "power":
        result = args[0] ** args[1]
    else:
        result = {"error": "Unknown operation"}
    
    print(json.dumps({"result": result}))

if __name__ == "__main__":
    main()

Use in Rohas:

result1 = call calculatorTool("add", 10, 20)
result2 = call calculatorTool("multiply", 5, 6)
result3 = call calculatorTool("power", 2, 8)

prompt "Calculations: 10 + 20 = {result1}, 5 * 6 = {result2}, 2^8 = {result3}"

JavaScript Plugin Example

Create plugins/weather-tool/weatherTool.js:

const city = process.argv[2];

// Simulate weather API call
const weather = {
    city: city,
    temperature: 72,
    condition: "Sunny",
    humidity: 65
};

console.log(JSON.stringify(weather));

Plugin manifest:

name = "weatherTool"
type = "subprocess"
description = "Weather tool (Node.js subprocess)"
version = "1.0.0"
path = "weatherTool.js"
interpreter = "node"
args = []

Embedded Plugins

Embedded plugins run Python or JavaScript code directly in the Rohas runtime. See EMBEDDED_PLUGINS.md for detailed documentation.

Quick Example

# Embedded Python plugin
result = call calculatorTool("add", 10, 20)

HTTP Plugins

HTTP plugins call remote services:

name = "remoteAPI"
type = "http"
description = "Remote API plugin"
version = "1.0.0"
base_url = "https://api.example.com"
endpoint = "/process"
method = "POST"

WASM Plugins

WASM plugins run WebAssembly code:

name = "wasmPlugin"
type = "wasm"
description = "WASM plugin"
version = "1.0.0"
path = "plugin.wasm"

Creating Plugins

Plugin Directory Structure

plugins/
├── my-plugin/
│   ├── plugin.toml
│   ├── myPlugin.py (or .js, .wasm, etc.)
│   └── README.md (optional)
└── plugins.toml

Plugin Manifest (plugin.toml)

Required fields:

name = "myPlugin"           # Plugin name (used in call statements)
type = "subprocess"         # Plugin type
description = "..."         # Description
version = "1.0.0"          # Version

Type-specific fields:

Subprocess:

path = "script.py"         # Path to script
interpreter = "python3"    # Interpreter command
args = []                  # Additional arguments

HTTP:

base_url = "https://api.example.com"
endpoint = "/endpoint"
method = "POST"
headers = { "Authorization": "Bearer token" }

WASM:

path = "plugin.wasm"

Plugin Communication Protocol

Plugins communicate via JSON:

Input: Arguments are passed as command-line arguments (for subprocess) or JSON (for HTTP/WASM)

Output: Plugins must output JSON to stdout:

{
  "result": "value",
  "error": null
}

Or for errors:

{
  "result": null,
  "error": "Error message"
}

Example: Complete Python Plugin

plugins/my-tool/plugin.toml:

name = "myTool"
type = "subprocess"
description = "My custom tool"
version = "1.0.0"
path = "myTool.py"
interpreter = "python3"
args = []

plugins/my-tool/myTool.py:

import sys
import json

def main():
    try:
        # Get arguments
        args = sys.argv[1:]
        
        # Process arguments
        result = process(args)
        
        # Output JSON
        output = {
            "result": result,
            "error": None
        }
        print(json.dumps(output))
        
    except Exception as e:
        error_output = {
            "result": None,
            "error": str(e)
        }
        print(json.dumps(error_output))
        sys.exit(1)

def process(args):
    # Your plugin logic here
    return {"processed": args}

if __name__ == "__main__":
    main()

Use in Rohas:

result = call myTool("arg1", "arg2", "arg3")
prompt "Result: {result}"

Plugin Manifest (plugins.toml)

The root plugins/plugins.toml file tells Rohas which directories to scan:

# Rohas Plugin Manifest
# All plugins now live in dedicated folders under `plugins/<name>`
# This file simply tells the runtime which directories to scan.

# Scan the current directory (plugins/) for plugin subdirectories
directories = ["."]

Plugin Discovery

Rohas automatically discovers plugins by:

  1. Scanning directories listed in plugins/plugins.toml
  2. Loading plugin.toml from each plugin directory
  3. Registering plugins for use in Rohas scripts

Using Plugins

Calling Plugins

# Simple call
result = call myPlugin(arg1, arg2)

# Using results
data = call csvLoader("data.csv")
processed = call processData(data)
output = call saveData(processed)

Plugin Results

Plugin results are automatically parsed as JSON and available as Rohas values:

weather = call weatherTool("San Francisco")
# weather is a record: { city: "San Francisco", temperature: 72, ... }

temperature = weather.temperature
prompt "Temperature in {weather.city}: {temperature}°F"

Error Handling

result = call myPlugin(arg1, arg2)

if result.error != null {
    prompt "Error: " + result.error
} else {
    prompt "Success: " + result.result
}

Best Practices

  1. Use type annotations - Define expected input/output types
  2. Handle errors gracefully - Always return error information in JSON
  3. Validate inputs - Check arguments before processing
  4. Use descriptive names - Plugin names should be clear and descriptive
  5. Document your plugins - Add README.md files to plugin directories
  6. Version your plugins - Use semantic versioning
  7. Test plugins - Test plugins independently before using in Rohas

Examples

See the plugins/ directory for example plugins:

  • calculator-tool/ - Python subprocess plugin
  • calculator-tool-embedded/ - Embedded Python plugin
  • weather-tool/ - Weather API plugin

See examples/plugin-example.ro and examples/embedded-plugins-example.ro for usage examples.