Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
22919f3
feat(tools): add base Tool interface and Registry
Apr 29, 2025
7d3ebe2
feat(tools): implement file I/O tools with tests
Apr 29, 2025
c6987f6
feat: Initial project setup with core structure and documentation
Apr 29, 2025
86b21ef
feat: Add core engine implementation and parser
Apr 29, 2025
0f261e7
feat: Add LLM integration with OpenAI support
Apr 29, 2025
15da21c
feat: Add math and random number generator tools
Apr 29, 2025
410ea0c
feat: Add example scripts and documentation
Apr 29, 2025
330227a
Update pkg/llm/openai/openai.go
thejhh May 1, 2025
337fab1
docs: add comprehensive project documentation and guidelines
May 1, 2025
903ed5f
refactor(io): split IO tool into separate read and write files
May 1, 2025
d785a67
refactor(io): split io tests into separate files and improve error ha…
May 1, 2025
9000ec7
docs(git): add cursor rule for git commit practices
May 1, 2025
e2d7fee
docs: update development workflow with correct test paths and examples
May 1, 2025
5b457c3
refactor: split io module into separate read and write modules
May 1, 2025
755cc0b
docs: add GitHub Copilot code review instructions
May 1, 2025
ccddeee
feat: add node type system for input/output/error handling
May 1, 2025
bd4f207
refactor: simplify math tool and add documentation
May 1, 2025
9cb73de
docs: add random number generator documentation
May 1, 2025
db95c22
refactor: split I/O tools into separate packages and add documentation
May 1, 2025
7690c83
docs: update I/O tool examples and syntax in main README
May 1, 2025
446b647
style: fix newline in write tool README
May 1, 2025
af8cc11
Removed compiled gendo binary from git
May 2, 2025
86ce412
Added compiled gendo binary and Jetbrains configurations to gitignore
May 2, 2025
e158276
GitHub CoPilot instructions cleaned
May 2, 2025
e6e453f
Moved the code to more logical place
May 2, 2025
4c33c57
Using latest Go 1.24
May 2, 2025
54d346d
docs: add package documentation for core packages
May 2, 2025
bb5d26c
docs: add package documentation for tool implementations
May 2, 2025
114adca
docs: add package documentation for LLM implementations
May 2, 2025
e109944
docs: add package documentation for test files
May 2, 2025
41fb3de
Added thinker script
May 6, 2025
a1b33c4
Update README.md
thejhh May 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .cursor/rules/development-workflow.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description:
globs:
alwaysApply: false
---
5 changes: 5 additions & 0 deletions .cursor/rules/llm-integration.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description:
globs:
alwaysApply: false
---
5 changes: 5 additions & 0 deletions .cursor/rules/math-tool.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description:
globs:
alwaysApply: false
---
5 changes: 5 additions & 0 deletions .cursor/rules/project-structure.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description:
globs:
alwaysApply: false
---
5 changes: 5 additions & 0 deletions .cursor/rules/testing-requirements.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description:
globs:
alwaysApply: false
---
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2025 HyperifyIO
Copyright (c) 2025 Jaakko Heusala <jheusala@iki.fi>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
55 changes: 55 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
.PHONY: all build test bench clean

# Default target
all: build

# Build the project
build:
@echo "Building..."
go build -o gendo ./cmd/gendo

# Run all tests
test:
@echo "Running tests..."
go test -v ./...

# Run benchmarks
bench:
@echo "Running benchmarks..."
go test -bench=. -benchmem ./...

# Run tests with coverage
coverage:
@echo "Running tests with coverage..."
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

# Clean build artifacts
clean:
@echo "Cleaning..."
rm -f gendo
rm -f coverage.out

# Install dependencies
deps:
@echo "Installing dependencies..."
go mod download
go mod tidy

# Run linter
lint:
@echo "Running linter..."
golangci-lint run

# Help target
help:
@echo "Available targets:"
@echo " all - Build the project (default)"
@echo " build - Build the project"
@echo " test - Run all tests"
@echo " bench - Run benchmarks"
@echo " coverage - Run tests with coverage report"
@echo " clean - Remove build artifacts"
@echo " deps - Install dependencies"
@echo " lint - Run linter"
@echo " help - Show this help message"
167 changes: 165 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,165 @@
# gendo
Gendo Programming Language
# Gendo Language Specification v0.2

## 1. Introduction

Gendo is a minimalist, prompt-based programming language designed for live, incremental code generation and execution via small, local AI models. Programs consist of self-contained **nodes**—each defining behavior or invoking AI prompts—that pass plain-text streams to each other, enabling rapid composition of functionality without mutable global state or hidden dependencies.

## 2. Core Concepts

### 2.1 Nodes

- **Definition**: `nodeID : refID refID … [: prompt text]`
- `nodeID`: unique integer identifier
- `refID`s: list of nodeIDs this node can call
- `prompt text` *(optional)*: instructions for the AI when this node is invoked
- **Invocation**: `[errorDest !] [dest <] src input text`
- Routes stdout (`dest`) and stderr (`errorDest`) to designated nodes
- Defaults: stdout→1, stderr→2

### 2.2 Streams

- Nodes exchange plain-text. AI-enabled nodes transform input via their prompt; passthrough nodes output input verbatim.
- Errors are first-class data, buffered and routed like stdout.

### 2.3 Default Handlers

You can set **default** destinations for stdout and stderr across subsequent invocations by writing a line with only the handler syntax. Whitespace may be used to indent purely for readability; it has no semantic effect.

```gendo
# Only redefine stdout default to node 3 (errors still go to node 2)
3 <

# Errors still go to previously set default (node 2)
5 Another input

# You can override the default by specifying both handlers on a command:
# Here, errors→5, stdout→6 for this line only
5 ! 6 < Overridden command text
```

You can individually redefine defaults:

```gendo
# Only redefine stdout default to node 3 (errors still go to node 2)
3 <

# Errors still go to previously set default (node 2)
5 Another input

# You can override the default by specifying it
5 < 6 Second command text
```

The default handlers remain in effect until redefined or the script ends.

## 3. Structured Control Flow

*(Looping and conditionals TBD—let's agree on design here before fleshing out.)*

## 4. Modular Units & Files

*(Modular units, namespaces, and imports TBD—let's agree on design before fleshing this out.)*

## 5. Built-in Utilities

> **Note:** Each tool-backed node requires enabling the corresponding tool in the Gendo runtime configuration. If a tool (e.g., `math`, `rand`, `read`, `write`) is not enabled, attempting to invoke its node will result in an error.


### 5.1 Math

Gendo uses explicit **tool nodes** for arithmetic. If a node’s ref list includes the special `tool` directive, the runtime connects it to the math evaluator.

- **Definition Syntax**: `nodeID : tool : math [config...]`
- `tool` marks a tool-backed node.
- Optional `config` may specify precision or mode (e.g., `float`).

**Example Definition**
```gendo
# Node 50 runs the host math evaluator
50 : tool : math
```

**Example Invocation**
```gendo
# Evaluate an expression
< 50 3 * (2 + 5)
# → 21
```

Tool nodes are sandboxed and only execute their designated operation.

### 5.2 Random

Gendo defines **tool nodes** for randomness. Including `tool` with `rand` uses the host RNG.

- **Definition Syntax**: `nodeID : tool : rand [config...]`
- `config` may specify distribution (`uniform`, `normal`) or bounds.

**Example Definition**
```gendo
# Node 51 runs the host RNG
51 : tool : rand
```

**Example Invocation**
```gendo
# Generate a random integer in [1,100]
< 51 1 100
# → 73 (example)
```

Tool nodes are sandboxed and only execute their designated operation.

### 5.3 I/O & Persistence I/O & Persistence

Gendo also uses **tool nodes** for safe, sandboxed file operations. Include `tool` in the ref list and specify `read` or `write` as the tool name.

- **Definition Syntax**: `nodeID : tool : read|write [filename]`
- `read` nodes take no input arguments and output the contents of the named file.
- `write` nodes accept stdin and save it to the named file, returning a confirmation message.

**Example Definitions**
```gendo
# Node 60 reads "config.json"
60 : tool : read config.json

# Node 61 writes to "results.txt"
61 : tool : write results.txt
```

**Example Invocations**
```gendo
# Load configuration
< 60
# → {"threshold":10}

# Save results
Some computed output text
< 61
# → "Written to results.txt"
```

- Filenames are sandboxed and isolated per program; no arbitrary paths allowed.

## 6. Safety & Concurrency

Gendo emphasizes reliability and performance:

- **Stateless Nodes**: By default, nodes have no hidden state; all side effects occur through explicit tool nodes (e.g., I/O), ensuring predictable behavior.
- **Error Handling**: Errors are treated as first-class data. You choose where to route error messages via the `errorDest !` syntax; unhandled errors by default go to node 2. This allows logging, retries, or feeding errors into AI prompts for recovery.
- **Concurrency and Parallelism**: The runtime can execute independent node invocations in parallel when there are no data dependencies. This lets you leverage multi-core CPUs without adding complex syntax.
- **Sandboxing**: Tool nodes (math, rand, read, write) are isolated from arbitrary host resources. Filesystem and network access occur only through sandboxed APIs, preventing unauthorized operations.

## 7. Data Model

Gendo operates purely on plain text streams. Each node receives a string and returns a string. For structured data (e.g., JSON), simply define your prompts or AI nodes to parse and emit valid JSON. Gendo does not enforce data schemas, offering maximum flexibility.

## 8. Community and Next Steps

Gendo invites developers to build small, focused units that grow at runtime via AI. Its minimal core encourages experimentation:

- **Extensibility**: Community-contributed tools and node libraries can add capabilities (e.g., HTTP, database connectors) without altering the core.
- **Safety**: All extensions must register as explicit tools and respect sandbox rules.
- **Example Library**: Curated sets of nodes for common tasks (e.g., data processing pipelines, chat bots).

*Gendo makes it so.*
31 changes: 31 additions & 0 deletions cmd/gendo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"flag"
"fmt"
"os"

"gendo/internal/gendo"
"gendo/pkg/log"
)

func main() {
verbose := flag.Bool("verbose", false, "Enable verbose logging")
model := flag.String("model", "", "Model to use for LLM (overrides GENDO_MODEL environment variable)")
flag.StringVar(model, "m", "", "Model to use for LLM (shorthand)")
flag.Parse()

args := flag.Args()
if len(args) != 1 {
fmt.Fprintf(os.Stderr, "Usage: %s [-verbose] [-m model] <script>\n", os.Args[0])
os.Exit(1)
}

log.SetVerbose(*verbose)
log.Debug("Verbose logging enabled")

if err := gendo.Run(args[0], *model); err != nil {
log.Error("Failed to run script: %v", err)
os.Exit(1)
}
}
76 changes: 76 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Gendo Script Examples

This directory contains example Gendo scripts demonstrating various features and use cases.

## Configuration

Gendo can be configured using environment variables:

- `OPENAI_API_BASE`: Base URL for the OpenAI API (default: https://api.openai.com/v1)
- For local testing: `OPENAI_API_BASE=http://localhost:18080/v1`
- `OPENAI_API_KEY`: API key for authentication (optional)

## Script Format

Gendo scripts consist of:
1. Node definitions (numbered)
2. Input lines with routing
3. Comments (lines starting with #)

Node types:
- Empty node (`1:`) - Passthrough
- AI node (`1: prompt text`) - Uses AI to process input
- Tool node (`1: tool toolname`) - Uses a specific tool

Routing syntax:
- `< N` - Route output to node N
- `! N` - Route errors to node N

## Examples

### hello.gendo
A simple example showing basic node definitions and AI integration:
- Demonstrates passthrough nodes
- Shows AI-powered text generation
- Basic routing

### calculator.gendo
Demonstrates the math tool with error handling:
- Math operations
- Error routing
- Result formatting
- Multiple node pipeline

### file_processor.gendo
Shows file I/O operations:
- Reading files
- Writing files
- Content processing
- Error handling
- Multi-step processing

### random_story.gendo
Complex example combining multiple features:
- Random number generation
- Multi-stage processing
- AI-powered content generation
- State management between nodes

## Running Examples

To run any example:
```bash
# Using default OpenAI API
./gendo examples/hello.gendo

# Using local server
OPENAI_API_BASE=http://localhost:18080/v1 ./gendo examples/hello.gendo
```

## Error Handling

Gendo will:
- Print error messages to stderr
- Set non-zero exit code on errors
- Route errors to specified error handlers using `! N` syntax
- Continue processing if possible, stop on fatal errors
22 changes: 22 additions & 0 deletions examples/calculator.gendo
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Calculator example using math tool

# Error handler
2: Explain what went wrong with the calculation in simple terms.

# If any following operation fails, it goes to node 2 for error explanation
2!

# Input formatter (from stdin)
0: Extract the mathematical operation from the text. Return only the mathematical expression, removing any natural language. For example: "What is 1 plus 1?" -> "1 + 1", "Calculate 5 times 3" -> "5 * 3", "Divide 10 by 2" -> "10 / 2"

# Result formatter (to stdout)
1: Format the calculation result in a natural language response. For example: If input is "2", respond with "The result is 2."

# Define a math tool for calculations
3: tool math

# Formatted input lines go to math tool
3 < 0

# Math result goes to the output formatter
1 < 3
Loading