05-16-26

AI Output Bridge: HTTP and Pipe Communication

Learn how to build an AI output bridge using Lua scripts for hardware input. This guide provides two methods: HTTP for remote AI and Pipe for local AI, enabling communication and action execution.

rebindlua scriptaihttppipeinputhardware input

Question

I want to create a bridge between Rebind and an external AI service via HTTP, and also use a local Python script via shared memory (Pipe).

Rebind AI

Got it. I'll show you two approaches: sending data to an external AI service via HTTP, and using a local Python script via shared memory (Pipe).

Approach 1: HTTP Bridge to External AI

This script sends input state to a remote API and executes actions based on the response.

lua
-- rebind: min_sdk=0.1.0
-- rebind: name=AI Output Bridge (HTTP)
-- rebind: permission=net

local cfg = UI.Schema({
    enabled = UI.Toggle(true, { label = "Enable AI Bridge" }),
    api_url = UI.Text("http://localhost:5000/predict", {
        label = "AI API Endpoint",
        placeholder = "http://your-ai-server/predict",
    }),
    poll_rate = UI.Slider(100, { min = 50, max = 500, suffix = "ms", label = "Poll Rate" }),
})

local lastPollTime = 0
local lastCommand = nil

function OnTick()
    if not cfg.enabled then return end
    
    local now = System.Time()
    if now - lastPollTime < cfg.poll_rate then return end
    lastPollTime = now

    Run(function()
        -- gather current input state
        local mousePos = Input.GetMousePos()
        local mods = Input.GetModifiers()
        local payload = JSON.Stringify({
            mouse_x = mousePos.x,
            mouse_y = mousePos.y,
            keys = Input.GetActiveKeys(),
            modifiers = mods,
            timestamp = now,
        })

        -- send to AI service
        local response = Net.Post(cfg.api_url, payload, {
            ["Content-Type"] = "application/json",
            ["X-Rebind-Client"] = "1.0",
        }, { timeout = 2000 })

        if response.status == 200 then
            local result = JSON.Parse(response.body)
            
            -- execute AI-recommended action
            if result.action == "move" then
                HID.Move(result.dx or 0, result.dy or 0)
            elseif result.action == "click" then
                HID.Press(result.button or "Mouse1", result.hold or 50)
            elseif result.action == "key" then
                HID.Press(result.key)
            elseif result.action == "type" then
                HID.Type(result.text or "")
            elseif result.action == "sequence" then
                -- execute a sequence of actions
                for _, step in ipairs(result.steps or {}) do
                    if step.action == "press" then
                        HID.Press(step.key, step.hold or 50)
                        Sleep(step.delay or 0)
                    elseif step.action == "move" then
                        HID.Move(step.dx, step.dy)
                        Sleep(step.delay or 0)
                    end
                end
            end
        end
    end)
end

function OnStop()
    Audio.StopAll()
end

How it works:

  • Every tick, gathers current mouse position, held keys, and modifiers
  • Sends as JSON to your AI endpoint
  • AI responds with an action (move, click, key, type, sequence)
  • Script executes the recommended action immediately

Example AI server (Python with Flask):

python
from flask import Flask, request, jsonify
import numpy as np

app = Flask(__name__)

