upward-spiral-research / world-interface

A simulated operating system design for AI Agents to interact with the world
https://truth-terminal-world-interface.vercel.app
MIT License
132 stars 31 forks source link

world interface 0.1

This project simulates a command-line operating system interface, designed to be called by agentic large language models (LLMs). It is exposed as an OpenAI-compatible API and is completely stateless. For an example of an LLM using it: https://dreams.infinitebackrooms.com/AndyAyrey/3Nir1p6x-c

Table of Contents

Features

Getting Started

Make sure you have Node.js installed.

  1. Clone the repository
  2. Install dependencies: npm install
  3. Familarise yourself with the environments and adapters in src/environments. (n.b. some of them require other services to be running which I'm yet to release, sorry!)
  4. Set up environment variables - cp .env.example .env and populate with your keys. Set your WORLD_INTERFACE_KEY to anything you like!
  5. Start the server: npm start

The server will start on port 3000 by default. Prompt it as you would any chatbot.

Usage

Send POST requests to /v1/chat/completions with the following structure:

{
    "messages": [{ "role": "user", "content": "twitter post Hello, world!" }]
}

Include the header Authorization: Bearer WHATEVER_YOU_SET_YOUR_WORLD_INTERFACE_KEY_TO for authentication.

Adding New Environments

To add a new environment:

  1. Create a New Environment File

    Add your environment's JavaScript file in the src/environments/ directory. For example, to add a weather environment:

    const axios = require('axios');
    
    class Weather {
        getCommands() {
            return [
                { name: "current", description: "Get current weather for a location" },
                { name: "forecast", description: "Get weather forecast for a location" },
            ];
        }
    
        async handleCommand(command, messages) {
            const [action, ...params] = command.split(" ");
            const location = params.join(" ");
    
            switch (action.toLowerCase()) {
                case "current":
                    return await this.getCurrentWeather(location);
                case "forecast":
                    return await this.getWeatherForecast(location);
                case "help":
                    return this.help();
                default:
                    return { error: `Unknown action: ${action}` };
            }
        }
    
        async getCurrentWeather(location) {
            try {
                const response = await axios.get(`https://api.weather.com/v3/weather/conditions`, {
                    params: { location, apiKey: process.env.WEATHER_API_KEY },
                });
                return {
                    title: `Current Weather for ${location}`,
                    content: `Temperature: ${response.data.temperature}\nConditions: ${response.data.conditions}`,
                };
            } catch (error) {
                return {
                    title: "Error Fetching Weather",
                    content: error.response ? error.response.data.error : error.message,
                };
            }
        }
    
        async getWeatherForecast(location) {
            try {
                const response = await axios.get(`https://api.weather.com/v3/weather/forecast`, {
                    params: { location, apiKey: process.env.WEATHER_API_KEY },
                });
                return {
                    title: `Weather Forecast for ${location}`,
                    content: `Tomorrow: ${response.data.forecast}`,
                };
            } catch (error) {
                return {
                    title: "Error Fetching Weather Forecast",
                    content: error.response ? error.response.data.error : error.message,
                };
            }
        }
    
        help() {
            return {
                title: "Weather Environment Help",
                content: `Available commands:
        - current <location> - Get current weather for a location
        - forecast <location> - Get weather forecast for a location`,
            };
        }
    }
    
    module.exports = Weather;
  2. Register the New Environment

    Add your new environment to the src/environment-registry.js to make it available for use.

    const Twitter = require('./environments/twitter');
    const Exo = require('./environments/exo');
    const Sydney = require('./environments/sydney');
    const MemeMagic = require('./environments/meme_magic');
    const Search = require('./environments/search');
    const Weather = require('./environments/weather'); // Newly added
    
    const environments = {
        twitter: new Twitter(),
        exo: new Exo(),
        sydney: new Sydney(),
        meme_magic: new MemeMagic(),
        search: new Search(),
        weather: new Weather(), // Registering the new environment
    };
    
    module.exports = {
        getEnvironment: (name) => environments[name],
        getEnvironmentNames: () => Object.keys(environments),
    };

Current Environments

Future Improvements

This is a toy model created to solve my own particular use case so there's looooots of stuff that needs to be added/improved to make it more generally useful as a basis for your own projects. Here's some ideas:

LMK on X @andyayrey if you'd like to share ideas or contribute!

License

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.