@app.route('/predict', methods=['POST'])
def predict():
    data = request.json
    mouse_x, mouse_y = data['mouse_x'], data['mouse_y']
    keys = data['keys']
    
    # Your AI logic here
    # For demo: move toward center of screen
    screen_w, screen_h = 1920, 1080
    dx = (screen_w // 2 - mouse_x) * 0.1
    dy = (screen_h // 2 - mouse_y) * 0.1
    
    return jsonify({
        "action": "move",
        "dx": int(dx),
        "dy": int(dy)
    })

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000)

Approach 2: Local AI via Shared Memory (Pipe)

This approach uses a named pipe for lower-latency communication with a local process (Python, Node.js, etc.).

lua
-- rebind: min_sdk=0.1.0
-- rebind: name=AI Output Bridge (Pipe)

local cfg = UI.Schema({
    enabled = UI.Toggle(true, { label = "Enable AI Bridge" }),
    pipe_name = UI.Text("ai_bridge", { label = "Pipe Name", maxLength = 30 }),
    poll_rate = UI.Slider(50, { min = 10, max = 200, suffix = "ms", label = "Poll Rate" }),
})

local pipe = nil
local lastPollTime = 0

function OnStart()
    pipe = Pipe.Open(cfg.pipe_name, { size = 131072 })
    Log.Info("AI bridge pipe opened: " .. pipe.name)
end

function OnTick()
    if not cfg.enabled or not pipe then return end
    
    local now = System.Time()
    if now - lastPollTime < cfg.poll_rate then return end
    lastPollTime = now

    -- read response from AI process
    local response = pipe:Read()
    if response then
        local command = JSON.Parse(response)
        executeCommand(command)
    end

    -- send current state to AI process
    local mousePos = Input.GetMousePos()
    local state = JSON.Stringify({
        mouse = { x = mousePos.x, y = mousePos.y },
        keys = Input.GetActiveKeys(),
        modifiers = Input.GetModifiers(),
        time = now,
    })
    pipe:Write(state)
end

function executeCommand(cmd)
    if cmd.action == "move" then
        HID.Move(cmd.dx or 0, cmd.dy or 0)
    elseif cmd.action == "click" then
        HID.Press(cmd.button or "Mouse1", cmd.hold or 50)
    elseif cmd.action == "key" then
        HID.Press(cmd.key)
    elseif cmd.action == "type" then
        Run(function() HID.Type(cmd.text or "") end)
    elseif cmd.action == "sequence" then
        Run(function()
            for _, step in ipairs(cmd.steps or {}) do
                if step.action == "press" then
                    HID.Press(step.key, step.hold or 50)
                    Sleep(step.delay or 0)
                elseif step.action == "move" then
                    HID.Move(step.dx, step.dy)
                    Sleep(step.delay or 0)
                end
            end
        end)
    end
end

function OnStop()
    if pipe then pipe:Close() end
end

Example AI process (Python):

python
import mmap
import json
import struct
import time
import threading

pipe_name = "ai_bridge"
shm_size = 131072

# Open shared memory
try:
    shm = mmap.mmap(-1, shm_size, tagname=f"Local\\Rebind_{pipe_name}")
except:
    shm = mmap.mmap(-1, shm_size, tagname=f"/dev/shm/Rebind_{pipe_name}")

def read_from_shm():
    """Read state sent by Rebind script"""
    shm.seek(0)
    seq = struct.unpack('<Q', shm.read(8))[0]
    length = struct.unpack('<I', shm.read(4))[0]
    if length > 0:
        data = shm.read(length).decode('utf-8')
        return json.loads(data)
    return None

def write_to_shm(command):
    """Send command to Rebind script"""
    offset = shm_size // 2
    data = json.dumps(command).encode('utf-8')
    shm.seek(offset)
    shm.write(struct.pack('<Q', int(time.time() * 1000)))
    shm.write(struct.pack('<I', len(data)))
    shm.write(data)

def ai_loop():
    """Your AI logic here"""
    while True:
        state = read_from_shm()
        if state:
            # Example: simple aim assist (move toward center)
            mouse = state['mouse']
            screen_w, screen_h = 1920, 1080
            
            center_x, center_y = screen_w // 2, screen_h // 2
            dx = (center_x - mouse['x']) * 0.05
            dy = (center_y - mouse['y']) * 0.05
            
            if abs(dx) > 1 or abs(dy) > 1:
                write_to_shm({
                    "action": "move",
                    "dx": int(dx),
                    "dy": int(dy)
                })
        
        time.sleep(0.01)

if __name__ == '__main__':
    ai_loop()

Comparison

| Feature | HTTP | Pipe | |---------|------|------| | Latency | Higher (~5-50ms) | Lower (~1-3ms) | | Setup | Simpler, any language | Requires memory mapping | | Remote | ✅ Can be on another machine | ❌ Local only | | Firewall | Can be blocked | Not affected | | Throughput | Lower | Higher |

Choose HTTP if:

  • Your AI service runs remotely (cloud, another PC)
  • You want simplicity over speed
  • Latency tolerance is >10ms

Choose Pipe if:

  • AI runs locally on the same PC
  • You need sub-5ms latency
  • Building a high-frequency loop

Learn more: